swanctl: Document wildcard matching for remote identities master
authorTobias Brunner <tobias@strongswan.org>
Tue, 12 Nov 2019 09:59:38 +0000 (10:59 +0100)
committerTobias Brunner <tobias@strongswan.org>
Tue, 12 Nov 2019 09:59:38 +0000 (10:59 +0100)
134 files changed:
.travis.yml
conf/Makefile.am
conf/format-options.py
conf/options/charon.opt
conf/plugins/drbg.opt [new file with mode: 0644]
conf/plugins/ntru.opt
configure.ac
man/ipsec.conf.5.in
scripts/test.sh
src/frontends/android/app/build.gradle
src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java
src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java
src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java
src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java
src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/CertificateIdentitiesAdapter.java
src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java
src/frontends/android/app/src/main/res/layout/profile_detail_view.xml
src/frontends/android/app/src/main/res/values-de/strings.xml
src/frontends/android/app/src/main/res/values-pl/strings.xml
src/frontends/android/app/src/main/res/values-ru/strings.xml
src/frontends/android/app/src/main/res/values-ua/strings.xml
src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml
src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml
src/frontends/android/app/src/main/res/values/strings.xml
src/frontends/android/build.gradle
src/frontends/android/gradle/wrapper/gradle-wrapper.properties
src/libcharon/config/child_cfg.c
src/libcharon/config/child_cfg.h
src/libcharon/config/ike_cfg.c
src/libcharon/config/ike_cfg.h
src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
src/libcharon/plugins/load_tester/load_tester_config.c
src/libcharon/plugins/smp/smp.c
src/libcharon/plugins/stroke/stroke_list.c
src/libcharon/plugins/vici/vici_query.c
src/libcharon/sa/child_sa.c
src/libcharon/sa/ike_sa.c
src/libcharon/sa/ikev1/tasks/aggressive_mode.c
src/libcharon/sa/ikev1/tasks/main_mode.c
src/libcharon/sa/ikev1/tasks/quick_mode.c
src/libcharon/sa/ikev2/tasks/child_create.c
src/libcharon/sa/ikev2/tasks/ike_delete.c
src/libcharon/sa/ikev2/tasks/ike_init.c
src/libstrongswan/Makefile.am
src/libstrongswan/crypto/crypto_factory.c
src/libstrongswan/crypto/crypto_factory.h
src/libstrongswan/crypto/crypto_tester.c
src/libstrongswan/crypto/crypto_tester.h
src/libstrongswan/crypto/drbgs/drbg.c [new file with mode: 0644]
src/libstrongswan/crypto/drbgs/drbg.h [new file with mode: 0644]
src/libstrongswan/crypto/prf_plus.c
src/libstrongswan/crypto/proposal/proposal.c
src/libstrongswan/crypto/proposal/proposal.h
src/libstrongswan/crypto/rngs/rng_tester.c [new file with mode: 0644]
src/libstrongswan/crypto/rngs/rng_tester.h [new file with mode: 0644]
src/libstrongswan/crypto/transform.c
src/libstrongswan/crypto/transform.h
src/libstrongswan/plugins/drbg/Makefile.am [new file with mode: 0644]
src/libstrongswan/plugins/drbg/drbg_ctr.c [new file with mode: 0644]
src/libstrongswan/plugins/drbg/drbg_ctr.h [new file with mode: 0644]
src/libstrongswan/plugins/drbg/drbg_hmac.c [new file with mode: 0644]
src/libstrongswan/plugins/drbg/drbg_hmac.h [new file with mode: 0644]
src/libstrongswan/plugins/drbg/drbg_plugin.c [new file with mode: 0644]
src/libstrongswan/plugins/drbg/drbg_plugin.h [new file with mode: 0644]
src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
src/libstrongswan/plugins/ntru/Makefile.am
src/libstrongswan/plugins/ntru/ntru_drbg.c [deleted file]
src/libstrongswan/plugins/ntru/ntru_drbg.h [deleted file]
src/libstrongswan/plugins/ntru/ntru_ke.c
src/libstrongswan/plugins/ntru/ntru_private_key.c
src/libstrongswan/plugins/ntru/ntru_private_key.h
src/libstrongswan/plugins/ntru/ntru_public_key.c
src/libstrongswan/plugins/ntru/ntru_public_key.h
src/libstrongswan/plugins/pkcs11/pkcs11_library.c
src/libstrongswan/plugins/plugin_feature.c
src/libstrongswan/plugins/plugin_feature.h
src/libstrongswan/plugins/test_vectors/Makefile.am
src/libstrongswan/plugins/test_vectors/test_vectors.h
src/libstrongswan/plugins/test_vectors/test_vectors/drbg_ctr.c [new file with mode: 0644]
src/libstrongswan/plugins/test_vectors/test_vectors/drbg_hmac.c [new file with mode: 0644]
src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c
src/libstrongswan/plugins/wolfssl/wolfssl_rsa_private_key.c
src/libstrongswan/tests/Makefile.am
src/libstrongswan/tests/suites/test_enum.c
src/libstrongswan/tests/suites/test_mgf1.c
src/libstrongswan/tests/suites/test_ntru.c
src/libstrongswan/tests/suites/test_prf_plus.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_proposal.c
src/libstrongswan/tests/suites/test_rng_tester.c [new file with mode: 0644]
src/libstrongswan/tests/suites/test_test_rng.c [deleted file]
src/libstrongswan/tests/suites/test_utils.c
src/libstrongswan/tests/suites/test_vectors.c
src/libstrongswan/tests/tests.h
src/libstrongswan/tests/utils/test_rng.c [deleted file]
src/libstrongswan/tests/utils/test_rng.h [deleted file]
src/libstrongswan/utils/enum.h
src/libstrongswan/utils/utils/memory.h
src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.c
src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.h
src/libtpmtss/tpm_tss_tss2_names_v2.c
src/swanctl/swanctl.opt
testing/config/kernel/config-5.3 [new file with mode: 0644]
testing/hosts/winnetou/etc/strongswan.conf
testing/testing.conf
testing/tests/ikev1/esp-alg-null/description.txt
testing/tests/ikev1/net2net-ntru-cert/hosts/moon/etc/strongswan.conf
testing/tests/ikev1/net2net-ntru-cert/hosts/sun/etc/strongswan.conf
testing/tests/ikev1/rw-cert/hosts/carol/etc/strongswan.conf
testing/tests/ikev1/rw-cert/hosts/dave/etc/strongswan.conf
testing/tests/ikev1/rw-cert/hosts/moon/etc/strongswan.conf
testing/tests/ikev1/rw-ntru-psk/hosts/carol/etc/strongswan.conf
testing/tests/ikev1/rw-ntru-psk/hosts/dave/etc/strongswan.conf
testing/tests/ikev1/rw-ntru-psk/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/alg-chacha20poly1305/hosts/carol/etc/strongswan.conf
testing/tests/ikev2/alg-chacha20poly1305/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/esp-alg-null/description.txt
testing/tests/ikev2/force-udp-encaps/hosts/sun/etc/ipsec.conf
testing/tests/ikev2/net2net-ntru-bandwidth/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/net2net-ntru-bandwidth/hosts/sun/etc/strongswan.conf
testing/tests/ikev2/net2net-ntru-cert/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/net2net-ntru-cert/hosts/sun/etc/strongswan.conf
testing/tests/ikev2/rw-cert/hosts/carol/etc/strongswan.conf
testing/tests/ikev2/rw-cert/hosts/dave/etc/strongswan.conf
testing/tests/ikev2/rw-cert/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/rw-ntru-bliss/hosts/carol/etc/strongswan.conf
testing/tests/ikev2/rw-ntru-bliss/hosts/dave/etc/strongswan.conf
testing/tests/ikev2/rw-ntru-bliss/hosts/moon/etc/strongswan.conf
testing/tests/ikev2/rw-ntru-psk/hosts/carol/etc/strongswan.conf
testing/tests/ikev2/rw-ntru-psk/hosts/dave/etc/strongswan.conf
testing/tests/ikev2/rw-ntru-psk/hosts/moon/etc/strongswan.conf
testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/strongswan.conf
testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/strongswan.conf
testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/strongswan.conf

index 3a62e2c..7e99731 100644 (file)
@@ -1,7 +1,7 @@
 language: c
 
 sudo: required
-dist: xenial
+dist: bionic
 
 # don't build tags separately
 if: tag IS blank
@@ -50,6 +50,11 @@ matrix:
     - env: TEST=all
     - env: TEST=all
       compiler: clang
+    - env: TEST=all
+      dist: xenial
+    - env: TEST=all
+      dist: xenial
+      compiler: clang
     - env: TEST=all MONOLITHIC=yes
     - env: TEST=all MONOLITHIC=yes
       compiler: clang
@@ -86,7 +91,9 @@ matrix:
     - env: TEST=openssl
     - env: TEST=openssl LEAK_DETECTIVE=yes
     - env: TEST=openssl-1.0
+      dist: xenial
     - env: TEST=openssl-1.0 LEAK_DETECTIVE=yes
+      dist: xenial
     - env: TEST=gcrypt
     - env: TEST=gcrypt LEAK_DETECTIVE=yes
     - env: TEST=apidoc
index 0080a55..1c2b412 100644 (file)
@@ -39,6 +39,7 @@ plugins = \
        plugins/curl.opt \
        plugins/dhcp.opt \
        plugins/dnscert.opt \
+       plugins/drbg.opt \
        plugins/duplicheck.opt \
        plugins/eap-aka.opt \
        plugins/eap-aka-3gpp.opt \
index 592bf67..578ccf2 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright (C) 2014-2017 Tobias Brunner
+# Copyright (C) 2014-2019 Tobias Brunner
 # HSR Hochschule fuer Technik Rapperswil
 #
 # This program is free software; you can redistribute it and/or modify it
@@ -67,7 +67,7 @@ charon.filelog./var/log/daemon\.log {}
 import sys
 import re
 from textwrap import TextWrapper
-from optparse import OptionParser
+from argparse import ArgumentParser
 from functools import cmp_to_key
 
 class ConfigOption:
@@ -344,21 +344,22 @@ class ManFormatter:
                        else:
                                self.__format_option(option)
 
-options = OptionParser(usage = "Usage: %prog [options] file1 file2\n\n"
-                                          "If no filenames are provided the input is read from stdin.")
-options.add_option("-f", "--format", dest="format", type="choice", choices=["conf", "man"],
-                                  help="output format: conf, man [default: %default]", default="conf")
-options.add_option("-r", "--root", dest="root", metavar="NAME",
-                                  help="root section of which options are printed, "
-                                  "if not found everything is printed")
-options.add_option("-n", "--nosort", action="store_false", dest="sort",
-                                  default=True, help="do not sort sections alphabetically")
+args = ArgumentParser()
+args.add_argument('file', nargs='*',
+                                 help="files to process, omit to read input from stdin")
+args.add_argument("-f", "--format", dest="format", choices=["conf", "man"],
+                                 help="output format (default: %(default)s)", default="conf")
+args.add_argument("-r", "--root", dest="root", metavar="NAME",
+                                 help="root section of which options are printed; everything"
+                                 "is printed if not found")
+args.add_argument("-n", "--nosort", action="store_false", dest="sort",
+                                 default=True, help="do not sort sections alphabetically")
 
-(opts, args) = options.parse_args()
+opts = args.parse_args()
 
 parser = Parser(opts.sort)
-if len(args):
-       for filename in args:
+if len(opts.file):
+       for filename in opts.file:
                try:
                        with open(filename, 'r') as file:
                                parser.parse(file)
index d57b393..cc58afd 100644 (file)
@@ -286,8 +286,16 @@ charon.prefer_configured_proposals = yes
        notifies).
 
 charon.prefer_temporary_addrs = no
-       By default public IPv6 addresses are preferred over temporary ones (RFC
-       4941), to make connections more stable. Enable this option to reverse this.
+       Controls whether permanent or temporary IPv6 addresses are used as source,
+       or announced as additional addresses if MOBIKE is used.
+
+       By default, permanent IPv6 source addresses are preferred over temporary
+       ones (RFC 4941), to make connections more stable. Enable this option to
+       reverse this.
+
+       It also affects which IPv6 addresses are announced as additional addresses
+       if MOBIKE is used.  If the option is disabled, only permanent addresses are
+       sent, and only temporary ones if it is enabled.
 
 charon.process_route = yes
        Process RTM_NEWROUTE and RTM_DELROUTE events.
diff --git a/conf/plugins/drbg.opt b/conf/plugins/drbg.opt
new file mode 100644 (file)
index 0000000..2d132a1
--- /dev/null
@@ -0,0 +1,3 @@
+charon.plugins.drbg.max_drbg_requests = 4294967294
+       Number of pseudo-random bit requests from the DRBG before an automatic
+       reseeding occurs.
index 8e1bebd..afed563 100644 (file)
@@ -1,7 +1,3 @@
-charon.plugins.ntru.max_drbg_requests = 4294967294
-       Number of pseudo-random bit requests from the DRBG before an automatic
-       reseeding occurs.
-
 charon.plugins.ntru.parameter_set = optimum
        The following parameter sets are available: **x9_98_speed**,
        **x9_98_bandwidth**, **x9_98_balance** and **optimum**, the last set not
index 6a20ce6..4b0380b 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Copyright (C) 2007-2017 Tobias Brunner
-# Copyright (C) 2006-2017 Andreas Steffen
+# Copyright (C) 2006-2019 Andreas Steffen
 # Copyright (C) 2006-2014 Martin Willi
 # HSR Hochschule fuer Technik Rapperswil
 #
@@ -19,7 +19,7 @@
 #  initialize & set some vars
 # ============================
 
-AC_INIT([strongSwan],[5.8.1])
+AC_INIT([strongSwan],[5.8.2dr1])
 AM_INIT_AUTOMAKE(m4_esyscmd([
        echo tar-ustar
        echo subdir-objects
@@ -132,6 +132,7 @@ ARG_ENABL_SET([chapoly],        [enables the ChaCha20/Poly1305 AEAD plugin.])
 ARG_DISBL_SET([cmac],           [disable CMAC crypto implementation plugin.])
 ARG_ENABL_SET([ctr],            [enables the Counter Mode wrapper crypto plugin.])
 ARG_DISBL_SET([des],            [disable DES/3DES software implementation plugin.])
+ARG_DISBL_SET([drbg],           [disable the NIST Deterministic Random Bit Generator plugin.])
 ARG_DISBL_SET([fips-prf],       [disable FIPS PRF software implementation plugin.])
 ARG_ENABL_SET([gcm],            [enables the GCM AEAD wrapper crypto plugin.])
 ARG_ENABL_SET([gcrypt],         [enables the libgcrypt plugin.])
@@ -1442,6 +1443,7 @@ ADD_PLUGIN([ctr],                  [s charon scripts nm cmd])
 ADD_PLUGIN([ccm],                  [s charon scripts nm cmd])
 ADD_PLUGIN([gcm],                  [s charon scripts nm cmd])
 ADD_PLUGIN([ntru],                 [s charon scripts nm cmd])
+ADD_PLUGIN([drbg],                 [s charon pki scripts nm cmd])
 ADD_PLUGIN([newhope],              [s charon scripts nm cmd])
 ADD_PLUGIN([bliss],                [s charon pki scripts nm cmd])
 ADD_PLUGIN([curl],                 [s charon scepclient pki scripts nm cmd])
@@ -1611,6 +1613,7 @@ AM_CONDITIONAL(USE_AF_ALG, test x$af_alg = xtrue)
 AM_CONDITIONAL(USE_NTRU, test x$ntru = xtrue)
 AM_CONDITIONAL(USE_NEWHOPE, test x$newhope = xtrue)
 AM_CONDITIONAL(USE_BLISS, test x$bliss = xtrue)
+AM_CONDITIONAL(USE_DRBG, test x$drbg = xtrue)
 
 #  charon plugins
 # ----------------
@@ -1887,6 +1890,7 @@ AC_CONFIG_FILES([
        src/libstrongswan/plugins/ccm/Makefile
        src/libstrongswan/plugins/gcm/Makefile
        src/libstrongswan/plugins/af_alg/Makefile
+       src/libstrongswan/plugins/drbg/Makefile
        src/libstrongswan/plugins/ntru/Makefile
        src/libstrongswan/plugins/bliss/Makefile
        src/libstrongswan/plugins/bliss/tests/Makefile
index 2324089..ced1268 100644 (file)
@@ -323,7 +323,7 @@ defines the action to take if the remote peer unexpectedly closes a CHILD_SA
 for meaning of values).
 A
 .B closeaction should not be
-used if the peer uses reauthentication or uniquids checking, as these events
+used if the peer uses reauthentication or uniqueids checking, as these events
 might trigger the defined action when not desired.
 .TP
 .BR compress " = yes | " no
index 833d38a..a0a2895 100755 (executable)
@@ -36,7 +36,7 @@ build_botan()
 
 build_wolfssl()
 {
-       WOLFSSL_REV=v4.1.0-stable
+       WOLFSSL_REV=v4.2.0-stable
        WOLFSSL_DIR=$TRAVIS_BUILD_DIR/../wolfssl
 
        if test -d "$WOLFSSL_DIR"; then
@@ -86,43 +86,6 @@ build_tss2()
        cd -
 }
 
-build_openssl()
-{
-       SSL_REV=1.1.1d
-       SSL_PKG=openssl-$SSL_REV
-       SSL_DIR=$TRAVIS_BUILD_DIR/../$SSL_PKG
-       SSL_SRC=https://www.openssl.org/source/$SSL_PKG.tar.gz
-       SSL_INS=/usr/local/ssl
-       SSL_OPT="shared no-tls no-dtls no-ssl3 no-zlib no-comp no-idea no-psk no-srp
-                        no-stdio no-tests enable-rfc3779 enable-ec_nistp_64_gcc_128
-                        --api=1.1.0"
-
-       if test -d "$SSL_DIR"; then
-               return
-       fi
-
-       echo "$ build_openssl()"
-
-       curl -L $SSL_SRC | tar xz -C $TRAVIS_BUILD_DIR/.. &&
-       cd $SSL_DIR &&
-       ./config --prefix=$SSL_INS --openssldir=$SSL_INS $SSL_OPT &&
-       make -j4 >/dev/null &&
-       sudo make install_sw >/dev/null &&
-       echo $SSL_INS/lib | sudo tee /etc/ld.so.conf.d/openssl-$SSL_REV.conf >/dev/null &&
-       sudo ldconfig || exit $?
-       cd -
-}
-
-use_custom_openssl()
-{
-       CFLAGS="$CFLAGS -I/usr/local/ssl/include"
-       LDFLAGS="$LDFLAGS -L/usr/local/ssl/lib"
-       export LDFLAGS
-       if test "$1" = "deps"; then
-               build_openssl
-       fi
-}
-
 if test -z $TRAVIS_BUILD_DIR; then
        TRAVIS_BUILD_DIR=$PWD
 fi
@@ -144,10 +107,6 @@ openssl*)
        CONFIG="--disable-defaults --enable-pki --enable-openssl --enable-pem"
        export TESTS_PLUGINS="test-vectors pem openssl!"
        DEPS="libssl-dev"
-       if test "$TEST" != "openssl-1.0"; then
-               DEPS=""
-               use_custom_openssl $1
-       fi
        ;;
 gcrypt)
        CONFIG="--disable-defaults --enable-pki --enable-gcrypt --enable-pkcs1"
@@ -197,14 +156,13 @@ all|coverage|sonarcloud)
        DEPS="$DEPS libcurl4-gnutls-dev libsoup2.4-dev libunbound-dev libldns-dev
                  libmysqlclient-dev libsqlite3-dev clearsilver-dev libfcgi-dev
                  libpcsclite-dev libpam0g-dev binutils-dev libunwind8-dev libnm-dev
-                 libjson0-dev iptables-dev python-pip libtspi-dev libsystemd-dev"
+                 libjson-c-dev iptables-dev python-pip libtspi-dev libsystemd-dev"
        PYDEPS="pytest"
        if test "$1" = "deps"; then
                build_botan
                build_wolfssl
                build_tss2
        fi
-       use_custom_openssl $1
        ;;
 win*)
        CONFIG="--disable-defaults --enable-svc --enable-ikev2
@@ -374,6 +332,12 @@ esac
 echo "$ make $TARGET"
 case "$TEST" in
 sonarcloud)
+       # there is an issue with the platform detection that causes sonarqube to
+       # fail on bionic with "ERROR: ld.so: object '...libinterceptor-${PLATFORM}.so'
+       # from LD_PRELOAD cannot be preloaded (cannot open shared object file)"
+       # https://jira.sonarsource.com/browse/CPP-2027
+       BW_PATH=$(dirname $(which build-wrapper-linux-x86-64))
+       cp $BW_PATH/libinterceptor-x86_64.so $BW_PATH/libinterceptor-haswell.so
        # without target, coverage is currently not supported anyway because
        # sonarqube only supports gcov, not lcov
        build-wrapper-linux-x86-64 --out-dir bw-output make -j4 || exit $?
index b2d8c0b..b3a17f3 100644 (file)
@@ -7,8 +7,8 @@ android {
         applicationId "org.strongswan.android"
         minSdkVersion 15
         targetSdkVersion 28
-        versionCode 64
-        versionName "2.1.1"
+        versionCode 68
+        versionName "2.2.0"
     }
 
     sourceSets.main {
@@ -46,8 +46,8 @@ android {
 }
 
 dependencies {
-    implementation 'androidx.appcompat:appcompat:1.0.0'
-    implementation 'androidx.preference:preference:1.0.0'
+    implementation 'androidx.appcompat:appcompat:1.1.0'
+    implementation 'androidx.preference:preference:1.1.0'
     implementation 'androidx.legacy:legacy-support-v4:1.0.0'
     implementation 'com.google.android.material:material:1.0.0'
     testImplementation 'junit:junit:4.12'
index abe6293..e283cd5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2015 Tobias Brunner
+ * Copyright (C) 2012-2019 Tobias Brunner
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -20,7 +20,10 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
+import android.net.Network;
 import android.net.NetworkInfo;
+import android.net.NetworkRequest;
+import android.os.Build;
 
 import java.util.LinkedList;
 
@@ -28,12 +31,45 @@ public class NetworkManager extends BroadcastReceiver implements Runnable
 {
        private final Context mContext;
        private volatile boolean mRegistered;
+       private ConnectivityManager.NetworkCallback mCallback;
        private Thread mEventNotifier;
+       private int mConnectedNetworks = 0;
        private LinkedList<Boolean> mEvents = new LinkedList<>();
 
        public NetworkManager(Context context)
        {
                mContext = context;
+
+               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+               {
+                       mCallback = new ConnectivityManager.NetworkCallback()
+                       {
+                               @Override
+                               public void onAvailable(Network network)
+                               {
+                                       synchronized (NetworkManager.this)
+                                       {
+                                               /* we expect this to be called if connected to at least one network during
+                                                * callback registration */
+                                               mConnectedNetworks += 1;
+                                               mEvents.addLast(true);
+                                               NetworkManager.this.notifyAll();
+                                       }
+                               }
+
+                               @Override
+                               public void onLost(Network network)
+                               {
+                                       synchronized (NetworkManager.this)
+                                       {
+                                               /* in particular mobile connections are disconnected overlapping with WiFi */
+                                               mConnectedNetworks -= 1;
+                                               mEvents.addLast(mConnectedNetworks > 0);
+                                               NetworkManager.this.notifyAll();
+                                       }
+                               }
+                       };
+               }
        }
 
        public void Register()
@@ -42,12 +78,38 @@ public class NetworkManager extends BroadcastReceiver implements Runnable
                mRegistered = true;
                mEventNotifier = new Thread(this);
                mEventNotifier.start();
+               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+               {
+                       ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+                       /* while we only get events for the VPN network via registerDefaultNetworkCallback,
+                        * the default capabilities in the builder include NetworkCapabilities.NET_CAPABILITY_NOT_VPN */
+                       NetworkRequest.Builder builder = new NetworkRequest.Builder();
+                       cm.registerNetworkCallback(builder.build(), mCallback);
+               }
+               else
+               {
+                       registerLegacyReceiver();
+               }
+       }
+
+       @SuppressWarnings("deprecation")
+       private void registerLegacyReceiver()
+       {
+               /* deprecated since API level 28 */
                mContext.registerReceiver(this, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
        }
 
        public void Unregister()
        {
-               mContext.unregisterReceiver(this);
+               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+               {
+                       ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+                       cm.unregisterNetworkCallback(mCallback);
+               }
+               else
+               {
+                       mContext.unregisterReceiver(this);
+               }
                mRegistered = false;
                synchronized (this)
                {
index 2953790..1c13a11 100644 (file)
@@ -169,7 +169,7 @@ public class TrustedCertificatesActivity extends AppCompatActivity implements Tr
 
                public TrustedCertificatesPagerAdapter(FragmentManager fm, Context context)
                {
-                       super(fm);
+                       super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
                        mTabs = new TrustedCertificatesTab[]{
                                new TrustedCertificatesTab(context.getString(R.string.system_tab), TrustedCertificateSource.SYSTEM),
                                new TrustedCertificatesTab(context.getString(R.string.user_tab), TrustedCertificateSource.USER),
index 9674b7d..fac9b34 100644 (file)
@@ -28,7 +28,6 @@ import android.security.KeyChain;
 import android.security.KeyChainAliasCallback;
 import android.security.KeyChainException;
 import android.text.Editable;
-import android.text.Html;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.TextUtils;
@@ -91,7 +90,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity
        private TrustedCertificateEntry mCertEntry;
        private String mUserCertLoading;
        private CertificateIdentitiesAdapter mSelectUserIdAdapter;
-       private String mSelectedUserId;
        private TrustedCertificateEntry mUserCertEntry;
        private VpnType mVpnType = VpnType.IKEV2_EAP;
        private SelectedAppsHandling mSelectedAppsHandling = SelectedAppsHandling.SELECTED_APPS_DISABLE;
@@ -108,7 +106,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity
        private EditText mPassword;
        private ViewGroup mUserCertificate;
        private RelativeLayout mSelectUserCert;
-       private Spinner mSelectUserId;
        private CheckBox mCheckAuto;
        private RelativeLayout mSelectCert;
        private RelativeLayout mTncNotice;
@@ -116,6 +113,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity
        private ViewGroup mAdvancedSettings;
        private MultiAutoCompleteTextView mRemoteId;
        private TextInputLayoutHelper mRemoteIdWrap;
+       private MultiAutoCompleteTextView mLocalId;
+       private TextInputLayoutHelper mLocalIdWrap;
        private EditText mMTU;
        private TextInputLayoutHelper mMTUWrap;
        private EditText mPort;
@@ -141,7 +140,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
        private EditText mEspProposal;
        private TextView mProfileIdLabel;
        private TextView mProfileId;
-       private MultiAutoCompleteTextView mDnsServers;
+       private EditText mDnsServers;
        private TextInputLayoutHelper mDnsServersWrap;
 
        @Override
@@ -171,7 +170,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity
 
                mUserCertificate = (ViewGroup)findViewById(R.id.user_certificate_group);
                mSelectUserCert = (RelativeLayout)findViewById(R.id.select_user_certificate);
-               mSelectUserId = (Spinner)findViewById(R.id.select_user_id);
 
                mCheckAuto = (CheckBox)findViewById(R.id.ca_auto);
                mSelectCert = (RelativeLayout)findViewById(R.id.select_certificate);
@@ -181,8 +179,10 @@ public class VpnProfileDetailActivity extends AppCompatActivity
 
                mRemoteId = (MultiAutoCompleteTextView)findViewById(R.id.remote_id);
                mRemoteIdWrap = (TextInputLayoutHelper) findViewById(R.id.remote_id_wrap);
-               mDnsServers = (MultiAutoCompleteTextView)findViewById(R.id.dns_servers);
-               mDnsServersWrap = (TextInputLayoutHelper) findViewById(R.id.dns_servers_wrap);
+               mLocalId = findViewById(R.id.local_id);
+               mLocalIdWrap = findViewById(R.id.local_id_wrap);
+               mDnsServers = findViewById(R.id.dns_servers);
+               mDnsServersWrap = findViewById(R.id.dns_servers_wrap);
                mMTU = (EditText)findViewById(R.id.mtu);
                mMTUWrap = (TextInputLayoutHelper) findViewById(R.id.mtu_wrap);
                mPort = (EditText)findViewById(R.id.port);
@@ -217,9 +217,10 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                final SpaceTokenizer spaceTokenizer = new SpaceTokenizer();
                mName.setTokenizer(spaceTokenizer);
                mRemoteId.setTokenizer(spaceTokenizer);
-               final ArrayAdapter<String> completeAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line);
-               mName.setAdapter(completeAdapter);
-               mRemoteId.setAdapter(completeAdapter);
+               mLocalId.setTokenizer(spaceTokenizer);
+               final ArrayAdapter<String> gatewayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line);
+               mName.setAdapter(gatewayAdapter);
+               mRemoteId.setAdapter(gatewayAdapter);
 
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
                {
@@ -238,8 +239,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                        @Override
                        public void afterTextChanged(Editable s)
                        {
-                               completeAdapter.clear();
-                               completeAdapter.add(mGateway.getText().toString());
+                               gatewayAdapter.clear();
+                               gatewayAdapter.add(mGateway.getText().toString());
                                if (TextUtils.isEmpty(mGateway.getText()))
                                {
                                        mNameWrap.setHelperText(getString(R.string.profile_name_hint));
@@ -281,23 +282,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
 
                mSelectUserCert.setOnClickListener(new SelectUserCertOnClickListener());
                mSelectUserIdAdapter = new CertificateIdentitiesAdapter(this);
-               mSelectUserId.setAdapter(mSelectUserIdAdapter);
-               mSelectUserId.setOnItemSelectedListener(new OnItemSelectedListener() {
-                       @Override
-                       public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
-                       {
-                               if (mUserCertEntry != null)
-                               {       /* we don't store the subject DN as it is in the reverse order and the default anyway */
-                                       mSelectedUserId = position == 0 ? null : mSelectUserIdAdapter.getItem(position);
-                               }
-                       }
-
-                       @Override
-                       public void onNothingSelected(AdapterView<?> parent)
-                       {
-                               mSelectedUserId = null;
-                       }
-               });
+               mLocalId.setAdapter(mSelectUserIdAdapter);
 
                mCheckAuto.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                        @Override
@@ -385,10 +370,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                {
                        outState.putString(VpnProfileDataSource.KEY_USER_CERTIFICATE, mUserCertEntry.getAlias());
                }
-               if (mSelectedUserId != null)
-               {
-                       outState.putString(VpnProfileDataSource.KEY_LOCAL_ID, mSelectedUserId);
-               }
                if (mCertEntry != null)
                {
                        outState.putString(VpnProfileDataSource.KEY_CERTIFICATE, mCertEntry.getAlias());
@@ -456,10 +437,10 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                mUsernamePassword.setVisibility(mVpnType.has(VpnTypeFeature.USER_PASS) ? View.VISIBLE : View.GONE);
                mUserCertificate.setVisibility(mVpnType.has(VpnTypeFeature.CERTIFICATE) ? View.VISIBLE : View.GONE);
                mTncNotice.setVisibility(mVpnType.has(VpnTypeFeature.BYOD) ? View.VISIBLE : View.GONE);
+               mLocalIdWrap.setHelperText(getString(R.string.profile_local_id_hint_user));
 
                if (mVpnType.has(VpnTypeFeature.CERTIFICATE))
                {
-                       mSelectUserId.setEnabled(false);
                        if (mUserCertLoading != null)
                        {
                                ((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(mUserCertLoading);
@@ -471,8 +452,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                                ((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(mUserCertEntry.getAlias());
                                ((TextView)mSelectUserCert.findViewById(android.R.id.text2)).setText(mUserCertEntry.getCertificate().getSubjectDN().toString());
                                mSelectUserIdAdapter.setCertificate(mUserCertEntry);
-                               mSelectUserId.setSelection(mSelectUserIdAdapter.getPosition(mSelectedUserId));
-                               mSelectUserId.setEnabled(true);
                        }
                        else
                        {
@@ -480,6 +459,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                                ((TextView)mSelectUserCert.findViewById(android.R.id.text2)).setText(R.string.profile_user_select_certificate);
                                mSelectUserIdAdapter.setCertificate(null);
                        }
+                       mLocalIdWrap.setHelperText(getString(R.string.profile_local_id_hint_cert));
                }
        }
 
@@ -581,7 +561,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                                   mProfile.getIncludedSubnets() != null || mProfile.getExcludedSubnets() != null ||
                                   mProfile.getSelectedAppsHandling() != SelectedAppsHandling.SELECTED_APPS_DISABLE ||
                                   mProfile.getIkeProposal() != null || mProfile.getEspProposal() != null ||
-                                  mProfile.getDnsServers() != null;
+                                  mProfile.getDnsServers() != null || mProfile.getLocalId() != null;
                }
                mShowAdvanced.setVisibility(!show ? View.VISIBLE : View.GONE);
                mAdvancedSettings.setVisibility(show ? View.VISIBLE : View.GONE);
@@ -632,14 +612,14 @@ public class VpnProfileDetailActivity extends AppCompatActivity
        private boolean verifyInput()
        {
                boolean valid = true;
-               if (mGateway.getText().toString().trim().isEmpty())
+               if (getString(mGateway) == null)
                {
                        mGatewayWrap.setError(getString(R.string.alert_text_no_input_gateway));
                        valid = false;
                }
                if (mVpnType.has(VpnTypeFeature.USER_PASS))
                {
-                       if (mUsername.getText().toString().trim().isEmpty())
+                       if (getString(mUsername) == null)
                        {
                                mUsernameWrap.setError(getString(R.string.alert_text_no_input_username));
                                valid = false;
@@ -705,27 +685,24 @@ public class VpnProfileDetailActivity extends AppCompatActivity
        private void updateProfileData()
        {
                /* the name is optional, we default to the gateway if none is given */
-               String name = mName.getText().toString().trim();
-               String gateway = mGateway.getText().toString().trim();
-               mProfile.setName(name.isEmpty() ? gateway : name);
+               String name = getString(mName);
+               String gateway = getString(mGateway);
+               mProfile.setName(name == null ? gateway : name);
                mProfile.setGateway(gateway);
                mProfile.setVpnType(mVpnType);
                if (mVpnType.has(VpnTypeFeature.USER_PASS))
                {
-                       mProfile.setUsername(mUsername.getText().toString().trim());
-                       String password = mPassword.getText().toString().trim();
-                       password = password.isEmpty() ? null : password;
-                       mProfile.setPassword(password);
+                       mProfile.setUsername(getString(mUsername));
+                       mProfile.setPassword(getString(mPassword));
                }
                if (mVpnType.has(VpnTypeFeature.CERTIFICATE))
                {
                        mProfile.setUserCertificateAlias(mUserCertEntry.getAlias());
-                       mProfile.setLocalId(mSelectedUserId);
                }
                String certAlias = mCheckAuto.isChecked() ? null : mCertEntry.getAlias();
                mProfile.setCertificateAlias(certAlias);
-               String remote_id = mRemoteId.getText().toString().trim();
-               mProfile.setRemoteId(remote_id.isEmpty() ? null : remote_id);
+               mProfile.setRemoteId(getString(mRemoteId));
+               mProfile.setLocalId(getString(mLocalId));
                mProfile.setMTU(getInteger(mMTU));
                mProfile.setPort(getInteger(mPort));
                mProfile.setNATKeepAlive(getInteger(mNATKeepalive));
@@ -736,22 +713,17 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                flags |= mStrictRevocation.isChecked() ? VpnProfile.FLAGS_STRICT_REVOCATION : 0;
                flags |= mRsaPss.isChecked() ? VpnProfile.FLAGS_RSA_PSS : 0;
                mProfile.setFlags(flags);
-               String included = mIncludedSubnets.getText().toString().trim();
-               mProfile.setIncludedSubnets(included.isEmpty() ? null : included);
-               String excluded = mExcludedSubnets.getText().toString().trim();
-               mProfile.setExcludedSubnets(excluded.isEmpty() ? null : excluded);
+               mProfile.setIncludedSubnets(getString(mIncludedSubnets));
+               mProfile.setExcludedSubnets(getString(mExcludedSubnets));
                int st = 0;
                st |= mBlockIPv4.isChecked() ? VpnProfile.SPLIT_TUNNELING_BLOCK_IPV4 : 0;
                st |= mBlockIPv6.isChecked() ? VpnProfile.SPLIT_TUNNELING_BLOCK_IPV6 : 0;
                mProfile.setSplitTunneling(st == 0 ? null : st);
                mProfile.setSelectedAppsHandling(mSelectedAppsHandling);
                mProfile.setSelectedApps(mSelectedApps);
-               String ike = mIkeProposal.getText().toString().trim();
-               mProfile.setIkeProposal(ike.isEmpty() ? null : ike);
-               String esp = mEspProposal.getText().toString().trim();
-               mProfile.setEspProposal(esp.isEmpty() ? null : esp);
-               String dns = mDnsServers.getText().toString().trim();
-               mProfile.setDnsServers(dns.isEmpty() ? null : dns);
+               mProfile.setIkeProposal(getString(mIkeProposal));
+               mProfile.setEspProposal(getString(mEspProposal));
+               mProfile.setDnsServers(getString(mDnsServers));
        }
 
        /**
@@ -776,6 +748,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                                mUsername.setText(mProfile.getUsername());
                                mPassword.setText(mProfile.getPassword());
                                mRemoteId.setText(mProfile.getRemoteId());
+                               mLocalId.setText(mProfile.getLocalId());
                                mMTU.setText(mProfile.getMTU() != null ? mProfile.getMTU().toString() : null);
                                mPort.setText(mProfile.getPort() != null ? mProfile.getPort().toString() : null);
                                mNATKeepalive.setText(mProfile.getNATKeepAlive() != null ? mProfile.getNATKeepAlive().toString() : null);
@@ -812,12 +785,10 @@ public class VpnProfileDetailActivity extends AppCompatActivity
 
                /* check if the user selected a user certificate previously */
                useralias = savedInstanceState == null ? useralias : savedInstanceState.getString(VpnProfileDataSource.KEY_USER_CERTIFICATE);
-               local_id = savedInstanceState == null ? local_id : savedInstanceState.getString(VpnProfileDataSource.KEY_LOCAL_ID);
                if (useralias != null)
                {
                        UserCertificateLoader loader = new UserCertificateLoader(this, useralias);
                        mUserCertLoading = useralias;
-                       mSelectedUserId = local_id;
                        loader.execute();
                }
 
@@ -847,6 +818,17 @@ public class VpnProfileDetailActivity extends AppCompatActivity
        }
 
        /**
+        * Get the string value in the given text box or null if empty
+        *
+        * @param view text box
+        */
+       private String getString(EditText view)
+       {
+               String value = view.getText().toString().trim();
+               return value.isEmpty() ? null : value;
+       }
+
+       /**
         * Get the integer value in the given text box or null if empty
         *
         * @param view text box (numeric entry assumed)
@@ -943,7 +925,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
                public void onClick(View v)
                {
                        String useralias = mUserCertEntry != null ? mUserCertEntry.getAlias() : null;
-                       KeyChain.choosePrivateKeyAlias(VpnProfileDetailActivity.this, this, new String[] { "RSA" }, null, null, -1, useralias);
+                       KeyChain.choosePrivateKeyAlias(VpnProfileDetailActivity.this, this, null, null, null, -1, useralias);
                }
 
                @Override
index eae7683..33b3966 100644 (file)
@@ -505,6 +505,8 @@ public class VpnProfileImportActivity extends AppCompatActivity
                JSONObject local = obj.optJSONObject("local");
                if (local != null)
                {
+                       profile.setLocalId(local.optString("id", null));
+
                        if (type.has(VpnTypeFeature.USER_PASS))
                        {
                                profile.setUsername(local.optString("eap_id", null));
@@ -512,7 +514,6 @@ public class VpnProfileImportActivity extends AppCompatActivity
 
                        if (type.has(VpnTypeFeature.CERTIFICATE))
                        {
-                               profile.setLocalId(local.optString("id", null));
                                profile.PKCS12 = decodeBase64(local.optString("p12", null));
 
                                if (local.optBoolean("rsa-pss", false))
@@ -888,7 +889,7 @@ public class VpnProfileImportActivity extends AppCompatActivity
                        {
                                alias = getString(R.string.profile_cert_alias, mProfile.getName());
                        }
-                       KeyChain.choosePrivateKeyAlias(VpnProfileImportActivity.this, this, new String[] { "RSA" }, null, null, -1, alias);
+                       KeyChain.choosePrivateKeyAlias(VpnProfileImportActivity.this, this, null, null, null, -1, alias);
                }
 
                @Override
index c8e3df3..912f524 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Tobias Brunner
+ * Copyright (C) 2016-2019 Tobias Brunner
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
 package org.strongswan.android.ui.adapter;
 
 import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
-import android.widget.TextView;
 
-import org.strongswan.android.R;
 import org.strongswan.android.security.TrustedCertificateEntry;
 
-import java.util.List;
-
 public class CertificateIdentitiesAdapter extends ArrayAdapter<String>
 {
        TrustedCertificateEntry mCertificate;
@@ -51,14 +44,8 @@ public class CertificateIdentitiesAdapter extends ArrayAdapter<String>
 
        private void extractIdentities()
        {
-               if (mCertificate == null)
-               {
-                       add(getContext().getString(R.string.profile_user_select_id_init));
-               }
-               else
+               if (mCertificate != null)
                {
-                       add(String.format(getContext().getString(R.string.profile_user_select_id_default),
-                                                         mCertificate.getCertificate().getSubjectDN().getName()));
                        addAll(mCertificate.getSubjectAltNames());
                }
        }
index f1ff1c6..d920174 100644 (file)
 
 package org.strongswan.android.ui.adapter;
 
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import org.strongswan.android.R;
-import org.strongswan.android.data.VpnProfile;
-import org.strongswan.android.data.VpnType.VpnTypeFeature;
-
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -32,6 +24,14 @@ import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.TextView;
 
+import org.strongswan.android.R;
+import org.strongswan.android.data.VpnProfile;
+import org.strongswan.android.data.VpnType.VpnTypeFeature;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
 public class VpnProfileAdapter extends ArrayAdapter<VpnProfile>
 {
        private final int resource;
@@ -74,7 +74,7 @@ public class VpnProfileAdapter extends ArrayAdapter<VpnProfile>
                                 profile.getLocalId() != null)
                {
                        tv.setVisibility(View.VISIBLE);
-                       tv.setText(getContext().getString(R.string.profile_user_select_id_label) + ": " + profile.getLocalId());
+                       tv.setText(getContext().getString(R.string.profile_local_id_label) + ": " + profile.getLocalId());
                }
                else
                {
index 0bdbc1d..acab0b2 100644 (file)
@@ -73,6 +73,7 @@
                 android:id="@+id/username_wrap"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="4dp"
                 android:hint="@string/profile_username_label" >
 
                 <com.google.android.material.textfield.TextInputEditText
                 android:id="@+id/select_user_certificate"
                 layout="@layout/two_line_button" />
 
-            <TextView
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="4dp"
-                android:layout_marginLeft="4dp"
-                android:textSize="12sp"
-                android:text="@string/profile_user_select_id_label" />
-
-            <Spinner
-                android:id="@+id/select_user_id"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:spinnerMode="dropdown" />
-
         </LinearLayout>
 
         <TextView
             </org.strongswan.android.ui.widget.TextInputLayoutHelper>
 
             <org.strongswan.android.ui.widget.TextInputLayoutHelper
+                android:id="@+id/local_id_wrap"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:hint="@string/profile_local_id_label"
+                app:helper_text="@string/profile_local_id_hint_user" >
+
+                <MultiAutoCompleteTextView
+                    android:id="@+id/local_id"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:inputType="textNoSuggestions"
+                    android:completionThreshold="0" />
+
+            </org.strongswan.android.ui.widget.TextInputLayoutHelper>
+
+            <org.strongswan.android.ui.widget.TextInputLayoutHelper
                 android:id="@+id/dns_servers_wrap"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="10dp"
                 android:hint="@string/profile_dns_servers_label"
                 app:helper_text="@string/profile_dns_servers_hint" >
 
-                <MultiAutoCompleteTextView
+                <com.google.android.material.textfield.TextInputEditText
                     android:id="@+id/dns_servers"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:singleLine="true"
-                    android:inputType="textNoSuggestions"
-                    android:completionThreshold="1" />
+                    android:inputType="textNoSuggestions" />
 
             </org.strongswan.android.ui.widget.TextInputLayoutHelper>
 
index f7fc36d..fcd14ea 100644 (file)
@@ -73,9 +73,6 @@
     <string name="profile_user_certificate_label">Benutzer-Zertifikat</string>
     <string name="profile_user_select_certificate_label">Benutzer-Zertifikat auswählen</string>
     <string name="profile_user_select_certificate">Wählen Sie ein bestimmtes Benutzer-Zertifikat</string>
-    <string name="profile_user_select_id_label">Benutzer-Identität</string>
-    <string name="profile_user_select_id_init">Wählen Sie zuerst ein Benutzer-Zertifikat</string>
-    <string name="profile_user_select_id_default">Standardwert (%1$s)</string>
     <string name="profile_ca_label">CA-Zertifikat</string>
     <string name="profile_ca_auto_label">Automatisch wählen</string>
     <string name="profile_ca_select_certificate_label">CA-Zertifikat auswählen</string>
     <string name="profile_remote_id_label">Server-Identität</string>
     <string name="profile_remote_id_hint">Standardwert ist der konfigurierte Server. Eigene Werte werden explizit an den Server gesendet und während der Authentifizierung erzwungen</string>
     <string name="profile_remote_id_hint_gateway">Standardwert ist \"%1$s\". Eigene Werte werden explizit an den Server gesendet und während der Authentifizierung erzwungen</string>
+    <string name="profile_local_id_label">Client-Identität</string>
+    <string name="profile_local_id_hint_user">Standardwert ist der konfigurierte Benutzername. Eigene Werte können verwendet werden, falls der Server diese erwartet/benötigt</string>
+    <string name="profile_local_id_hint_cert">Standardwert ist die Inhaber-Identität des Zertifkats. Eigene Werte können verwendet werden, falls der Server diese erwartet/benötigt. Zu beachten ist, dass diese üblicherweise vom Zertifikat bestätigt werden müssen (für die alternativen Identitäten des Zertifikats, falls vorhanden, wird eine Auto-Vervollständigung angeboten)</string>
     <string name="profile_dns_servers_label">DNS Server</string>
-    <string name="profile_dns_servers_hint">Benutzerdefinierte DNS Server bei Verbindung zum VPN (mit Leerzeichen getrennt, z.B.. \"8.8.8.8 2001:4860:4860::8888\", standardmässig werden die vom VPN Server erhaltenen Server verwendet)</string>
+    <string name="profile_dns_servers_hint">Benutzerdefinierte DNS Server bei Verbindung zum VPN (mit Leerzeichen getrennt, z.B.. \"8.8.8.8 2001:4860:4860::8888\"), standardmässig werden die vom VPN Server erhaltenen Server verwendet</string>
     <string name="profile_mtu_label">MTU des VPN Tunnel-Device</string>
     <string name="profile_mtu_hint">Falls der Standardwert in einem bestimmten Netzwerk nicht geeignet ist</string>
     <string name="profile_port_label">Server Port</string>
index b202b67..6f4716b 100644 (file)
@@ -73,9 +73,6 @@
     <string name="profile_user_certificate_label">Certyfikat użytkownika</string>
     <string name="profile_user_select_certificate_label">Wybierz certyfikat użytkownika</string>
     <string name="profile_user_select_certificate">>Wybierz określony certyfikat użytkownika</string>
-    <string name="profile_user_select_id_label">User identity</string>
-    <string name="profile_user_select_id_init">Select a certificate first</string>
-    <string name="profile_user_select_id_default">Default (%1$s)</string>
     <string name="profile_ca_label">Certyfikat CA</string>
     <string name="profile_ca_auto_label">Wybierz automatycznie</string>
     <string name="profile_ca_select_certificate_label">Wybierz certyfikat CA</string>
     <string name="profile_remote_id_label">Server identity</string>
     <string name="profile_remote_id_hint">Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication</string>
     <string name="profile_remote_id_hint_gateway">Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication</string>
+    <string name="profile_local_id_label">Client identity</string>
+    <string name="profile_local_id_hint_user">Defaults to the configured username. Custom values may be used if expected/required by the server</string>
+    <string name="profile_local_id_hint_cert">Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any)</string>
     <string name="profile_dns_servers_label">DNS servers</string>
-    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
+    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server</string>
     <string name="profile_mtu_label">MTU of the VPN tunnel device</string>
     <string name="profile_mtu_hint">In case the default value is unsuitable for a particular network</string>
     <string name="profile_port_label">Server port</string>
index 1f81587..5def66d 100644 (file)
@@ -70,9 +70,6 @@
     <string name="profile_user_certificate_label">Сертификат пользователя</string>
     <string name="profile_user_select_certificate_label">Выбрать сертификат пользователя</string>
     <string name="profile_user_select_certificate">Выбрать сертификат пользователя</string>
-    <string name="profile_user_select_id_label">User identity</string>
-    <string name="profile_user_select_id_init">Select a certificate first</string>
-    <string name="profile_user_select_id_default">Default (%1$s)</string>
     <string name="profile_ca_label">Сертификат CA</string>
     <string name="profile_ca_auto_label">Выбрать автоматически</string>
     <string name="profile_ca_select_certificate_label">Выбрать сертификат CA</string>
     <string name="profile_remote_id_label">Server identity</string>
     <string name="profile_remote_id_hint">Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication</string>
     <string name="profile_remote_id_hint_gateway">Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication</string>
+    <string name="profile_local_id_label">Client identity</string>
+    <string name="profile_local_id_hint_user">Defaults to the configured username. Custom values may be used if expected/required by the server</string>
+    <string name="profile_local_id_hint_cert">Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any)</string>
     <string name="profile_dns_servers_label">DNS servers</string>
-    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
+    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server</string>
     <string name="profile_mtu_label">MTU of the VPN tunnel device</string>
     <string name="profile_mtu_hint">In case the default value is unsuitable for a particular network</string>
     <string name="profile_port_label">Server port</string>
index 95fdd42..4920aa2 100644 (file)
@@ -71,9 +71,6 @@
     <string name="profile_user_certificate_label">Сертифікат користувача</string>
     <string name="profile_user_select_certificate_label">Виберіть сертифікат користувача</string>
     <string name="profile_user_select_certificate">Вибрати спеціальний сертифікат користувача</string>
-    <string name="profile_user_select_id_label">User identity</string>
-    <string name="profile_user_select_id_init">Select a certificate first</string>
-    <string name="profile_user_select_id_default">Default (%1$s)</string>
     <string name="profile_ca_label">Сертифікат CA</string>
     <string name="profile_ca_auto_label">Вибрати автоматично</string>
     <string name="profile_ca_select_certificate_label">Вибрати сертифікат CA</string>
     <string name="profile_remote_id_label">Server identity</string>
     <string name="profile_remote_id_hint">Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication</string>
     <string name="profile_remote_id_hint_gateway">Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication</string>
+    <string name="profile_local_id_label">Client identity</string>
+    <string name="profile_local_id_hint_user">Defaults to the configured username. Custom values may be used if expected/required by the server</string>
+    <string name="profile_local_id_hint_cert">Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any)</string>
     <string name="profile_dns_servers_label">DNS servers</string>
-    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
+    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server</string>
     <string name="profile_mtu_label">MTU of the VPN tunnel device</string>
     <string name="profile_mtu_hint">In case the default value is unsuitable for a particular network</string>
     <string name="profile_port_label">Server port</string>
index 006ad53..3408f5f 100644 (file)
@@ -70,9 +70,6 @@
     <string name="profile_user_certificate_label">用户证书</string>
     <string name="profile_user_select_certificate_label">选择用户证书</string>
     <string name="profile_user_select_certificate">选择指定的用户证书</string>
-    <string name="profile_user_select_id_label">用户ID</string>
-    <string name="profile_user_select_id_init">首先选择一个证书</string>
-    <string name="profile_user_select_id_default">默认(%1$s)</string>
     <string name="profile_ca_label">CA证书</string>
     <string name="profile_ca_auto_label">自动选择</string>
     <string name="profile_ca_select_certificate_label">选择CA证书</string>
     <string name="profile_remote_id_label">服务器ID</string>
     <string name="profile_remote_id_hint">默认为已配置的服务器地址。自义定值将在鉴权期间被显式地发送至服务器</string>
     <string name="profile_remote_id_hint_gateway">默认为 \"%1$s\"。自义定值将在鉴权期间被显式地发送至服务器</string>
+    <string name="profile_local_id_label">Client identity</string>
+    <string name="profile_local_id_hint_user">Defaults to the configured username. Custom values may be used if expected/required by the server</string>
+    <string name="profile_local_id_hint_cert">Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any)</string>
+    <string name="profile_dns_servers_label">DNS servers</string>
+    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server</string>
     <string name="profile_mtu_label">VPN隧道设备的MTU值</string>
     <string name="profile_mtu_hint">假如在某一网络下默认值不合适</string>
     <string name="profile_port_label">服务器端口</string>
index 12666ca..e3d7f03 100644 (file)
@@ -70,9 +70,6 @@
     <string name="profile_user_certificate_label">用戶憑證</string>
     <string name="profile_user_select_certificate_label">選擇用戶憑證</string>
     <string name="profile_user_select_certificate">選擇指定的用戶憑證</string>
-    <string name="profile_user_select_id_label">用戶帳號</string>
-    <string name="profile_user_select_id_init">請先選擇一個憑證</string>
-    <string name="profile_user_select_id_default">預設(%1$s)</string>
     <string name="profile_ca_label">CA憑證</string>
     <string name="profile_ca_auto_label">自動選擇</string>
     <string name="profile_ca_select_certificate_label">選擇CA憑證</string>
     <string name="profile_remote_id_label">伺服器ID</string>
     <string name="profile_remote_id_hint">預設為已設定的伺服器位置。自訂值會在授權期間送到伺服器</string>
     <string name="profile_remote_id_hint_gateway">預設為 \"%1$s\"。自訂值會在授權期間送到伺服器</string>
+    <string name="profile_local_id_label">Client identity</string>
+    <string name="profile_local_id_hint_user">Defaults to the configured username. Custom values may be used if expected/required by the server</string>
+    <string name="profile_local_id_hint_cert">Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any)</string>
     <string name="profile_dns_servers_label">DNS servers</string>
-    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
+    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server</string>
     <string name="profile_mtu_label">VPN通道裝置的MTU值</string>
     <string name="profile_mtu_hint">如果在某個網路下預設值不適合</string>
     <string name="profile_port_label">伺服器Port</string>
index e86e84b..4d9fd87 100644 (file)
@@ -73,9 +73,6 @@
     <string name="profile_user_certificate_label">User certificate</string>
     <string name="profile_user_select_certificate_label">Select user certificate</string>
     <string name="profile_user_select_certificate">Select a specific user certificate</string>
-    <string name="profile_user_select_id_label">User identity</string>
-    <string name="profile_user_select_id_init">Select a certificate first</string>
-    <string name="profile_user_select_id_default">Default (%1$s)</string>
     <string name="profile_ca_label">CA certificate</string>
     <string name="profile_ca_auto_label">Select automatically</string>
     <string name="profile_ca_select_certificate_label">Select CA certificate</string>
     <string name="profile_remote_id_label">Server identity</string>
     <string name="profile_remote_id_hint">Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication</string>
     <string name="profile_remote_id_hint_gateway">Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication</string>
+    <string name="profile_local_id_label">Client identity</string>
+    <string name="profile_local_id_hint_user">Defaults to the configured username. Custom values may be used if expected/required by the server</string>
+    <string name="profile_local_id_hint_cert">Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any)</string>
     <string name="profile_dns_servers_label">DNS servers</string>
-    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server)</string>
+    <string name="profile_dns_servers_hint">Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server</string>
     <string name="profile_mtu_label">MTU of the VPN tunnel device</string>
     <string name="profile_mtu_hint">In case the default value is unsuitable for a particular network</string>
     <string name="profile_port_label">Server port</string>
index f5a6850..5880d16 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
         google()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.4.2'
+        classpath 'com.android.tools.build:gradle:3.5.1'
     }
 }
 
index 54bc74a..558ba36 100644 (file)
@@ -1,6 +1,6 @@
-#Tue Aug 13 13:47:52 CEST 2019
+#Mon Oct 07 16:41:25 CEST 2019
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
index 73cb02b..e0aee8b 100644 (file)
@@ -209,16 +209,18 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*,
 {
        enumerator_t *enumerator;
        proposal_t *current;
+       proposal_selection_flag_t flags = 0;
        linked_list_t *proposals = linked_list_create();
 
+       if (strip_dh)
+       {
+               flags |= PROPOSAL_SKIP_DH;
+       }
+
        enumerator = this->proposals->create_enumerator(this->proposals);
        while (enumerator->enumerate(enumerator, &current))
        {
-               current = current->clone(current);
-               if (strip_dh)
-               {
-                       current->strip_dh(current, MODP_NONE);
-               }
+               current = current->clone(current, flags);
                if (proposals->find_first(proposals, match_proposal, NULL, current))
                {
                        current->destroy(current);
@@ -234,69 +236,10 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*,
 }
 
 METHOD(child_cfg_t, select_proposal, proposal_t*,
-       private_child_cfg_t*this, linked_list_t *proposals, bool strip_dh,
-       bool private, bool prefer_self)
+       private_child_cfg_t*this, linked_list_t *proposals,
+       proposal_selection_flag_t flags)
 {
-       enumerator_t *prefer_enum, *match_enum;
-       proposal_t *proposal, *match, *selected = NULL;
-
-       if (prefer_self)
-       {
-               prefer_enum = this->proposals->create_enumerator(this->proposals);
-               match_enum = proposals->create_enumerator(proposals);
-       }
-       else
-       {
-               prefer_enum = proposals->create_enumerator(proposals);
-               match_enum = this->proposals->create_enumerator(this->proposals);
-       }
-
-       while (prefer_enum->enumerate(prefer_enum, &proposal))
-       {
-               proposal = proposal->clone(proposal);
-               if (strip_dh)
-               {
-                       proposal->strip_dh(proposal, MODP_NONE);
-               }
-               if (prefer_self)
-               {
-                       proposals->reset_enumerator(proposals, match_enum);
-               }
-               else
-               {
-                       this->proposals->reset_enumerator(this->proposals, match_enum);
-               }
-               while (match_enum->enumerate(match_enum, &match))
-               {
-                       match = match->clone(match);
-                       if (strip_dh)
-                       {
-                               match->strip_dh(match, MODP_NONE);
-                       }
-                       selected = proposal->select(proposal, match, prefer_self, private);
-                       match->destroy(match);
-                       if (selected)
-                       {
-                               DBG2(DBG_CFG, "received proposals: %#P", proposals);
-                               DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
-                               DBG1(DBG_CFG, "selected proposal: %P", selected);
-                               break;
-                       }
-               }
-               proposal->destroy(proposal);
-               if (selected)
-               {
-                       break;
-               }
-       }
-       prefer_enum->destroy(prefer_enum);
-       match_enum->destroy(match_enum);
-       if (!selected)
-       {
-               DBG1(DBG_CFG, "received proposals: %#P", proposals);
-               DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
-       }
-       return selected;
+       return proposal_select(this->proposals, proposals, flags);
 }
 
 METHOD(child_cfg_t, add_traffic_selector, void,
index b802685..13ec6d8 100644 (file)
@@ -99,14 +99,11 @@ struct child_cfg_t {
         * Returned propsal is newly created and must be destroyed after usage.
         *
         * @param proposals             list from which proposals are selected
-        * @param strip_dh              TRUE strip out diffie hellman groups
-        * @param private               accept algorithms from a private range
-        * @param prefer_self   whether to prefer configured or supplied proposals
+        * @param flags                 flags to consider during proposal selection
         * @return                              selected proposal, or NULL if nothing matches
         */
        proposal_t* (*select_proposal)(child_cfg_t*this, linked_list_t *proposals,
-                                                                  bool strip_dh, bool private,
-                                                                  bool prefer_self);
+                                                                  proposal_selection_flag_t flags);
 
        /**
         * Add a traffic selector to the config.
index d99abbc..79a344e 100644 (file)
@@ -310,7 +310,7 @@ METHOD(ike_cfg_t, get_proposals, linked_list_t*,
        enumerator = this->proposals->create_enumerator(this->proposals);
        while (enumerator->enumerate(enumerator, &current))
        {
-               current = current->clone(current);
+               current = current->clone(current, 0);
                proposals->insert_last(proposals, current);
        }
        enumerator->destroy(enumerator);
@@ -329,7 +329,8 @@ METHOD(ike_cfg_t, has_proposal, bool,
        enumerator = this->proposals->create_enumerator(this->proposals);
        while (enumerator->enumerate(enumerator, &proposal))
        {
-               if (proposal->matches(proposal, match, private))
+               if (proposal->matches(proposal, match,
+                                                         private ? 0 : PROPOSAL_SKIP_PRIVATE))
                {
                        enumerator->destroy(enumerator);
                        return TRUE;
@@ -340,57 +341,10 @@ METHOD(ike_cfg_t, has_proposal, bool,
 }
 
 METHOD(ike_cfg_t, select_proposal, proposal_t*,
-       private_ike_cfg_t *this, linked_list_t *proposals, bool private,
-       bool prefer_self)
+       private_ike_cfg_t *this, linked_list_t *proposals,
+       proposal_selection_flag_t flags)
 {
-       enumerator_t *prefer_enum, *match_enum;
-       proposal_t *proposal, *match, *selected = NULL;
-
-       if (prefer_self)
-       {
-               prefer_enum = this->proposals->create_enumerator(this->proposals);
-               match_enum = proposals->create_enumerator(proposals);
-       }
-       else
-       {
-               prefer_enum = proposals->create_enumerator(proposals);
-               match_enum = this->proposals->create_enumerator(this->proposals);
-       }
-
-       while (prefer_enum->enumerate(prefer_enum, (void**)&proposal))
-       {
-               if (prefer_self)
-               {
-                       proposals->reset_enumerator(proposals, match_enum);
-               }
-               else
-               {
-                       this->proposals->reset_enumerator(this->proposals, match_enum);
-               }
-               while (match_enum->enumerate(match_enum, (void**)&match))
-               {
-                       selected = proposal->select(proposal, match, prefer_self, private);
-                       if (selected)
-                       {
-                               DBG2(DBG_CFG, "received proposals: %#P", proposals);
-                               DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
-                               DBG1(DBG_CFG, "selected proposal: %P", selected);
-                               break;
-                       }
-               }
-               if (selected)
-               {
-                       break;
-               }
-       }
-       prefer_enum->destroy(prefer_enum);
-       match_enum->destroy(match_enum);
-       if (!selected)
-       {
-               DBG1(DBG_CFG, "received proposals: %#P", proposals);
-               DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
-       }
-       return selected;
+       return proposal_select(this->proposals, proposals, flags);
 }
 
 METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
index 9c697da..1e11a1e 100644 (file)
@@ -186,12 +186,11 @@ struct ike_cfg_t {
         * Returned proposal must be destroyed after use.
         *
         * @param proposals             list of proposals to select from
-        * @param private               accept algorithms from a private range
-        * @param prefer_self   whether to prefer configured or supplied proposals
+        * @param flags                 flags to consider during proposal selection
         * @return                              selected proposal, or NULL if none matches.
         */
        proposal_t *(*select_proposal) (ike_cfg_t *this, linked_list_t *proposals,
-                                                                       bool private, bool prefer_self);
+                                                                       proposal_selection_flag_t flags);
 
        /**
         * Check if the config has a matching proposal.
index c22e379..f95ee3c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2018 Tobias Brunner
+ * Copyright (C) 2008-2019 Tobias Brunner
  * Copyright (C) 2005-2008 Martin Willi
  * HSR Hochschule fuer Technik Rapperswil
  *
@@ -90,14 +90,15 @@ ENUM(rt_msg_names, RTM_NEWLINK, RTM_GETRULE,
        "RTM_NEWADDR",
        "RTM_DELADDR",
        "RTM_GETADDR",
-       "31",
+       "23",
        "RTM_NEWROUTE",
        "RTM_DELROUTE",
        "RTM_GETROUTE",
-       "35",
+       "27",
        "RTM_NEWNEIGH",
        "RTM_DELNEIGH",
        "RTM_GETNEIGH",
+       "31",
        "RTM_NEWRULE",
        "RTM_DELRULE",
        "RTM_GETRULE",
@@ -439,12 +440,12 @@ struct private_kernel_netlink_net_t {
        /**
         * routing table to install routes
         */
-       int routing_table;
+       uint32_t routing_table;
 
        /**
         * priority of used routing table
         */
-       int routing_table_prio;
+       uint32_t routing_table_prio;
 
        /**
         * installed routes
@@ -1400,7 +1401,8 @@ static void process_addr(private_kernel_netlink_net_t *this,
 /**
  * process RTM_NEWROUTE and RTM_DELROUTE from kernel
  */
-static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
+static void process_route(private_kernel_netlink_net_t *this,
+                                                 struct nlmsghdr *hdr)
 {
        struct rtmsg* msg = NLMSG_DATA(hdr);
        struct rtattr *rta = RTM_RTA(msg);
@@ -1423,6 +1425,16 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
        {
                switch (rta->rta_type)
                {
+#ifdef HAVE_RTA_TABLE
+                       case RTA_TABLE:
+                               /* also check against extended table ID */
+                               if (RTA_PAYLOAD(rta) == sizeof(uint32_t) &&
+                                       this->routing_table == *(uint32_t*)RTA_DATA(rta))
+                               {
+                                       return;
+                               }
+                               break;
+#endif /* HAVE_RTA_TABLE */
                        case RTA_PREFSRC:
                                DESTROY_IF(host);
                                host = host_create_from_chunk(msg->rtm_family,
@@ -1463,13 +1475,13 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
 /**
  * process RTM_NEW|DELRULE from kernel
  */
-static void process_rule(private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
+static void process_rule(private_kernel_netlink_net_t *this,
+                                                struct nlmsghdr *hdr)
 {
 #ifdef HAVE_LINUX_FIB_RULES_H
        struct rtmsg* msg = NLMSG_DATA(hdr);
        struct rtattr *rta = RTM_RTA(msg);
        size_t rtasize = RTM_PAYLOAD(hdr);
-       uint32_t table = 0;
 
        /* ignore rules added by us or in the local routing table (local addrs) */
        if (msg->rtm_table && (msg->rtm_table == this->routing_table ||
@@ -1483,18 +1495,16 @@ static void process_rule(private_kernel_netlink_net_t *this, struct nlmsghdr *hd
                switch (rta->rta_type)
                {
                        case FRA_TABLE:
-                               if (RTA_PAYLOAD(rta) == sizeof(table))
+                               /* also check against extended table ID */
+                               if (RTA_PAYLOAD(rta) == sizeof(uint32_t) &&
+                                       this->routing_table == *(uint32_t*)RTA_DATA(rta))
                                {
-                                       table = *(uint32_t*)RTA_DATA(rta);
+                                       return;
                                }
                                break;
                }
                rta = RTA_NEXT(rta, rtasize);
        }
-       if (table && table == this->routing_table)
-       {       /* also check against extended table ID */
-               return;
-       }
        fire_roam_event(this, FALSE);
 #endif
 }
@@ -1603,10 +1613,19 @@ CALLBACK(filter_addresses, bool,
                {       /* address is regular, but not requested */
                        continue;
                }
-               if (addr->scope >= RT_SCOPE_LINK)
-               {       /* skip addresses with a unusable scope */
+               if (addr->flags & IFA_F_DEPRECATED ||
+                       addr->scope >= RT_SCOPE_LINK)
+               {       /* skip deprecated addresses or those with an unusable scope */
                        continue;
                }
+               if (addr->ip->get_family(addr->ip) == AF_INET6)
+               {       /* handle temporary IPv6 addresses according to config */
+                       bool temporary = (addr->flags & IFA_F_TEMPORARY) == IFA_F_TEMPORARY;
+                       if (data->this->prefer_temporary_addrs != temporary)
+                       {
+                               continue;
+                       }
+               }
                *out = addr->ip;
                return TRUE;
        }
@@ -2653,11 +2672,24 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this,
        msg = NLMSG_DATA(hdr);
        msg->rtm_family = src_ip->get_family(src_ip);
        msg->rtm_dst_len = prefixlen;
-       msg->rtm_table = this->routing_table;
        msg->rtm_protocol = RTPROT_STATIC;
        msg->rtm_type = RTN_UNICAST;
        msg->rtm_scope = RT_SCOPE_UNIVERSE;
 
+       if (this->routing_table < 256)
+       {
+               msg->rtm_table = this->routing_table;
+       }
+       else
+       {
+#ifdef HAVE_RTA_TABLE
+               chunk = chunk_from_thing(this->routing_table);
+               netlink_add_attribute(hdr, RTA_TABLE, chunk, sizeof(request));
+#else
+               DBG1(DBG_KNL, "routing table IDs > 255 are not supported");
+               return FAILED;
+#endif /* HAVE_RTA_TABLE */
+       }
        netlink_add_attribute(hdr, RTA_DST, dst_net, sizeof(request));
        chunk = src_ip->get_address(src_ip);
        netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
@@ -2953,12 +2985,25 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
 
        msg = NLMSG_DATA(hdr);
-       msg->rtm_table = table;
        msg->rtm_family = family;
        msg->rtm_protocol = RTPROT_BOOT;
        msg->rtm_scope = RT_SCOPE_UNIVERSE;
        msg->rtm_type = RTN_UNICAST;
 
+       if (this->routing_table < 256)
+       {
+               msg->rtm_table = table;
+       }
+       else
+       {
+#ifdef HAVE_LINUX_FIB_RULES_H
+               chunk = chunk_from_thing(table);
+               netlink_add_attribute(hdr, FRA_TABLE, chunk, sizeof(request));
+#else
+               DBG1(DBG_KNL, "routing table IDs > 255 are not supported");
+               return FAILED;
+#endif /* HAVE_LINUX_FIB_RULES_H */
+       }
        chunk = chunk_from_thing(prio);
        netlink_add_attribute(hdr, RTA_PRIORITY, chunk, sizeof(request));
 
@@ -2987,7 +3032,7 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
                }
 #else
                DBG1(DBG_KNL, "setting firewall mark on routing rule is not supported");
-#endif
+#endif /* HAVE_LINUX_FIB_RULES_H */
        }
        return this->socket->send_ack(this->socket, hdr);
 }
index 37170a3..a97daf4 100644 (file)
@@ -692,12 +692,27 @@ struct pfkey_msg_t
                        struct sadb_x_kmprivate *x_kmprivate;   /* SADB_X_EXT_KMPRIVATE */
                        struct sadb_x_policy *x_policy;                 /* SADB_X_EXT_POLICY */
                        struct sadb_x_sa2 *x_sa2;                               /* SADB_X_EXT_SA2 */
+#if defined(__linux__) || defined (__FreeBSD__)
                        struct sadb_x_nat_t_type *x_natt_type;  /* SADB_X_EXT_NAT_T_TYPE */
                        struct sadb_x_nat_t_port *x_natt_sport; /* SADB_X_EXT_NAT_T_SPORT */
                        struct sadb_x_nat_t_port *x_natt_dport; /* SADB_X_EXT_NAT_T_DPORT */
+#ifdef __linux__
                        struct sadb_address *x_natt_oa;                 /* SADB_X_EXT_NAT_T_OA */
                        struct sadb_x_sec_ctx *x_sec_ctx;               /* SADB_X_EXT_SEC_CTX */
                        struct sadb_x_kmaddress *x_kmaddress;   /* SADB_X_EXT_KMADDRESS */
+#else
+                       struct sadb_address *x_natt_oai;                /* SADB_X_EXT_NAT_T_OAI */
+                       struct sadb_address *x_natt_oar;                /* SADB_X_EXT_NAT_T_OAR */
+#ifdef SADB_X_EXT_NAT_T_FRAG
+                       struct sadb_x_nat_t_frag *x_natt_frag;  /* SADB_X_EXT_NAT_T_FRAG */
+#ifdef SADB_X_EXT_SA_REPLAY
+                       struct sadb_x_sa_replay *x_replay;              /* SADB_X_EXT_SA_REPLAY */
+                       struct sadb_address *x_new_addr_src;    /* SADB_X_EXT_NEW_ADDRESS_SRC */
+                       struct sadb_address *x_new_addr_dst;    /* SADB_X_EXT_NEW_ADDRESS_DST */
+#endif
+#endif
+#endif /* __linux__ */
+#endif /* __linux__ || __FreeBSD__ */
                } __attribute__((__packed__));
        };
 };
@@ -723,12 +738,34 @@ ENUM(sadb_ext_type_names, SADB_EXT_RESERVED, SADB_EXT_MAX,
        "SADB_X_EXT_KMPRIVATE",
        "SADB_X_EXT_POLICY",
        "SADB_X_EXT_SA2",
+#ifdef __APPLE__
+       "SADB_EXT_SESSION_ID",
+       "SADB_EXT_SASTAT",
+       "SADB_X_EXT_IPSECIF",
+       "SADB_X_EXT_ADDR_RANGE_SRC_START",
+       "SADB_X_EXT_ADDR_RANGE_SRC_END",
+       "SADB_X_EXT_ADDR_RANGE_DST_START",
+       "SADB_X_EXT_ADDR_RANGE_DST_END",
+       "SADB_EXT_MIGRATE_ADDRESS_SRC",
+       "SADB_EXT_MIGRATE_ADDRESS_DST",
+       "SADB_X_EXT_MIGRATE_IPSECIF",
+#else
        "SADB_X_EXT_NAT_T_TYPE",
        "SADB_X_EXT_NAT_T_SPORT",
        "SADB_X_EXT_NAT_T_DPORT",
+#ifdef __linux__
        "SADB_X_EXT_NAT_T_OA",
        "SADB_X_EXT_SEC_CTX",
-       "SADB_X_EXT_KMADDRESS"
+       "SADB_X_EXT_KMADDRESS",
+#else
+       "SADB_X_EXT_NAT_T_OAI",
+       "SADB_X_EXT_NAT_T_OAR",
+       "SADB_X_EXT_NAT_T_FRAG",
+       "SADB_X_EXT_SA_REPLAY",
+       "SADB_X_EXT_NEW_ADDRESS_SRC",
+       "SADB_X_EXT_NEW_ADDRESS_DST",
+#endif /* __linux__ */
+#endif /* __APPLE__ */
 );
 
 /**
@@ -1145,6 +1182,23 @@ static status_t pfkey_send_socket(private_kernel_pfkey_ipsec_t *this, int socket
 
        this->mutex_pfkey->lock(this->mutex_pfkey);
 
+       /* the kernel may broadcast messages not related to our requests (e.g. when
+        * managing SAs and policies via an external tool), so let's clear the
+        * receive buffer so there is room for our request and its reply. */
+       while (TRUE)
+       {
+               len = recv(socket, buf, sizeof(buf), MSG_DONTWAIT);
+
+               if (len < 0)
+               {
+                       if (errno == EINTR)
+                       {       /* interrupted, try again */
+                               continue;
+                       }
+                       break;
+               }
+       }
+
        /* FIXME: our usage of sequence numbers is probably wrong. check RFC 2367,
         * in particular the behavior in response to an SADB_ACQUIRE. */
        in->sadb_msg_seq = ++this->seq;
@@ -1760,6 +1814,17 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                        sa->sadb_sa_replay = min((data->replay_window + 7) / 8, UINT8_MAX);
 #endif
                }
+               if (data->esn)
+               {
+#ifdef SADB_X_SAFLAGS_ESN
+                       DBG2(DBG_KNL, "  using extended sequence numbers (ESN)");
+                       sa->sadb_sa_flags |= SADB_X_SAFLAGS_ESN;
+#else
+                       DBG1(DBG_KNL, "extended sequence numbers (ESN) not supported by "
+                                "kernel!");
+                       return FAILED;
+#endif
+               }
                sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, data->int_alg);
                sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM,
                                                                                           data->enc_alg);
index 6fb6673..77c9630 100644 (file)
@@ -749,7 +749,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
                ike.local_port = charon->socket->get_port(charon->socket, FALSE);
        }
        ike_cfg = ike_cfg_create(&ike);
-       ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
+       ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal, 0));
        peer_cfg = peer_cfg_create("load-test", ike_cfg, &peer);
 
        if (this->vip)
@@ -784,7 +784,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
        }
 
        child_cfg = child_cfg_create("load-test", &child);
-       child_cfg->add_proposal(child_cfg, this->esp->clone(this->esp));
+       child_cfg->add_proposal(child_cfg, this->esp->clone(this->esp, 0));
 
        if (num)
        {       /* initiator */
index ad84818..2953a60 100644 (file)
@@ -56,7 +56,9 @@ ENUM(ike_sa_state_lower_names, IKE_CREATED, IKE_DELETING,
        "created",
        "connecting",
        "established",
+       "passive",
        "rekeying",
+       "rekeyed",
        "deleting",
 );
 
index d767148..92b18a8 100644 (file)
@@ -849,6 +849,7 @@ static void list_algs(FILE *out)
        hash_algorithm_t hash;
        pseudo_random_function_t prf;
        ext_out_function_t xof;
+       drbg_type_t drbg;
        diffie_hellman_group_t group;
        rng_quality_t quality;
        const char *plugin_name;
@@ -904,6 +905,14 @@ static void list_algs(FILE *out)
                print_alg(out, &len, ext_out_function_names, xof, plugin_name);
        }
        enumerator->destroy(enumerator);
+       fprintf(out, "\n  drbg:      ");
+       len = 13;
+       enumerator = lib->crypto->create_drbg_enumerator(lib->crypto);
+       while (enumerator->enumerate(enumerator, &drbg, &plugin_name))
+       {
+               print_alg(out, &len, drbg_type_names, drbg, plugin_name);
+       }
+       enumerator->destroy(enumerator);
        fprintf(out, "\n  dh-group:  ");
        len = 13;
        enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
index 346ffb5..81d692c 100644 (file)
@@ -111,6 +111,9 @@ struct private_vici_query_t {
        time_t uptime;
 };
 
+/**
+ * Add the given mark/mask to the message using the provided labels
+ */
 static void add_mark(vici_builder_t *b, mark_t mark,
                                         char *label, char *mask_label)
 {
@@ -148,115 +151,143 @@ static void list_mode(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
 }
 
 /**
- * List details of a CHILD_SA
+ * List IPsec-related details about a CHILD_SA
  */
-static void list_child(private_vici_query_t *this, vici_builder_t *b,
-                                          child_sa_t *child, time_t now)
+static void list_child_ipsec(vici_builder_t *b, child_sa_t *child)
 {
-       time_t t;
-       uint64_t bytes, packets;
-       uint32_t if_id;
-       uint16_t alg, ks;
        proposal_t *proposal;
-       enumerator_t *enumerator;
-       traffic_selector_t *ts;
+       uint16_t alg, ks;
+       uint32_t if_id;
 
-       b->add_kv(b, "name", "%s", child->get_name(child));
-       b->add_kv(b, "uniqueid", "%u", child->get_unique_id(child));
-       b->add_kv(b, "reqid", "%u", child->get_reqid(child));
-       b->add_kv(b, "state", "%N", child_sa_state_names, child->get_state(child));
-       list_mode(b, child, NULL);
-       if (child->get_state(child) == CHILD_INSTALLED ||
-               child->get_state(child) == CHILD_REKEYING ||
-               child->get_state(child) == CHILD_REKEYED)
+       b->add_kv(b, "protocol", "%N", protocol_id_names,
+                         child->get_protocol(child));
+       if (child->has_encap(child))
        {
-               b->add_kv(b, "protocol", "%N", protocol_id_names,
-                                 child->get_protocol(child));
-               if (child->has_encap(child))
-               {
-                       b->add_kv(b, "encap", "yes");
-               }
-               b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
-               b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
+               b->add_kv(b, "encap", "yes");
+       }
+       b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
+       b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
 
-               if (child->get_ipcomp(child) != IPCOMP_NONE)
-               {
-                       b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
-                       b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
-               }
-               add_mark(b, child->get_mark(child, TRUE), "mark-in", "mark-mask-in");
-               add_mark(b, child->get_mark(child, FALSE), "mark-out", "mark-mask-out");
-               if_id = child->get_if_id(child, TRUE);
-               if (if_id)
-               {
-                       b->add_kv(b, "if-id-in", "%.8x", if_id);
-               }
-               if_id = child->get_if_id(child, FALSE);
-               if (if_id)
-               {
-                       b->add_kv(b, "if-id-out", "%.8x", if_id);
-               }
-               proposal = child->get_proposal(child);
-               if (proposal)
+       if (child->get_ipcomp(child) != IPCOMP_NONE)
+       {
+               b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
+               b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
+       }
+       add_mark(b, child->get_mark(child, TRUE), "mark-in", "mark-mask-in");
+       add_mark(b, child->get_mark(child, FALSE), "mark-out", "mark-mask-out");
+
+       if_id = child->get_if_id(child, TRUE);
+       if (if_id)
+       {
+               b->add_kv(b, "if-id-in", "%.8x", if_id);
+       }
+       if_id = child->get_if_id(child, FALSE);
+       if (if_id)
+       {
+               b->add_kv(b, "if-id-out", "%.8x", if_id);
+       }
+
+       proposal = child->get_proposal(child);
+       if (proposal)
+       {
+               if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+                                                                       &alg, &ks) && alg != ENCR_UNDEFINED)
                {
-                       if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
-                                                                               &alg, &ks) && alg != ENCR_UNDEFINED)
-                       {
-                               b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
-                               if (ks)
-                               {
-                                       b->add_kv(b, "encr-keysize", "%u", ks);
-                               }
-                       }
-                       if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
-                                                                               &alg, &ks) && alg != AUTH_UNDEFINED)
-                       {
-                               b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
-                               if (ks)
-                               {
-                                       b->add_kv(b, "integ-keysize", "%u", ks);
-                               }
-                       }
-                       if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
-                                                                               &alg, NULL))
+                       b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
+                       if (ks)
                        {
-                               b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
+                               b->add_kv(b, "encr-keysize", "%u", ks);
                        }
-                       if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
-                                                                               &alg, NULL) && alg == EXT_SEQ_NUMBERS)
+               }
+               if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+                                                                       &alg, &ks) && alg != AUTH_UNDEFINED)
+               {
+                       b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
+                       if (ks)
                        {
-                               b->add_kv(b, "esn", "1");
+                               b->add_kv(b, "integ-keysize", "%u", ks);
                        }
                }
-
-               child->get_usestats(child, TRUE,  &t, &bytes, &packets);
-               b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
-               b->add_kv(b, "packets-in", "%" PRIu64, packets);
-               if (t)
+               if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+                                                                       &alg, NULL))
                {
-                       b->add_kv(b, "use-in", "%"PRIu64, (uint64_t)(now - t));
+                       b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
                }
-
-               child->get_usestats(child, FALSE, &t, &bytes, &packets);
-               b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
-               b->add_kv(b, "packets-out", "%"PRIu64, packets);
-               if (t)
+               if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
+                                                                       &alg, NULL) && alg == EXT_SEQ_NUMBERS)
                {
-                       b->add_kv(b, "use-out", "%"PRIu64, (uint64_t)(now - t));
+                       b->add_kv(b, "esn", "1");
                }
+       }
+}
 
-               t = child->get_lifetime(child, FALSE);
-               if (t)
-               {
-                       b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
-               }
-               t = child->get_lifetime(child, TRUE);
-               if (t)
-               {
-                       b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
-               }
-               t = child->get_installtime(child);
-               b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
+/**
+ * List usage and lifetime stats of a CHILD_SA
+ */
+static void list_child_stats(vici_builder_t *b, child_sa_t *child, time_t now)
+{
+       uint64_t bytes, packets;
+       time_t t;
+
+       child->get_usestats(child, TRUE,  &t, &bytes, &packets);
+       b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
+       b->add_kv(b, "packets-in", "%" PRIu64, packets);
+       if (t)
+       {
+               b->add_kv(b, "use-in", "%"PRIu64, (uint64_t)(now - t));
+       }
+
+       child->get_usestats(child, FALSE, &t, &bytes, &packets);
+       b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
+       b->add_kv(b, "packets-out", "%"PRIu64, packets);
+       if (t)
+       {
+               b->add_kv(b, "use-out", "%"PRIu64, (uint64_t)(now - t));
+       }
+
+       t = child->get_lifetime(child, FALSE);
+       if (t)
+       {
+               b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
+       }
+       t = child->get_lifetime(child, TRUE);
+       if (t)
+       {
+               b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
+       }
+       t = child->get_installtime(child);
+       b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
+}
+
+/**
+ * List details of a CHILD_SA
+ */
+static void list_child(private_vici_query_t *this, vici_builder_t *b,
+                                          child_sa_t *child, time_t now)
+{
+       enumerator_t *enumerator;
+       traffic_selector_t *ts;
+       child_sa_state_t state;
+
+       b->add_kv(b, "name", "%s", child->get_name(child));
+       b->add_kv(b, "uniqueid", "%u", child->get_unique_id(child));
+       b->add_kv(b, "reqid", "%u", child->get_reqid(child));
+       state = child->get_state(child);
+       b->add_kv(b, "state", "%N", child_sa_state_names, state);
+       list_mode(b, child, NULL);
+
+       switch (state)
+       {
+               case CHILD_INSTALLED:
+               case CHILD_REKEYING:
+               case CHILD_REKEYED:
+               case CHILD_DELETING:
+               case CHILD_DELETED:
+                       list_child_ipsec(b, child);
+                       list_child_stats(b, child, now);
+                       break;
+               default:
+                       break;
        }
 
        b->begin_list(b, "local-ts");
@@ -1231,6 +1262,7 @@ CALLBACK(get_algorithms, vici_message_t*,
        hash_algorithm_t hash;
        pseudo_random_function_t prf;
        ext_out_function_t xof;
+       drbg_type_t drbg;
        diffie_hellman_group_t group;
        rng_quality_t quality;
        const char *plugin_name;
@@ -1291,6 +1323,15 @@ CALLBACK(get_algorithms, vici_message_t*,
        enumerator->destroy(enumerator);
        b->end_section(b);
 
+       b->begin_section(b, "drbg");
+       enumerator = lib->crypto->create_drbg_enumerator(lib->crypto);
+       while (enumerator->enumerate(enumerator, &drbg, &plugin_name))
+       {
+               add_algorithm(b, drbg_type_names, drbg, plugin_name);
+       }
+       enumerator->destroy(enumerator);
+       b->end_section(b);
+
        b->begin_section(b, "dh");
        enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
        while (enumerator->enumerate(enumerator, &group, &plugin_name))
index fc60b41..b11236b 100644 (file)
@@ -429,7 +429,7 @@ METHOD(child_sa_t, get_proposal, proposal_t*,
 METHOD(child_sa_t, set_proposal, void,
           private_child_sa_t *this, proposal_t *proposal)
 {
-       this->proposal = proposal->clone(proposal);
+       this->proposal = proposal->clone(proposal, 0);
 }
 
 METHOD(child_sa_t, create_ts_enumerator, enumerator_t*,
index 4e60ed8..d6cc4e5 100644 (file)
@@ -610,7 +610,7 @@ METHOD(ike_sa_t, set_proposal, void,
        private_ike_sa_t *this, proposal_t *proposal)
 {
        DESTROY_IF(this->proposal);
-       this->proposal = proposal->clone(proposal);
+       this->proposal = proposal->clone(proposal, 0);
 }
 
 METHOD(ike_sa_t, set_message_id, void,
index 023119d..94c3b76 100644 (file)
@@ -374,8 +374,8 @@ METHOD(task_t, process_r, status_t,
                        id_payload_t *id_payload;
                        identification_t *id;
                        linked_list_t *list;
+                       proposal_selection_flag_t flags = PROPOSAL_SKIP_PRIVATE;
                        uint16_t group;
-                       bool prefer_configured;
 
                        this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
                        DBG0(DBG_IKE, "%H is initiating a Aggressive Mode IKE_SA",
@@ -399,10 +399,13 @@ METHOD(task_t, process_r, status_t,
                        }
 
                        list = sa_payload->get_proposals(sa_payload);
-                       prefer_configured = lib->settings->get_bool(lib->settings,
-                                                       "%s.prefer_configured_proposals", TRUE, lib->ns);
-                       this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
-                                                                                               list, FALSE, prefer_configured);
+                       if (!lib->settings->get_bool(lib->settings,
+                                               "%s.prefer_configured_proposals", TRUE, lib->ns))
+                       {
+                               flags = PROPOSAL_PREFER_SUPPLIED;
+                       }
+                       this->proposal = this->ike_cfg->select_proposal(this->ike_cfg, list,
+                                                                                                                       flags);
                        list->destroy_offset(list, offsetof(proposal_t, destroy));
                        if (!this->proposal)
                        {
@@ -641,8 +644,7 @@ METHOD(task_t, process_i, status_t,
                        return send_notify(this, INVALID_PAYLOAD_TYPE);
                }
                list = sa_payload->get_proposals(sa_payload);
-               this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
-                                                                                                               list, FALSE, TRUE);
+               this->proposal = this->ike_cfg->select_proposal(this->ike_cfg, list, 0);
                list->destroy_offset(list, offsetof(proposal_t, destroy));
                if (!this->proposal)
                {
index b60c849..43848ad 100644 (file)
@@ -362,7 +362,7 @@ METHOD(task_t, process_r, status_t,
                {
                        linked_list_t *list;
                        sa_payload_t *sa_payload;
-                       bool private, prefer_configured;
+                       proposal_selection_flag_t flags = 0;
 
                        this->ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
                        DBG0(DBG_IKE, "%H is initiating a Main Mode IKE_SA",
@@ -386,12 +386,17 @@ METHOD(task_t, process_r, status_t,
                        }
 
                        list = sa_payload->get_proposals(sa_payload);
-                       private = this->ike_sa->supports_extension(this->ike_sa,
-                                                                                                          EXT_STRONGSWAN);
-                       prefer_configured = lib->settings->get_bool(lib->settings,
-                                                       "%s.prefer_configured_proposals", TRUE, lib->ns);
+                       if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
+                       {
+                               flags |= PROPOSAL_SKIP_PRIVATE;
+                       }
+                       if (!lib->settings->get_bool(lib->settings,
+                                                       "%s.prefer_configured_proposals", TRUE, lib->ns))
+                       {
+                               flags |= PROPOSAL_PREFER_SUPPLIED;
+                       }
                        this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
-                                                                                       list, private, prefer_configured);
+                                                                                       list, flags);
                        list->destroy_offset(list, offsetof(proposal_t, destroy));
                        if (!this->proposal)
                        {
@@ -624,8 +629,8 @@ METHOD(task_t, process_i, status_t,
                        linked_list_t *list;
                        sa_payload_t *sa_payload;
                        auth_method_t method;
+                       proposal_selection_flag_t flags = 0;
                        uint32_t lifetime;
-                       bool private;
 
                        sa_payload = (sa_payload_t*)message->get_payload(message,
                                                                                                        PLV1_SECURITY_ASSOCIATION);
@@ -635,10 +640,12 @@ METHOD(task_t, process_i, status_t,
                                return send_notify(this, INVALID_PAYLOAD_TYPE);
                        }
                        list = sa_payload->get_proposals(sa_payload);
-                       private = this->ike_sa->supports_extension(this->ike_sa,
-                                                                                                                  EXT_STRONGSWAN);
+                       if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
+                       {
+                               flags |= PROPOSAL_SKIP_PRIVATE;
+                       }
                        this->proposal = this->ike_cfg->select_proposal(this->ike_cfg,
-                                                                                                                       list, private, TRUE);
+                                                                                                                       list, flags);
                        list->destroy_offset(list, offsetof(proposal_t, destroy));
                        if (!this->proposal)
                        {
index 128f027..9ded2dd 100644 (file)
@@ -802,7 +802,7 @@ static linked_list_t *get_proposals(private_quick_mode_t *this,
                                proposal->destroy(proposal);
                                continue;
                        }
-                       proposal->strip_dh(proposal, group);
+                       proposal->promote_dh_group(proposal, group);
                }
                proposal->set_spi(proposal, this->spi_i);
        }
@@ -852,7 +852,7 @@ METHOD(task_t, build_i, status_t,
                                }
                        }
 
-                       list = this->config->get_proposals(this->config, MODP_NONE);
+                       list = this->config->get_proposals(this->config, FALSE);
                        if (list->get_first(list, (void**)&proposal) == SUCCESS)
                        {
                                this->proto = proposal->get_protocol(proposal);
@@ -1072,7 +1072,7 @@ METHOD(task_t, process_r, status_t,
                        linked_list_t *tsi, *tsr, *hostsi, *hostsr, *list = NULL;
                        peer_cfg_t *peer_cfg;
                        uint16_t group;
-                       bool private, prefer_configured;
+                       proposal_selection_flag_t flags = 0;
 
                        sa_payload = (sa_payload_t*)message->get_payload(message,
                                                                                                        PLV1_SECURITY_ASSOCIATION);
@@ -1132,12 +1132,17 @@ METHOD(task_t, process_r, status_t,
                                DESTROY_IF(list);
                                list = sa_payload->get_proposals(sa_payload);
                        }
-                       private = this->ike_sa->supports_extension(this->ike_sa,
-                                                                                                          EXT_STRONGSWAN);
-                       prefer_configured = lib->settings->get_bool(lib->settings,
-                                                       "%s.prefer_configured_proposals", TRUE, lib->ns);
+                       if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
+                       {
+                               flags |= PROPOSAL_SKIP_PRIVATE;
+                       }
+                       if (!lib->settings->get_bool(lib->settings,
+                                                       "%s.prefer_configured_proposals", TRUE, lib->ns))
+                       {
+                               flags |= PROPOSAL_PREFER_SUPPLIED;
+                       }
                        this->proposal = this->config->select_proposal(this->config, list,
-                                                                                       FALSE, private, prefer_configured);
+                                                                                                                  flags);
                        list->destroy_offset(list, offsetof(proposal_t, destroy));
 
                        get_lifetimes(this);
@@ -1340,7 +1345,7 @@ METHOD(task_t, process_i, status_t,
                {
                        sa_payload_t *sa_payload;
                        linked_list_t *list = NULL;
-                       bool private;
+                       proposal_selection_flag_t flags = 0;
 
                        sa_payload = (sa_payload_t*)message->get_payload(message,
                                                                                                        PLV1_SECURITY_ASSOCIATION);
@@ -1365,10 +1370,12 @@ METHOD(task_t, process_i, status_t,
                                DESTROY_IF(list);
                                list = sa_payload->get_proposals(sa_payload);
                        }
-                       private = this->ike_sa->supports_extension(this->ike_sa,
-                                                                                                          EXT_STRONGSWAN);
+                       if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
+                       {
+                               flags |= PROPOSAL_SKIP_PRIVATE;
+                       }
                        this->proposal = this->config->select_proposal(this->config, list,
-                                                                                                               FALSE, private, TRUE);
+                                                                                                                  flags);
                        list->destroy_offset(list, offsetof(proposal_t, destroy));
                        if (!this->proposal)
                        {
index ac1f999..e98c1db 100644 (file)
@@ -544,7 +544,7 @@ static status_t select_and_install(private_child_create_t *this,
        chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
        linked_list_t *my_ts, *other_ts;
        host_t *me, *other;
-       bool private, prefer_configured;
+       proposal_selection_flag_t flags = 0;
 
        if (this->proposals == NULL)
        {
@@ -560,11 +560,21 @@ static status_t select_and_install(private_child_create_t *this,
        me = this->ike_sa->get_my_host(this->ike_sa);
        other = this->ike_sa->get_other_host(this->ike_sa);
 
-       private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
-       prefer_configured = lib->settings->get_bool(lib->settings,
-                                                       "%s.prefer_configured_proposals", TRUE, lib->ns);
+       if (no_dh)
+       {
+               flags |= PROPOSAL_SKIP_DH;
+       }
+       if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
+       {
+               flags |= PROPOSAL_SKIP_PRIVATE;
+       }
+       if (!lib->settings->get_bool(lib->settings,
+                                                       "%s.prefer_configured_proposals", TRUE, lib->ns))
+       {
+               flags |= PROPOSAL_PREFER_SUPPLIED;
+       }
        this->proposal = this->config->select_proposal(this->config,
-                                                       this->proposals, no_dh, private, prefer_configured);
+                                                                                                  this->proposals, flags);
        if (this->proposal == NULL)
        {
                DBG1(DBG_IKE, "no acceptable proposal found");
index fd36b14..49cd663 100644 (file)
@@ -168,6 +168,33 @@ METHOD(task_t, process_r, status_t,
        return NEED_MORE;
 }
 
+/**
+ * Check if we are currently deleting this IKE_SA in a break-before-make reauth.
+ */
+static bool is_reauthenticating(private_ike_delete_t *this)
+{
+       enumerator_t *tasks;
+       task_t *task;
+
+       if (!this->ike_sa->has_condition(this->ike_sa, COND_REAUTHENTICATING))
+       {
+               return FALSE;
+       }
+
+       tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
+                                                                                                TASK_QUEUE_ACTIVE);
+       while (tasks->enumerate(tasks, &task))
+       {
+               if (task->get_type(task) == TASK_IKE_REAUTH)
+               {
+                       tasks->destroy(tasks);
+                       return TRUE;
+               }
+       }
+       tasks->destroy(tasks);
+       return FALSE;
+}
+
 METHOD(task_t, build_r, status_t,
        private_ike_delete_t *this, message_t *message)
 {
@@ -177,6 +204,18 @@ METHOD(task_t, build_r, status_t,
        {       /* invoke ike_down() hook if SA has not been rekeyed */
                charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
        }
+
+       /* if we are currently deleting this IKE_SA due to a break-before-make
+        * reauthentication, make sure to not just silently destroy the SA if
+        * the peer concurrently deletes it */
+       if (is_reauthenticating(this))
+       {
+               if (this->ike_sa->reestablish(this->ike_sa) != SUCCESS)
+               {
+                       DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
+               }
+       }
+
        /* completed, delete IKE_SA by returning DESTROY_ME */
        return DESTROY_ME;
 }
index 04ce504..d15b5b1 100644 (file)
@@ -453,17 +453,21 @@ static void process_sa_payload(private_ike_init_t *this, message_t *message,
        enumerator_t *enumerator;
        linked_list_t *proposal_list;
        host_t *me, *other;
-       bool private, prefer_configured;
+       proposal_selection_flag_t flags = 0;
 
        ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
 
        proposal_list = sa_payload->get_proposals(sa_payload);
-       private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
-       prefer_configured = lib->settings->get_bool(lib->settings,
-                                                       "%s.prefer_configured_proposals", TRUE, lib->ns);
-
-       this->proposal = ike_cfg->select_proposal(ike_cfg, proposal_list, private,
-                                                                                         prefer_configured);
+       if (!this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
+       {
+               flags |= PROPOSAL_SKIP_PRIVATE;
+       }
+       if (!lib->settings->get_bool(lib->settings,
+                                                       "%s.prefer_configured_proposals", TRUE, lib->ns))
+       {
+               flags |= PROPOSAL_PREFER_SUPPLIED;
+       }
+       this->proposal = ike_cfg->select_proposal(ike_cfg, proposal_list, flags);
        if (!this->proposal)
        {
                if (!this->initiator && !this->old_sa)
@@ -481,7 +485,7 @@ static void process_sa_payload(private_ike_init_t *this, message_t *message,
                                DBG1(DBG_IKE, "no matching proposal found, trying alternative "
                                         "config");
                                this->proposal = cfg->select_proposal(cfg, proposal_list,
-                                                                                                       private, prefer_configured);
+                                                                                                         flags);
                                if (this->proposal)
                                {
                                        alt_cfg = cfg->get_ref(cfg);
index 77fe6eb..fda7463 100644 (file)
@@ -5,11 +5,13 @@ library.c \
 asn1/asn1.c asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
 collections/blocking_queue.c collections/enumerator.c collections/hashtable.c \
 collections/array.c \
-collections/linked_list.c crypto/crypters/crypter.c crypto/hashers/hasher.c \
+collections/linked_list.c crypto/crypters/crypter.c \
+crypto/drbgs/drbg.c crypto/hashers/hasher.c \
 crypto/hashers/hash_algorithm_set.c crypto/proposal/proposal.c \
 crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords_static.c \
 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/rngs/rng.c crypto/rngs/rng_tester.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.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
@@ -68,10 +70,11 @@ library.h \
 asn1/asn1.h asn1/asn1_parser.h asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
 collections/blocking_queue.h collections/enumerator.h collections/hashtable.h \
 collections/linked_list.h collections/array.h collections/dictionary.h \
-crypto/crypters/crypter.h crypto/hashers/hasher.h \
+crypto/crypters/crypter.h crypto/drbgs/drbg.h crypto/hashers/hasher.h \
 crypto/hashers/hash_algorithm_set.h crypto/mac.h crypto/proposal/proposal.h \
 crypto/proposal/proposal_keywords.h crypto/proposal/proposal_keywords_static.h \
-crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
+crypto/rngs/rng.h crypto/rngs/rng_tester.h \
+crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/nonce_gen.h \
 crypto/prf_plus.h crypto/signers/signer.h crypto/signers/mac_signer.h \
 crypto/crypto_factory.h crypto/crypto_tester.h crypto/diffie_hellman.h \
 crypto/aead.h crypto/transform.h crypto/pkcs5.h crypto/iv/iv_gen.h \
@@ -663,6 +666,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_DRBG
+  SUBDIRS += plugins/drbg
+if MONOLITHIC
+  libstrongswan_la_LIBADD += plugins/drbg/libstrongswan-drbg.la
+endif
+endif
+
 if USE_TEST_VECTORS
   SUBDIRS += plugins/test_vectors
 if MONOLITHIC
index 096bcbc..62b9806 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2013-2014 Tobias Brunner
  * Copyright (C) 2008 Martin Willi
- * Copyright (C) 2016 Andreas Steffen
+ * Copyright (C) 2016-2019 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -53,6 +53,7 @@ struct entry_t {
                hasher_constructor_t create_hasher;
                prf_constructor_t create_prf;
                xof_constructor_t create_xof;
+               drbg_constructor_t create_drbg;
                rng_constructor_t create_rng;
                nonce_gen_constructor_t create_nonce_gen;
                dh_constructor_t create_dh;
@@ -103,6 +104,11 @@ struct private_crypto_factory_t {
        linked_list_t *xofs;
 
        /**
+        * registered drbgs, as entry_t
+        */
+       linked_list_t *drbgs;
+
+       /**
         * registered rngs, as entry_t
         */
        linked_list_t *rngs;
@@ -342,6 +348,40 @@ METHOD(crypto_factory_t, create_xof, xof_t*,
        return xof;
 }
 
+METHOD(crypto_factory_t, create_drbg, drbg_t*,
+       private_crypto_factory_t *this, drbg_type_t type, uint32_t strength,
+       rng_t *entropy, chunk_t personalization_str)
+{
+       enumerator_t *enumerator;
+       entry_t *entry;
+       drbg_t *drbg = NULL;
+
+       this->lock->read_lock(this->lock);
+       enumerator = this->drbgs->create_enumerator(this->drbgs);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               if (entry->algo == type)
+               {
+                       if (this->test_on_create &&
+                               !this->tester->test_drbg(this->tester, type,
+                                                                                entry->create_drbg, NULL,
+                                                                                default_plugin_name))
+                       {
+                               continue;
+                       }
+                       drbg = entry->create_drbg(type, strength, entropy,
+                                                                         personalization_str);
+                       if (drbg)
+                       {
+                               break;
+                       }
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->lock->unlock(this->lock);
+       return drbg;
+}
+
 METHOD(crypto_factory_t, create_rng, rng_t*,
        private_crypto_factory_t *this, rng_quality_t quality)
 {
@@ -709,6 +749,43 @@ METHOD(crypto_factory_t, remove_xof, void,
        this->lock->unlock(this->lock);
 }
 
+METHOD(crypto_factory_t, add_drbg, bool,
+       private_crypto_factory_t *this, drbg_type_t type,
+       const char *plugin_name, drbg_constructor_t create)
+{
+       u_int speed = 0;
+
+       if (!this->test_on_add ||
+               this->tester->test_drbg(this->tester, type, create,
+                                                          this->bench ? &speed : NULL, plugin_name))
+       {
+               add_entry(this, this->drbgs, type, plugin_name, speed, create);
+               return TRUE;
+       }
+       this->test_failures++;
+       return FALSE;
+}
+
+METHOD(crypto_factory_t, remove_drbg, void,
+       private_crypto_factory_t *this, drbg_constructor_t create)
+{
+       entry_t *entry;
+       enumerator_t *enumerator;
+
+       this->lock->write_lock(this->lock);
+       enumerator = this->drbgs->create_enumerator(this->drbgs);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               if (entry->create_drbg == create)
+               {
+                       this->drbgs->remove_at(this->drbgs, enumerator);
+                       free(entry);
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->lock->unlock(this->lock);
+}
+
 METHOD(crypto_factory_t, add_rng, bool,
        private_crypto_factory_t *this, rng_quality_t quality,
        const char *plugin_name, rng_constructor_t create)
@@ -981,6 +1058,30 @@ METHOD(crypto_factory_t, create_xof_enumerator, enumerator_t*,
        return create_enumerator(this, this->xofs, xof_filter);
 }
 
+CALLBACK(drbg_filter, bool,
+       void *n, enumerator_t *orig, va_list args)
+{
+       entry_t *entry;
+       drbg_type_t *type;
+       const char **plugin_name;
+
+       VA_ARGS_VGET(args, type, plugin_name);
+
+       if (orig->enumerate(orig, &entry))
+       {
+               *type = entry->algo;
+               *plugin_name = entry->plugin_name;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+METHOD(crypto_factory_t, create_drbg_enumerator, enumerator_t*,
+       private_crypto_factory_t *this)
+{
+       return create_enumerator(this, this->drbgs, drbg_filter);
+}
+
 CALLBACK(dh_filter, bool,
        void *n, enumerator_t *orig, va_list args)
 {
@@ -1068,6 +1169,8 @@ METHOD(crypto_factory_t, add_test_vector, void,
                        return this->tester->add_prf_vector(this->tester, vector);
                case EXTENDED_OUTPUT_FUNCTION:
                        return this->tester->add_xof_vector(this->tester, vector);
+               case DETERMINISTIC_RANDOM_BIT_GENERATOR:
+                       return this->tester->add_drbg_vector(this->tester, vector);
                case RANDOM_NUMBER_GENERATOR:
                        return this->tester->add_rng_vector(this->tester, vector);
                case DIFFIE_HELLMAN_GROUP:
@@ -1129,6 +1232,10 @@ METHOD(enumerator_t, verify_enumerate, bool,
                        *valid = this->tester->test_xof(this->tester, entry->algo,
                                                        entry->create_xof, NULL, entry->plugin_name);
                        break;
+               case DETERMINISTIC_RANDOM_BIT_GENERATOR:
+                       *valid = this->tester->test_drbg(this->tester, entry->algo,
+                                                       entry->create_drbg, 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);
@@ -1180,6 +1287,9 @@ METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
                case EXTENDED_OUTPUT_FUNCTION:
                        inner = this->xofs->create_enumerator(this->xofs);
                        break;
+               case DETERMINISTIC_RANDOM_BIT_GENERATOR:
+                       inner = this->drbgs->create_enumerator(this->drbgs);
+                       break;
                case RANDOM_NUMBER_GENERATOR:
                        inner = this->rngs->create_enumerator(this->rngs);
                        break;
@@ -1213,6 +1323,7 @@ METHOD(crypto_factory_t, destroy, void,
        this->hashers->destroy(this->hashers);
        this->prfs->destroy(this->prfs);
        this->xofs->destroy(this->xofs);
+       this->drbgs->destroy(this->drbgs);
        this->rngs->destroy(this->rngs);
        this->nonce_gens->destroy(this->nonce_gens);
        this->dhs->destroy(this->dhs);
@@ -1236,6 +1347,7 @@ crypto_factory_t *crypto_factory_create()
                        .create_hasher = _create_hasher,
                        .create_prf = _create_prf,
                        .create_xof = _create_xof,
+                       .create_drbg = _create_drbg,
                        .create_rng = _create_rng,
                        .create_nonce_gen = _create_nonce_gen,
                        .create_dh = _create_dh,
@@ -1251,6 +1363,8 @@ crypto_factory_t *crypto_factory_create()
                        .remove_prf = _remove_prf,
                        .add_xof = _add_xof,
                        .remove_xof = _remove_xof,
+                       .add_drbg = _add_drbg,
+                       .remove_drbg = _remove_drbg,
                        .add_rng = _add_rng,
                        .remove_rng = _remove_rng,
                        .add_nonce_gen = _add_nonce_gen,
@@ -1263,6 +1377,7 @@ crypto_factory_t *crypto_factory_create()
                        .create_hasher_enumerator = _create_hasher_enumerator,
                        .create_prf_enumerator = _create_prf_enumerator,
                        .create_xof_enumerator = _create_xof_enumerator,
+                       .create_drbg_enumerator = _create_drbg_enumerator,
                        .create_dh_enumerator = _create_dh_enumerator,
                        .create_rng_enumerator = _create_rng_enumerator,
                        .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
@@ -1276,6 +1391,7 @@ crypto_factory_t *crypto_factory_create()
                .hashers = linked_list_create(),
                .prfs = linked_list_create(),
                .xofs = linked_list_create(),
+               .drbgs = linked_list_create(),
                .rngs = linked_list_create(),
                .nonce_gens = linked_list_create(),
                .dhs = linked_list_create(),
index 7f048c6..87e2cd2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 Martin Willi
- * Copyright (C) 2016 Andreas Steffen
+ * Copyright (C) 2016-2019 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@ typedef struct crypto_factory_t crypto_factory_t;
 #include <crypto/prfs/prf.h>
 #include <crypto/rngs/rng.h>
 #include <crypto/xofs/xof.h>
+#include <crypto/drbgs/drbg.h>
 #include <crypto/nonce_gen.h>
 #include <crypto/diffie_hellman.h>
 #include <crypto/transform.h>
@@ -65,11 +66,17 @@ typedef hasher_t* (*hasher_constructor_t)(hash_algorithm_t algo);
 typedef prf_t* (*prf_constructor_t)(pseudo_random_function_t algo);
 
 /**
- * Constructor function for pseudo random functions
+ * Constructor function for extended output functions
  */
 typedef xof_t* (*xof_constructor_t)(ext_out_function_t algo);
 
 /**
+ * Constructor function for deterministic random bit generators
+ */
+typedef drbg_t* (*drbg_constructor_t)(drbg_type_t type, uint32_t strength,
+                                                               rng_t *entropy, chunk_t personalization_str);
+
+/**
  * Constructor function for source of randomness
  */
 typedef rng_t* (*rng_constructor_t)(rng_quality_t quality);
@@ -148,6 +155,19 @@ struct crypto_factory_t {
        xof_t* (*create_xof)(crypto_factory_t *this, ext_out_function_t algo);
 
        /**
+        * Create a deterministic random bit generator instance.
+        *
+        * @param type                                  DRBG type to use
+        * @param strength                              security strength in bits
+        * @param entropy                               entropy source to be used
+        * @param personalization_str   optional personalization string
+        * @return                                              drbg_t instance, NULL if not supported
+        */
+       drbg_t* (*create_drbg)(crypto_factory_t *this, drbg_type_t type,
+                                                  uint32_t strength, rng_t *entropy,
+                                                  chunk_t personalization_str);
+
+       /**
         * Create a source of randomness.
         *
         * @param quality               required randomness quality
@@ -286,6 +306,24 @@ struct crypto_factory_t {
        void (*remove_xof)(crypto_factory_t *this, xof_constructor_t create);
 
        /**
+        * Register a drbg constructor.
+        *
+        * @param type                  type to constructor
+        * @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_drbg)(crypto_factory_t *this, drbg_type_t type,
+                                        const char *plugin_name, drbg_constructor_t create);
+
+       /**
+        * Unregister a drbg constructor.
+        *
+        * @param create                constructor function to unregister
+        */
+       void (*remove_drbg)(crypto_factory_t *this, drbg_constructor_t create);
+
+       /**
         * Register a source of randomness.
         *
         * @param quality               quality of randomness this RNG serves
@@ -382,6 +420,13 @@ struct crypto_factory_t {
        enumerator_t* (*create_xof_enumerator)(crypto_factory_t *this);
 
        /**
+        * Create an enumerator over all registered DRBGs.
+        *
+        * @return                              enumerator over drbg_type_t, plugin
+        */
+       enumerator_t* (*create_drbg_enumerator)(crypto_factory_t *this);
+
+       /**
         * Create an enumerator over all registered diffie hellman groups.
         *
         * @return                              enumerator over diffie_hellman_group_t, plugin
index f0f64ce..a04543e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009-2010 Martin Willi
+ * Copyright (C) 2016-2019 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  * Copyright (C) 2010 revosec AG
  *
@@ -24,6 +25,7 @@
 
 #include <utils/debug.h>
 #include <collections/linked_list.h>
+#include <crypto/rngs/rng_tester.h>
 
 typedef struct private_crypto_tester_t private_crypto_tester_t;
 
@@ -68,6 +70,11 @@ struct private_crypto_tester_t {
        linked_list_t *xof;
 
        /**
+        * List of DRBG test vectors
+        */
+       linked_list_t *drbg;
+
+       /**
         * List of RNG test vectors
         */
        linked_list_t *rng;
@@ -1180,6 +1187,133 @@ failure:
 }
 
 /**
+ * Benchmark a DRBG
+ */
+static u_int bench_drbg(private_crypto_tester_t *this,
+                                               drbg_type_t type, drbg_constructor_t create)
+{
+       drbg_t *drbg;
+       rng_t *entropy;
+       uint32_t strength = 128;
+       chunk_t seed = chunk_alloca(48);
+
+       memset(seed.ptr, 0x81, seed.len);
+       entropy = rng_tester_create(seed);
+
+       drbg = create(type, strength, entropy, chunk_empty);
+       if (drbg)
+       {
+               struct timespec start;
+               u_int runs = 0;
+               size_t out_len = 128;
+               char out_buf[out_len];
+
+               start_timing(&start);
+               while (end_timing(&start) < this->bench_time)
+               {
+                       if (drbg->generate(drbg, out_len, out_buf))
+                       {
+                               runs++;
+                       }
+               }
+               drbg->destroy(drbg);
+
+               return runs;
+       }
+       return 0;
+}
+
+METHOD(crypto_tester_t, test_drbg, bool,
+       private_crypto_tester_t *this, drbg_type_t type,
+       drbg_constructor_t create, u_int *speed, const char *plugin_name)
+{
+       enumerator_t *enumerator;
+       drbg_test_vector_t *vector;
+       bool failed = FALSE;
+       u_int tested = 0;
+
+       enumerator = this->drbg->create_enumerator(this->drbg);
+       while (enumerator->enumerate(enumerator, &vector))
+       {
+               drbg_t *drbg;
+               rng_t *entropy;
+               chunk_t out = chunk_empty;
+
+               if (vector->type != type)
+               {
+                       continue;
+               }
+               tested++;
+               failed = TRUE;
+
+               entropy = rng_tester_create(vector->entropy);
+               out = chunk_alloc(vector->out.len);
+
+               drbg = create(type, vector->strength, entropy,
+                                         vector->personalization_str);
+               if (!drbg)
+               {
+                       DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
+                                drbg_type_names, type, plugin_name);
+                       entropy->destroy(entropy);
+                       chunk_free(&out);
+                       break;
+               }
+               if (!drbg->reseed(drbg))
+               {
+                       goto failure;
+               }
+               if (!drbg->generate(drbg, out.len, out.ptr))
+               {
+                       goto failure;
+               }
+               if (!drbg->generate(drbg, out.len, out.ptr))
+               {
+                       goto failure;
+               }
+               if (!chunk_equals(out, vector->out))
+               {
+                       goto failure;
+               }
+               failed = FALSE;
+
+failure:
+               drbg->destroy(drbg);
+               entropy->destroy(entropy);
+               chunk_free(&out);
+               if (failed)
+               {
+                       DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
+                                drbg_type_names, type, plugin_name, get_name(vector));
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+       if (!tested)
+       {
+               DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
+                        this->required ? "disabled" : "enabled ",
+                        drbg_type_names, type, plugin_name);
+               return !this->required;
+       }
+       if (!failed)
+       {
+               if (speed)
+               {
+                       *speed = bench_drbg(this, type, create);
+                       DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
+                                drbg_type_names, type, plugin_name, tested, *speed);
+               }
+               else
+               {
+                       DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
+                                drbg_type_names, type, plugin_name, tested);
+               }
+       }
+       return !failed;
+}
+
+/**
  * Benchmark a RNG
  */
 static u_int bench_rng(private_crypto_tester_t *this,
@@ -1489,6 +1623,12 @@ METHOD(crypto_tester_t, add_xof_vector, void,
        this->xof->insert_last(this->xof, vector);
 }
 
+METHOD(crypto_tester_t, add_drbg_vector, void,
+       private_crypto_tester_t *this, drbg_test_vector_t *vector)
+{
+       this->drbg->insert_last(this->drbg, vector);
+}
+
 METHOD(crypto_tester_t, add_rng_vector, void,
        private_crypto_tester_t *this, rng_test_vector_t *vector)
 {
@@ -1510,6 +1650,7 @@ METHOD(crypto_tester_t, destroy, void,
        this->hasher->destroy(this->hasher);
        this->prf->destroy(this->prf);
        this->xof->destroy(this->xof);
+       this->drbg->destroy(this->drbg);
        this->rng->destroy(this->rng);
        this->dh->destroy(this->dh);
        free(this);
@@ -1530,6 +1671,7 @@ crypto_tester_t *crypto_tester_create()
                        .test_hasher = _test_hasher,
                        .test_prf = _test_prf,
                        .test_xof = _test_xof,
+                       .test_drbg = _test_drbg,
                        .test_rng = _test_rng,
                        .test_dh = _test_dh,
                        .add_crypter_vector = _add_crypter_vector,
@@ -1538,6 +1680,7 @@ crypto_tester_t *crypto_tester_create()
                        .add_hasher_vector = _add_hasher_vector,
                        .add_prf_vector = _add_prf_vector,
                        .add_xof_vector = _add_xof_vector,
+                       .add_drbg_vector = _add_drbg_vector,
                        .add_rng_vector = _add_rng_vector,
                        .add_dh_vector = _add_dh_vector,
                        .destroy = _destroy,
@@ -1548,6 +1691,7 @@ crypto_tester_t *crypto_tester_create()
                .hasher = linked_list_create(),
                .prf = linked_list_create(),
                .xof = linked_list_create(),
+               .drbg = linked_list_create(),
                .rng = linked_list_create(),
                .dh = linked_list_create(),
 
index 4309295..fcb64a6 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Martin Willi
+ * Copyright (C) 2016-2019 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -31,6 +32,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 xof_test_vector_t xof_test_vector_t;
+typedef struct drbg_test_vector_t drbg_test_vector_t;
 typedef struct rng_test_vector_t rng_test_vector_t;
 typedef struct dh_test_vector_t dh_test_vector_t;
 
@@ -128,6 +130,19 @@ struct xof_test_vector_t {
        u_char *out;
 };
 
+struct drbg_test_vector_t {
+       /** drbg type this test vector tests */
+       drbg_type_t type;
+       /** security strength in bits */
+       uint32_t strength;
+       /** optional personalization string */
+       chunk_t personalization_str;
+       /** entropy_input | nonce | entropy_input_reseed */
+       chunk_t entropy;
+       /** returned output bits */
+       chunk_t out;
+};
+
 /**
  * Test vector for a RNG.
  *
@@ -242,6 +257,17 @@ struct crypto_tester_t {
                                         xof_constructor_t create,
                                         u_int *speed, const char *plugin_name);
        /**
+        * Test a DRBG type.
+        *
+        * @param type                  DRBG type to test
+        * @param create                constructor function for the DRBG
+        * @param speed                 speed test result, NULL to omit
+        * @return                              TRUE if test passed
+        */
+       bool (*test_drbg)(crypto_tester_t *this, drbg_type_t type,
+                                         drbg_constructor_t create,
+                                         u_int *speed, const char *plugin_name);
+       /**
         * Test a RNG implementation.
         *
         * @param alg                   algorithm to test
@@ -307,6 +333,13 @@ struct crypto_tester_t {
        void (*add_xof_vector)(crypto_tester_t *this, xof_test_vector_t *vector);
 
        /**
+        * Add a test vector to test a DRBG.
+        *
+        * @param vector                pointer to test vector
+        */
+       void (*add_drbg_vector)(crypto_tester_t *this, drbg_test_vector_t *vector);
+
+       /**
         * Add a test vector to test a RNG.
         *
         * @param vector                pointer to test vector
diff --git a/src/libstrongswan/crypto/drbgs/drbg.c b/src/libstrongswan/crypto/drbgs/drbg.c
new file mode 100644 (file)
index 0000000..7e76384
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 Andreas Steffen
+ * HSR 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 Foundatio"n; 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 "drbg.h"
+
+ENUM(drbg_type_names, DRBG_UNDEFINED, DRBG_CTR_AES256,
+       "DRBG_UNDEFINED",
+       "DRBG_HMAC_SHA1",
+       "DRBG_HMAC_SHA256",
+       "DRBG_HMAC_SHA384",
+       "DRBG_HMAC_SHA512",
+       "DRBG_CTR_AES128",
+       "DRBG_CTR_AES192",
+       "DRBG_CTR_AES256",
+);
+
diff --git a/src/libstrongswan/crypto/drbgs/drbg.h b/src/libstrongswan/crypto/drbgs/drbg.h
new file mode 100644 (file)
index 0000000..620d44d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 Andreas Steffen
+ * HSR 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 drbg drbg
+ * @{ @ingroup crypto
+ */
+
+#ifndef DRBG_H_
+#define DRBG_H_
+
+typedef enum drbg_type_t drbg_type_t;
+typedef struct drbg_t drbg_t;
+
+#include <library.h>
+
+/**
+ * Deterministic Random Bit Generator.(DRBG) Type
+ */
+enum drbg_type_t {
+       DRBG_UNDEFINED,
+       DRBG_HMAC_SHA1,
+       DRBG_HMAC_SHA256,
+       DRBG_HMAC_SHA384,
+       DRBG_HMAC_SHA512,
+       DRBG_CTR_AES128,
+       DRBG_CTR_AES192,
+       DRBG_CTR_AES256,
+};
+
+/**
+ * enum name for drbg_type_t.
+ */
+extern enum_name_t *drbg_type_names;
+
+/**
+ * Interface for a Deterministic Random Bit Generator (DRBG)
+ * compliant with NIST SP 800-90A
+ */
+struct drbg_t {
+
+       /**
+        * Return the type of the DRBG
+        *
+        * @return                      DRBG type
+        */
+       drbg_type_t (*get_type)(drbg_t *this);
+
+       /**
+        * Return the security strength of the  DRBG
+        *
+        * @return                      configured security strength in bits
+        */
+       uint32_t (*get_strength)(drbg_t *this);
+
+       /**
+        * Reseed the instantiated DRBG
+        *
+        * @return                      TRUE if successful
+        */
+       bool (*reseed)(drbg_t *this);
+
+       /**
+        * Generate pseudorandom bytes.
+        * If the maximum number of requests has been reached, reseeding occurs
+        *
+        * @param len           number of octets to generate
+        * @param out           address of output buffer
+        * @return                      TRUE if successful
+        */
+       bool (*generate)(drbg_t *this, uint32_t len, uint8_t *out);
+
+       /**
+        * Get a reference on an drbg_t object increasing the count by one
+        *
+        * @return                      reference to the drbg_t object
+        */
+       drbg_t* (*get_ref)(drbg_t *this);
+
+       /**
+        * Uninstantiate and destroy the DRBG object
+        */
+       void (*destroy)(drbg_t *this);
+
+};
+
+#endif /** DRBG_H_ @}*/
index 7d2b521..55da146 100644 (file)
@@ -20,6 +20,8 @@
 
 typedef struct private_prf_plus_t private_prf_plus_t;
 
+typedef bool (*apply_prf_t)(private_prf_plus_t *this);
+
 /**
  * Private data of an prf_plus_t object.
  *
@@ -42,7 +44,7 @@ struct private_prf_plus_t {
        chunk_t seed;
 
        /**
-        * Octet which will be appended to the seed, 0 if not used
+        * Octet which will be appended to the seed if a counter is used.
         */
        uint8_t counter;
 
@@ -55,8 +57,41 @@ struct private_prf_plus_t {
         * Buffer to store current PRF result.
         */
        chunk_t buffer;
+
+       /**
+        * The prf application method depending on whether a counter is used.
+        */
+       apply_prf_t apply_prf;
 };
 
+/**
+ * Apply the PRF using the running counter
+ */
+static bool apply_prf_counter(private_prf_plus_t *this)
+{
+       if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
+               !this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
+                                                         this->buffer.ptr))
+       {
+               return FALSE;
+       }
+       this->counter++;
+       if (!this->counter)
+       {       /* according to RFC 7296, section 2.13, prf+ is undefined once the
+                * counter wrapped, so let's fail for future calls */
+               this->apply_prf = (void*)return_false;
+       }
+       return TRUE;
+}
+
+/**
+ * Apply the PRF using the running counter
+ */
+static bool apply_prf(private_prf_plus_t *this)
+{
+       return this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr);
+}
+
 METHOD(prf_plus_t, get_bytes, bool,
        private_prf_plus_t *this, size_t length, uint8_t *buffer)
 {
@@ -70,23 +105,9 @@ METHOD(prf_plus_t, get_bytes, bool,
                        {
                                return FALSE;
                        }
-                       if (this->counter)
-                       {
-                               if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
-                                       !this->prf->get_bytes(this->prf,
-                                                       chunk_from_thing(this->counter), this->buffer.ptr))
-                               {
-                                       return FALSE;
-                               }
-                               this->counter++;
-                       }
-                       else
+                       if (!this->apply_prf(this))
                        {
-                               if (!this->prf->get_bytes(this->prf, this->seed,
-                                                                                 this->buffer.ptr))
-                               {
-                                       return FALSE;
-                               }
+                               return FALSE;
                        }
                        this->used = 0;
                }
@@ -103,12 +124,12 @@ METHOD(prf_plus_t, get_bytes, bool,
 METHOD(prf_plus_t, allocate_bytes, bool,
        private_prf_plus_t *this, size_t length, chunk_t *chunk)
 {
-       if (length)
+       *chunk = chunk_alloc(length);
+       if (!get_bytes(this, length, chunk->ptr))
        {
-               *chunk = chunk_alloc(length);
-               return get_bytes(this, length, chunk->ptr);
+               chunk_free(chunk);
+               return FALSE;
        }
-       *chunk = chunk_empty;
        return TRUE;
 }
 
@@ -136,28 +157,14 @@ prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed)
                .prf = prf,
                .seed = chunk_clone(seed),
                .buffer = chunk_alloc(prf->get_block_size(prf)),
+               .apply_prf = counter ? apply_prf_counter : apply_prf,
+               .counter = 0x01,
        );
 
-       if (counter)
-       {
-               this->counter = 0x01;
-               if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
-                       !this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
-                                                                 this->buffer.ptr))
-               {
-                       destroy(this);
-                       return NULL;
-               }
-               this->counter++;
-       }
-       else
+       if (!this->apply_prf(this))
        {
-               if (!this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr))
-               {
-                       destroy(this);
-                       return NULL;
-               }
+               destroy(this);
+               return NULL;
        }
-
        return &this->public;
 }
index 9526089..560303f 100644 (file)
@@ -302,44 +302,12 @@ METHOD(proposal_t, promote_dh_group, bool,
        return found;
 }
 
-METHOD(proposal_t, strip_dh, void,
-       private_proposal_t *this, diffie_hellman_group_t keep)
-{
-       enumerator_t *enumerator;
-       entry_t *entry;
-       bool found = FALSE;
-
-       enumerator = array_create_enumerator(this->transforms);
-       while (enumerator->enumerate(enumerator, &entry))
-       {
-               if (entry->type == DIFFIE_HELLMAN_GROUP)
-               {
-                       if (entry->alg != keep)
-                       {
-                               array_remove_at(this->transforms, enumerator);
-                       }
-                       else
-                       {
-                               found = TRUE;
-                       }
-               }
-       }
-       enumerator->destroy(enumerator);
-       array_compress(this->transforms);
-
-       if (keep == MODP_NONE || !found)
-       {
-               remove_type(this, DIFFIE_HELLMAN_GROUP);
-               array_compress(this->types);
-       }
-}
-
 /**
  * Select a matching proposal from this and other.
  */
 static bool select_algo(private_proposal_t *this, proposal_t *other,
-                                               transform_type_t type, bool priv, bool log,
-                                               uint16_t *alg, uint16_t *ks)
+                                               transform_type_t type, proposal_selection_flag_t flags,
+                                               bool log, uint16_t *alg, uint16_t *ks)
 {
        enumerator_t *e1, *e2;
        uint16_t alg1, alg2, ks1, ks2;
@@ -390,7 +358,7 @@ static bool select_algo(private_proposal_t *this, proposal_t *other,
                {
                        if (alg1 == alg2 && ks1 == ks2)
                        {
-                               if (!priv && alg1 >= 1024)
+                               if ((flags & PROPOSAL_SKIP_PRIVATE) && alg1 >= 1024)
                                {
                                        if (log)
                                        {
@@ -417,7 +385,7 @@ static bool select_algo(private_proposal_t *this, proposal_t *other,
  * is stored there and errors are logged.
  */
 static bool select_algos(private_proposal_t *this, proposal_t *other,
-                                                proposal_t *selected, bool private)
+                                                proposal_t *selected, proposal_selection_flag_t flags)
 {
        transform_type_t type;
        array_t *types;
@@ -434,7 +402,11 @@ static bool select_algos(private_proposal_t *this, proposal_t *other,
                {
                        continue;
                }
-               if (select_algo(this, other, type, private, selected != NULL, &alg, &ks))
+               if (type == DIFFIE_HELLMAN_GROUP && (flags & PROPOSAL_SKIP_DH))
+               {
+                       continue;
+               }
+               if (select_algo(this, other, type, flags, selected != NULL, &alg, &ks))
                {
                        if (alg == 0 && type != EXTENDED_SEQUENCE_NUMBERS)
                        {       /* 0 is "valid" for extended sequence numbers, for other
@@ -468,8 +440,8 @@ static bool select_algos(private_proposal_t *this, proposal_t *other,
 }
 
 METHOD(proposal_t, select_proposal, proposal_t*,
-       private_proposal_t *this, proposal_t *other, bool other_remote,
-       bool private)
+       private_proposal_t *this, proposal_t *other,
+       proposal_selection_flag_t flags)
 {
        proposal_t *selected;
 
@@ -481,18 +453,18 @@ METHOD(proposal_t, select_proposal, proposal_t*,
                return NULL;
        }
 
-       if (other_remote)
+       if (flags & PROPOSAL_PREFER_SUPPLIED)
        {
-               selected = proposal_create(this->protocol, other->get_number(other));
-               selected->set_spi(selected, other->get_spi(other));
+               selected = proposal_create(this->protocol, this->number);
+               selected->set_spi(selected, this->spi);
        }
        else
        {
-               selected = proposal_create(this->protocol, this->number);
-               selected->set_spi(selected, this->spi);
+               selected = proposal_create(this->protocol, other->get_number(other));
+               selected->set_spi(selected, other->get_spi(other));
        }
 
-       if (!select_algos(this, other, selected, private))
+       if (!select_algos(this, other, selected, flags))
        {
                selected->destroy(selected);
                return NULL;
@@ -502,13 +474,14 @@ METHOD(proposal_t, select_proposal, proposal_t*,
 }
 
 METHOD(proposal_t, matches, bool,
-       private_proposal_t *this, proposal_t *other, bool private)
+       private_proposal_t *this, proposal_t *other,
+       proposal_selection_flag_t flags)
 {
        if (this->protocol != other->get_protocol(other))
        {
                return FALSE;
        }
-       return select_algos(this, other, NULL, private);
+       return select_algos(this, other, NULL, flags);
 }
 
 METHOD(proposal_t, get_protocol, protocol_id_t,
@@ -599,25 +572,27 @@ METHOD(proposal_t, equals, bool,
 }
 
 METHOD(proposal_t, clone_, proposal_t*,
-       private_proposal_t *this)
+       private_proposal_t *this, proposal_selection_flag_t flags)
 {
        private_proposal_t *clone;
        enumerator_t *enumerator;
        entry_t *entry;
-       transform_type_t *type;
 
        clone = (private_proposal_t*)proposal_create(this->protocol, 0);
 
        enumerator = array_create_enumerator(this->transforms);
        while (enumerator->enumerate(enumerator, &entry))
        {
+               if (entry->alg >= 1024 && (flags & PROPOSAL_SKIP_PRIVATE))
+               {
+                       continue;
+               }
+               if (entry->type == DIFFIE_HELLMAN_GROUP && (flags & PROPOSAL_SKIP_DH))
+               {
+                       continue;
+               }
                array_insert(clone->transforms, ARRAY_TAIL, entry);
-       }
-       enumerator->destroy(enumerator);
-       enumerator = array_create_enumerator(this->types);
-       while (enumerator->enumerate(enumerator, &type))
-       {
-               array_insert(clone->types, ARRAY_TAIL, type);
+               add_type(clone->types, entry->type);
        }
        enumerator->destroy(enumerator);
 
@@ -954,7 +929,6 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number)
                        .get_algorithm = _get_algorithm,
                        .has_dh_group = _has_dh_group,
                        .promote_dh_group = _promote_dh_group,
-                       .strip_dh = _strip_dh,
                        .select = _select_proposal,
                        .matches = _matches,
                        .get_protocol = _get_protocol,
@@ -1341,3 +1315,59 @@ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs
 
        return &this->public;
 }
+
+/*
+ * Described in header
+ */
+proposal_t *proposal_select(linked_list_t *configured, linked_list_t *supplied,
+                                                       proposal_selection_flag_t flags)
+{
+       enumerator_t *prefer_enum, *match_enum;
+       proposal_t *proposal, *match, *selected = NULL;
+
+       if (flags & PROPOSAL_PREFER_SUPPLIED)
+       {
+               prefer_enum = supplied->create_enumerator(supplied);
+               match_enum = configured->create_enumerator(configured);
+       }
+       else
+       {
+               prefer_enum = configured->create_enumerator(configured);
+               match_enum = supplied->create_enumerator(supplied);
+       }
+
+       while (prefer_enum->enumerate(prefer_enum, &proposal))
+       {
+               if (flags & PROPOSAL_PREFER_SUPPLIED)
+               {
+                       configured->reset_enumerator(configured, match_enum);
+               }
+               else
+               {
+                       supplied->reset_enumerator(supplied, match_enum);
+               }
+               while (match_enum->enumerate(match_enum, &match))
+               {
+                       selected = proposal->select(proposal, match, flags);
+                       if (selected)
+                       {
+                               DBG2(DBG_CFG, "received proposals: %#P", supplied);
+                               DBG2(DBG_CFG, "configured proposals: %#P", configured);
+                               DBG1(DBG_CFG, "selected proposal: %P", selected);
+                               break;
+                       }
+               }
+               if (selected)
+               {
+                       break;
+               }
+       }
+       prefer_enum->destroy(prefer_enum);
+       match_enum->destroy(match_enum);
+       if (!selected)
+       {
+               DBG1(DBG_CFG, "received proposals: %#P", supplied);
+               DBG1(DBG_CFG, "configured proposals: %#P", configured);
+       }
+       return selected;
+}
index 3383243..6a9cdba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2018 Tobias Brunner
+ * Copyright (C) 2009-2019 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * HSR Hochschule fuer Technik Rapperswil
  *
@@ -23,6 +23,7 @@
 #define PROPOSAL_H_
 
 typedef enum protocol_id_t protocol_id_t;
+typedef enum proposal_selection_flag_t proposal_selection_flag_t;
 typedef enum extended_sequence_numbers_t extended_sequence_numbers_t;
 typedef struct proposal_t proposal_t;
 
@@ -52,26 +53,32 @@ enum protocol_id_t {
 extern enum_name_t *protocol_id_names;
 
 /**
+ * Flags for selecting proposals.
+ */
+enum proposal_selection_flag_t {
+       /** Whether to prefer configured (default) or supplied proposals. */
+       PROPOSAL_PREFER_SUPPLIED = (1<<0),
+       /** Whether to skip and ignore algorithms from a private range. */
+       PROPOSAL_SKIP_PRIVATE = (1<<1),
+       /** Whether to skip and ignore diffie hellman groups. */
+       PROPOSAL_SKIP_DH = (1<<2),
+};
+
+/**
  * Stores a set of algorithms used for an SA.
  *
- * A proposal stores algorithms for a specific
- * protocol. It can store algorithms for one protocol.
- * Proposals with multiple protocols are not supported,
- * as it's not specified in RFC4301 anymore.
+ * A proposal stores algorithms for a specific protocol.
+ * Proposals with multiple protocols are not supported, as that's not specified
+ * in RFC 7296 anymore.
  */
 struct proposal_t {
 
        /**
         * Add an algorithm to the proposal.
         *
-        * The algorithms are stored by priority, first added
-        * is the most preferred.
-        * Key size is only needed for encryption algorithms
-        * with variable key size (such as AES). Must be set
-        * to zero if key size is not specified.
-        * The alg parameter accepts encryption_algorithm_t,
-        * integrity_algorithm_t, dh_group_number_t and
-        * extended_sequence_numbers_t.
+        * The algorithms are stored by priority, first added is the most preferred.
+        * Key size is only needed for encryption algorithms with variable key
+        * size (such as AES). Must be set to zero if the key size is not specified.
         *
         * @param type                  kind of algorithm
         * @param alg                   identifier for algorithm
@@ -81,7 +88,7 @@ struct proposal_t {
                                                   uint16_t alg, uint16_t key_size);
 
        /**
-        * Get an enumerator over algorithms for a specific algo type.
+        * Get an enumerator over algorithms for a specific transform type.
         *
         * @param type                  kind of algorithm
         * @return                              enumerator over uint16_t alg, uint16_t key_size
@@ -119,28 +126,22 @@ struct proposal_t {
        bool (*promote_dh_group)(proposal_t *this, diffie_hellman_group_t group);
 
        /**
-        * Strip DH groups from proposal to use it without PFS.
-        *
-        * @param keep                  group to keep (MODP_NONE to remove all)
-        */
-       void (*strip_dh)(proposal_t *this, diffie_hellman_group_t keep);
-
-       /**
-        * Compare two proposal, and select a matching subset.
+        * Compare two proposals and select a matching subset.
         *
         * If the proposals are for the same protocols (AH/ESP), they are
         * compared. If they have at least one algorithm of each type
         * in common, a resulting proposal of this kind is created.
         *
+        * Unless the flag PROPOSAL_PREFER_SUPPLIED is set, other is expected to be
+        * the remote proposal from which to copy SPI and proposal number to the
+        * result, otherwise copy from this proposal.
+        *
         * @param other                 proposal to compare against
-        * @param other_remote  whether other is the remote proposal from which to
-        *                                              copy SPI and proposal number to the result,
-        *                                              otherwise copy from this proposal
-        * @param private               accepts algorithms allocated in a private range
+        * @param flags                 flags to consider during proposal selection
         * @return                              selected proposal, NULL if proposals don't match
         */
        proposal_t *(*select)(proposal_t *this, proposal_t *other,
-                                                 bool other_remote, bool private);
+                                                 proposal_selection_flag_t flags);
 
        /**
         * Check if the given proposal matches this proposal.
@@ -148,10 +149,11 @@ struct proposal_t {
         * This is similar to select, but no resulting proposal is selected.
         *
         * @param other                 proposal to compare against
-        * @param private               accepts algorithms allocated in a private range
+        * @param flags                 flags to consider during proposal selection
         * @return                              TRUE if the proposals match
         */
-       bool (*matches)(proposal_t *this, proposal_t *other, bool private);
+       bool (*matches)(proposal_t *this, proposal_t *other,
+                                       proposal_selection_flag_t flags);
 
        /**
         * Get the protocol ID of the proposal.
@@ -163,38 +165,39 @@ struct proposal_t {
        /**
         * Get the SPI of the proposal.
         *
-        * @return                              spi for proto
+        * @return                              SPI of the proposal
         */
        uint64_t (*get_spi) (proposal_t *this);
 
        /**
         * Set the SPI of the proposal.
         *
-        * @param spi                   spi to set for proto
+        * @param spi                   SPI to set for proposal
         */
        void (*set_spi) (proposal_t *this, uint64_t spi);
 
        /**
-        * Get the proposal number, as encoded in SA payload
+        * Get the proposal number, as encoded in the SA payload.
         *
         * @return                              proposal number
         */
        u_int (*get_number)(proposal_t *this);
 
        /**
-        * Check for the eqality of two proposals.
+        * Check for the equality of two proposals.
         *
         * @param other                 other proposal to check for equality
-        * @return                              TRUE if other equal to this
+        * @return                              TRUE if proposals are equal
         */
        bool (*equals)(proposal_t *this, proposal_t *other);
 
        /**
         * Clone a proposal.
         *
+        * @param flags                 flags to consider during cloning
         * @return                              clone of proposal
         */
-       proposal_t *(*clone) (proposal_t *this);
+       proposal_t *(*clone)(proposal_t *this, proposal_selection_flag_t flags);
 
        /**
         * Destroys the proposal object.
@@ -203,7 +206,7 @@ struct proposal_t {
 };
 
 /**
- * Create a child proposal for AH, ESP or IKE.
+ * Create a proposal for IKE, ESP or AH.
  *
  * @param protocol                     protocol, such as PROTO_ESP
  * @param number                       proposal number, as encoded in SA payload
@@ -212,7 +215,7 @@ struct proposal_t {
 proposal_t *proposal_create(protocol_id_t protocol, u_int number);
 
 /**
- * Create a default proposal if nothing further specified.
+ * Create a default proposal.
  *
  * @param protocol                     protocol, such as PROTO_ESP
  * @return                                     proposal_t object
@@ -220,7 +223,7 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number);
 proposal_t *proposal_create_default(protocol_id_t protocol);
 
 /**
- * Create a default proposal for supported AEAD algorithms
+ * Create a default proposal for supported AEAD algorithms.
  *
  * @param protocol                     protocol, such as PROTO_ESP
  * @return                                     proposal_t object, NULL if none supported
@@ -230,25 +233,43 @@ proposal_t *proposal_create_default_aead(protocol_id_t protocol);
 /**
  * Create a proposal from a string identifying the algorithms.
  *
- * The string is in the same form as a in the ipsec.conf file.
- * E.g.:       aes128-sha2_256-modp2048
- *               3des-md5
- * An additional '!' at the end of the string forces this proposal,
- * without it the peer may choose another algorithm we support.
+ * Each algorithm identifier is separated with a '-' character e.g.
+ * aes256-sha2-curve25519. Multiple algorithms of the same transform type can be
+ * given (they don't have to be grouped together), the order is preserved e.g.
+ * curve25519-sha2-aes256-sha1-modp3072-aes128 is the same as
+ * aes256-aes128-sha2-sha1-curve25519-modp3072.
+ *
+ * The proposal is validated (e.g. PROTO_IKE proposals must contain a key
+ * exchange method, AEAD algorithms can't be combined with classic encryption
+ * algorithms etc.) and in some cases modified (e.g. by adding missing PRFs for
+ * PROTO_IKE, or by adding noesn in PROTO_ESP/AH proposals if neither esn, nor
+ * noesn is contained in the string etc.).
  *
  * @param protocol                     protocol, such as PROTO_ESP
  * @param algs                         algorithms as string
- * @return                                     proposal_t object
+ * @return                                     proposal_t object, NULL if invalid
+ */
+proposal_t *proposal_create_from_string(protocol_id_t protocol,
+                                                                               const char *algs);
+
+/**
+ * Select a common proposal from the given lists of proposals.
+ *
+ * @param configured           list of configured/local proposals
+ * @param supplied                     list of supplied/remote proposals
+ * @param flags                                flags to consider during proposal selection
+ * @return                                     selected proposal, or NULL (allocated)
  */
-proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs);
+proposal_t *proposal_select(linked_list_t *configured, linked_list_t *supplied,
+                                                       proposal_selection_flag_t flags);
 
 /**
  * printf hook function for proposal_t.
  *
  * Arguments are:
- *     proposal_t *proposal
+ *     proposal_t*
  * With the #-specifier, arguments are:
- *     linked_list_t *list containing proposal_t*
+ *     linked_list_t* (containing proposal_t*)
  */
 int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
                                                 const void *const *args);
diff --git a/src/libstrongswan/crypto/rngs/rng_tester.c b/src/libstrongswan/crypto/rngs/rng_tester.c
new file mode 100644 (file)
index 0000000..4c763f1
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR 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 "rng_tester.h"
+
+typedef struct private_rng_t private_rng_t;
+
+/**
+ * Private data.
+ */
+struct private_rng_t {
+
+       /**
+        * Public interface.
+        */
+       rng_t public;
+
+       /**
+        * Entropy string.
+        */
+       chunk_t entropy;
+};
+
+METHOD(rng_t, get_bytes, bool,
+       private_rng_t *this, size_t bytes, uint8_t *buffer)
+{
+       if (bytes > this->entropy.len)
+       {
+               return FALSE;
+       }
+       memcpy(buffer, this->entropy.ptr, bytes);
+       this->entropy = chunk_skip(this->entropy, bytes);
+       return TRUE;
+}
+
+METHOD(rng_t, allocate_bytes, bool,
+       private_rng_t *this, size_t bytes, chunk_t *chunk)
+{
+       if (bytes > this->entropy.len)
+       {
+               *chunk = chunk_empty;
+               return FALSE;
+       }
+
+       *chunk = chunk_alloc(bytes);
+       memcpy(chunk->ptr, this->entropy.ptr, bytes);
+       this->entropy = chunk_skip(this->entropy, bytes);
+       return TRUE;
+}
+
+METHOD(rng_t, destroy, void,
+       private_rng_t *this)
+{
+       free(this);
+}
+
+/*
+ * Described in header.
+ */
+rng_t *rng_tester_create(chunk_t entropy)
+{
+       private_rng_t *this;
+
+       INIT(this,
+               .public = {
+                       .get_bytes = _get_bytes,
+                       .allocate_bytes = _allocate_bytes,
+                       .destroy = _destroy,
+               },
+               .entropy = entropy,
+       );
+
+       return &this->public;
+}
diff --git a/src/libstrongswan/crypto/rngs/rng_tester.h b/src/libstrongswan/crypto/rngs/rng_tester.h
new file mode 100644 (file)
index 0000000..7b7d3ce
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013-2019 Andreas Steffen
+ * HSR 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.
+ */
+
+/**
+ * rng_t providing deterministic output (DO NOT USE IN PRODUCTIVE SYSTEMS!!!)
+ *
+ * @defgroup rng_tester rng_tester
+ * @{ @ingroup crypto
+ */
+
+#ifndef RNG_TESTER_H_
+#define RNG_TESTER_H_
+
+#include <library.h>
+
+/**
+ * Creates a rng_tester_t instance.
+ *
+ * @param entropy      deterministic output
+ * @return                     created rng_tester_t
+ */
+rng_t *rng_tester_create(chunk_t entropy);
+
+#endif /** RNG_TESTER_H_ @} */
index 77a57f5..e30208e 100644 (file)
@@ -23,14 +23,15 @@ ENUM_BEGIN(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS
        "INTEGRITY_ALGORITHM",
        "DIFFIE_HELLMAN_GROUP",
        "EXTENDED_SEQUENCE_NUMBERS");
-ENUM_NEXT(transform_type_names, HASH_ALGORITHM, EXTENDED_OUTPUT_FUNCTION,
+ENUM_NEXT(transform_type_names, HASH_ALGORITHM, DETERMINISTIC_RANDOM_BIT_GENERATOR,
                  EXTENDED_SEQUENCE_NUMBERS,
        "HASH_ALGORITHM",
        "RANDOM_NUMBER_GENERATOR",
        "AEAD_ALGORITHM",
        "COMPRESSION_ALGORITHM",
-       "EXTENDED OUTPUT FUNCTION");
-ENUM_END(transform_type_names, EXTENDED_OUTPUT_FUNCTION);
+       "EXTENDED OUTPUT FUNCTION",
+       "DETERMINISTIC RANDOM BIT GENERATOR");
+ENUM_END(transform_type_names, DETERMINISTIC_RANDOM_BIT_GENERATOR);
 
 
 ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS,
@@ -38,7 +39,6 @@ ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS,
        "EXT_SEQ",
 );
 
-
 /**
  * See header
  */
@@ -63,6 +63,8 @@ enum_name_t* transform_get_enum_names(transform_type_t type)
                        return extended_sequence_numbers_names;
                case EXTENDED_OUTPUT_FUNCTION:
                        return ext_out_function_names;
+               case DETERMINISTIC_RANDOM_BIT_GENERATOR:
+                       return drbg_type_names;
                case COMPRESSION_ALGORITHM:
                        break;
        }
index 63881b3..f7892b8 100644 (file)
@@ -39,6 +39,7 @@ enum transform_type_t {
        AEAD_ALGORITHM = 258,
        COMPRESSION_ALGORITHM = 259,
        EXTENDED_OUTPUT_FUNCTION = 260,
+       DETERMINISTIC_RANDOM_BIT_GENERATOR = 261,
 };
 
 /**
diff --git a/src/libstrongswan/plugins/drbg/Makefile.am b/src/libstrongswan/plugins/drbg/Makefile.am
new file mode 100644 (file)
index 0000000..560b294
--- /dev/null
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+       $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-drbg.la
+else
+plugin_LTLIBRARIES = libstrongswan-drbg.la
+endif
+
+libstrongswan_drbg_la_SOURCES = \
+       drbg_plugin.h drbg_plugin.c \
+       drbg_ctr.h drbg_ctr.c \
+       drbg_hmac.h drbg_hmac.c
+
+libstrongswan_drbg_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/drbg/drbg_ctr.c b/src/libstrongswan/plugins/drbg/drbg_ctr.c
new file mode 100644 (file)
index 0000000..39801b6
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2016-2019 Andreas Steffen
+ * HSR 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 "drbg_ctr.h"
+
+#define MAX_DRBG_REQUESTS      0xfffffffe
+
+typedef struct private_drbg_ctr_t private_drbg_ctr_t;
+
+/**
+ * Private data of an drbg_ctr_t object.
+ */
+struct private_drbg_ctr_t {
+
+       /**
+        * Public drbg_ctr_t interface.
+        */
+       drbg_ctr_t public;
+
+       /**
+        * DRBG type.
+        */
+       drbg_type_t type;
+
+       /**
+        * Security strength in bits.
+        */
+       uint32_t strength;
+
+       /**
+        * Number of requests for pseudorandom bits
+        */
+       uint32_t reseed_counter;
+
+       /**
+        * Maximum number of requests for pseudorandom bits
+        */
+       uint32_t max_requests;
+
+       /**
+        * True entropy source
+        */
+       rng_t *entropy;
+
+       /**
+        * Block cipher in counter mode used by the DRBG
+        */
+       crypter_t *crypter;
+
+       /**
+        * Internal state of HMAC: key
+        */
+       chunk_t key;
+
+       /**
+        * Internal state of HMAC: value
+        */
+       chunk_t value;
+
+       /**
+        * reference count
+        */
+       refcount_t ref;
+
+};
+
+METHOD(drbg_t, get_type, drbg_type_t,
+       private_drbg_ctr_t *this)
+{
+       return this->type;
+}
+
+METHOD(drbg_t, get_strength, uint32_t,
+       private_drbg_ctr_t *this)
+{
+       return this->strength;
+}
+
+static bool encrypt_ctr(private_drbg_ctr_t *this, chunk_t out)
+{
+       chunk_t iv = chunk_alloca(this->value.len);
+       chunk_t bl = chunk_alloca(this->value.len);
+       chunk_t block;
+       size_t delta, pos = 0;
+
+       /* Initialize IV to all zeroes for ECB mode */
+       memset(iv.ptr, 0x00, iv.len);
+
+       if (!this->crypter->set_key(this->crypter, this->key))
+       {
+               return FALSE;
+       }
+
+       while (pos < out.len)
+       {
+               /* Increment counter by one */
+               chunk_increment(this->value);
+
+               /* Copy current counter to input block */
+               delta = out.len - pos;
+               block = (delta < this->value.len) ?
+                                        bl : chunk_create(out.ptr + pos, this->value.len);
+               memcpy(block.ptr, this->value.ptr, this->value.len);
+
+               /* ECB encryption */
+               if (!this->crypter->encrypt(this->crypter, block, iv, NULL))
+               {
+                       return FALSE;
+               }
+
+               /* Partial output block at the end? */
+               if (delta < this->value.len)
+               {
+                       memcpy(out.ptr + pos, block.ptr, delta);
+               }
+               pos += this->value.len;
+       }
+
+       return TRUE;
+}
+
+/**
+ * Update the internal state of the CTR_DRBG
+ */
+static bool update(private_drbg_ctr_t *this, chunk_t data)
+{
+       chunk_t temp;
+
+       if (data.len && data.len != (this->key.len + this->value.len))
+       {
+               return FALSE;
+       }
+       temp = chunk_alloca(this->key.len + this->value.len);
+
+       if (!encrypt_ctr(this, temp))
+       {
+               return FALSE;
+       }
+       /* Apply data */
+       memxor(temp.ptr, data.ptr, data.len);
+
+       /* Copy new key and value */
+       memcpy(this->key.ptr, temp.ptr, this->key.len);
+       memcpy(this->value.ptr, temp.ptr + this->key.len, this->value.len);
+       memwipe(temp.ptr, temp.len);
+       DBG4(DBG_LIB, "CTR_DRBG K: %B", &this->key);
+       DBG4(DBG_LIB, "CTR_DRBG V: %B", &this->value);
+
+       return TRUE;
+}
+
+METHOD(drbg_t, reseed, bool,
+       private_drbg_ctr_t *this)
+{
+       chunk_t seed;
+       bool success;
+
+       seed = chunk_alloc(this->key.len + this->value.len);
+       DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", seed.len);
+
+       if (!this->entropy->get_bytes(this->entropy, seed.len, seed.ptr))
+       {
+               chunk_free(&seed);
+               return FALSE;
+       }
+       DBG4(DBG_LIB, "reseed: %B", &seed);
+
+       success = update(this, seed);
+       chunk_clear(&seed);
+
+       if (!success)
+       {
+               return FALSE;
+       }
+       this->reseed_counter = 1;
+
+       return TRUE;
+}
+
+METHOD(drbg_t, generate, bool,
+       private_drbg_ctr_t *this, uint32_t len, uint8_t *out)
+{
+       chunk_t output;
+
+       if (this->reseed_counter > this->max_requests)
+       {
+               if (!reseed(this))
+               {
+                       return FALSE;
+               }
+       }
+
+       DBG2(DBG_LIB, "DRBG generates %u pseudorandom bytes", len);
+       if (!out || len == 0)
+       {
+               return FALSE;
+       }
+       output = chunk_create(out, len);
+
+       if (!encrypt_ctr(this, output))
+       {
+               return FALSE;
+       }
+       DBG4(DBG_LIB, "CTR_DRBG Out: %B", &output);
+
+       if (!update(this, chunk_empty))
+       {
+               return FALSE;
+       }
+       this->reseed_counter++;
+
+       return TRUE;
+}
+
+METHOD(drbg_t, get_ref, drbg_t*,
+       private_drbg_ctr_t *this)
+{
+       ref_get(&this->ref);
+       return &this->public.interface;
+}
+
+METHOD(drbg_t, destroy, void,
+       private_drbg_ctr_t *this)
+{
+       if (ref_put(&this->ref))
+       {
+               this->crypter->destroy(this->crypter);
+               chunk_clear(&this->key);
+               chunk_clear(&this->value);
+               free(this);
+       }
+}
+
+/**
+ * See header
+ */
+drbg_ctr_t *drbg_ctr_create(drbg_type_t type, uint32_t strength,
+                                                       rng_t *entropy, chunk_t personalization_str)
+{
+       private_drbg_ctr_t *this;
+       encryption_algorithm_t crypter_type;
+       crypter_t *crypter;
+       chunk_t seed;
+       size_t key_len, out_len, seed_len;
+       uint32_t max_requests;
+       bool success;
+
+       switch (type)
+       {
+               case DRBG_CTR_AES128:
+                       crypter_type = ENCR_AES_CBC;
+                       key_len = 16;
+                       break;
+               case DRBG_CTR_AES192:
+                       crypter_type = ENCR_AES_CBC;
+                       key_len = 24;
+                       break;
+               case DRBG_CTR_AES256:
+                       crypter_type = ENCR_AES_CBC;
+                       key_len = 32;
+                       break;
+               default:
+                       DBG1(DBG_LIB, "%N not supported", drbg_type_names, type);
+                       return NULL;
+       }
+
+       if (strength >  key_len * BITS_PER_BYTE)
+       {
+               DBG1(DBG_LIB, "%d bit block encryption key not sufficient for security "
+                        "strength of % bits", key_len * BITS_PER_BYTE, strength);
+               return NULL;
+       }
+
+       crypter = lib->crypto->create_crypter(lib->crypto, crypter_type, key_len);
+       if (!crypter)
+       {
+               DBG1(DBG_LIB, "creation of %N for DRBG failed",
+                        encryption_algorithm_names, crypter_type);
+               return NULL;
+       }
+       out_len = crypter->get_block_size(crypter);
+       seed_len = key_len + out_len;
+
+       if (personalization_str.len > seed_len)
+       {
+               DBG1(DBG_LIB, "personalization string length of %d bytes is larger "
+                        "than seed length of % bytes", personalization_str.len, seed_len);
+               crypter->destroy(crypter);
+               return NULL;
+       }
+
+       max_requests = lib->settings->get_int(lib->settings,
+                                                                                 "%s.plugins.drbg.max_drbg_requests",
+                                                                                 MAX_DRBG_REQUESTS, lib->ns);
+
+       INIT(this,
+               .public = {
+                       .interface = {
+                               .get_type = _get_type,
+                               .get_strength = _get_strength,
+                               .reseed = _reseed,
+                               .generate = _generate,
+                               .get_ref = _get_ref,
+                               .destroy = _destroy,
+                       },
+               },
+               .type = type,
+               .strength = strength,
+               .entropy = entropy,
+               .crypter = crypter,
+               .key = chunk_alloc(key_len),
+               .value = chunk_alloc(out_len),
+               .max_requests = max_requests,
+               .reseed_counter = 1,
+               .ref = 1,
+       );
+
+       memset(this->key.ptr,   0x00, key_len);
+       memset(this->value.ptr, 0x00, out_len);
+
+       seed = chunk_alloc(seed_len);
+       DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", seed_len);
+
+       if (!this->entropy->get_bytes(this->entropy, seed.len, seed.ptr))
+       {
+               chunk_free(&seed);
+               destroy(this);
+               return NULL;
+       }
+       memxor(seed.ptr, personalization_str.ptr, personalization_str.len);
+       DBG4(DBG_LIB, "seed: %B", &seed);
+
+       success = update(this, seed);
+       chunk_clear(&seed);
+
+       if (!success)
+       {
+               destroy(this);
+               return NULL;
+       }
+
+       return &this->public;
+}
diff --git a/src/libstrongswan/plugins/drbg/drbg_ctr.h b/src/libstrongswan/plugins/drbg/drbg_ctr.h
new file mode 100644 (file)
index 0000000..9e41a4e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Andreas Steffen
+ * HSR 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 drbg_ctr drbg_ctr
+ * @{ @ingroup drbg
+ */
+
+#ifndef DRBG_CTR_H_
+#define DRBG_CTR_H_
+
+#include <crypto/drbgs/drbg.h>
+
+typedef struct drbg_ctr_t drbg_ctr_t;
+
+/**
+ * NIST SP 800-90A CTR DRBC implementation
+ */
+struct drbg_ctr_t {
+
+       /**
+        * Public Deterministic Random Bit Generator (DRBG) Interface
+        */
+       drbg_t interface;
+};
+
+/**
+ * Create a drbg_ctr instance.
+ *
+ * @param type                                 DRBG CTR type
+ * @param strength                             security strength in bits
+ * @param entropy                              entropy source to be used
+ * @param personalization_str  optional personalization string
+ * @return                                             drbg_ctr_t object, NULL if not supported
+ */
+drbg_ctr_t *drbg_ctr_create(drbg_type_t type, uint32_t strength,
+                                                       rng_t *entropy, chunk_t personalization_str);
+
+#endif /** DRBG_CTR_H_ @}*/
diff --git a/src/libstrongswan/plugins/drbg/drbg_hmac.c b/src/libstrongswan/plugins/drbg/drbg_hmac.c
new file mode 100644 (file)
index 0000000..2006e10
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2016-2019 Andreas Steffen
+ * HSR 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 "drbg_hmac.h"
+
+#define MAX_DRBG_REQUESTS      0xfffffffe
+
+typedef struct private_drbg_hmac_t private_drbg_hmac_t;
+
+/**
+ * Private data of an drbg_prf_t object.
+ */
+struct private_drbg_hmac_t {
+
+       /**
+        * Public drbg_prf_t interface.
+        */
+       drbg_hmac_t public;
+
+       /**
+        * DRBG type.
+        */
+       drbg_type_t type;
+
+       /**
+        * Security strength in bits.
+        */
+       uint32_t strength;
+
+       /**
+        * Number of requests for pseudorandom bits
+        */
+       size_t reseed_counter;
+
+       /**
+        * Maximum number of requests for pseudorandom bits
+        */
+       size_t max_requests;
+
+       /**
+        * True entropy source
+        */
+       rng_t *entropy;
+
+       /**
+        * HMAC PRF used by the DRBG
+        */
+       prf_t *prf;
+
+       /**
+        * Internal state of HMAC: key
+        */
+       chunk_t key;
+
+       /**
+        * Internal state of HMAC: value
+        */
+       chunk_t value;
+
+       /**
+        * reference count
+        */
+       refcount_t ref;
+
+};
+
+METHOD(drbg_t, get_type, drbg_type_t,
+       private_drbg_hmac_t *this)
+{
+       return this->type;
+}
+
+METHOD(drbg_t, get_strength, uint32_t,
+       private_drbg_hmac_t *this)
+{
+       return this->strength;
+}
+
+/**
+ * Update the internal state of the HMAC_DRBG
+ */
+static bool update(private_drbg_hmac_t *this, chunk_t data)
+{
+       chunk_t ch_00 = chunk_from_chars(0x00);
+       chunk_t ch_01 = chunk_from_chars(0x01);
+
+       if (!this->prf->set_key(this->prf, this->key) ||
+               !this->prf->get_bytes(this->prf, this->value, NULL) ||
+           !this->prf->get_bytes(this->prf, ch_00, NULL) ||
+           !this->prf->get_bytes(this->prf, data, this->key.ptr) ||
+               !this->prf->set_key(this->prf, this->key) ||
+           !this->prf->get_bytes(this->prf, this->value, this->value.ptr))
+       {
+               return FALSE;
+       }
+
+       if (data.len > 0)
+       {
+               if (!this->prf->set_key(this->prf, this->key) ||
+                       !this->prf->get_bytes(this->prf, this->value, NULL) ||
+                       !this->prf->get_bytes(this->prf, ch_01, NULL) ||
+                       !this->prf->get_bytes(this->prf, data, this->key.ptr) ||
+                       !this->prf->set_key(this->prf, this->key) ||
+                       !this->prf->get_bytes(this->prf, this->value, this->value.ptr))
+               {
+                       return FALSE;
+               }
+       }
+       DBG4(DBG_LIB, "HMAC_DRBG K: %B", &this->key);
+       DBG4(DBG_LIB, "HMAC_DRBG V: %B", &this->value);
+
+       return TRUE;
+}
+
+METHOD(drbg_t, reseed, bool,
+       private_drbg_hmac_t *this)
+{
+       chunk_t seed;
+       bool success;
+
+       seed = chunk_alloc(this->strength / BITS_PER_BYTE);
+       DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", seed.len);
+
+       if (!this->entropy->get_bytes(this->entropy, seed.len, seed.ptr))
+       {
+               chunk_free(&seed);
+               return FALSE;
+       }
+       DBG4(DBG_LIB, "reseed: %B", &seed);
+
+       success = update(this, seed);
+       chunk_clear(&seed);
+
+       if (!success)
+       {
+               return FALSE;
+       }
+       this->reseed_counter = 1;
+
+       return TRUE;
+}
+
+METHOD(drbg_t, generate, bool,
+       private_drbg_hmac_t *this, uint32_t len, uint8_t *out)
+{
+       size_t delta;
+       chunk_t output;
+
+       DBG2(DBG_LIB, "DRBG generates %u pseudorandom bytes", len);
+       if (!out || len == 0)
+       {
+               return FALSE;
+       }
+       output = chunk_create(out, len);
+
+       if (this->reseed_counter > this->max_requests)
+       {
+               if (!reseed(this))
+               {
+                       return FALSE;
+               }
+       }
+       while (len)
+       {
+               if (!this->prf->get_bytes(this->prf, this->value, this->value.ptr))
+               {
+                       return FALSE;
+               }
+               delta = min(len, this->value.len);
+               memcpy(out, this->value.ptr, delta);
+               len -= delta;
+               out += delta;
+       }
+       DBG4(DBG_LIB, "HMAC_DRBG Out: %B", &output);
+
+       if (!update(this, chunk_empty))
+       {
+               return FALSE;
+       }
+       this->reseed_counter++;
+
+       return TRUE;
+}
+
+METHOD(drbg_t, get_ref, drbg_t*,
+       private_drbg_hmac_t *this)
+{
+       ref_get(&this->ref);
+       return &this->public.interface;
+}
+
+METHOD(drbg_t, destroy, void,
+       private_drbg_hmac_t *this)
+{
+       if (ref_put(&this->ref))
+       {
+               this->prf->destroy(this->prf);
+               chunk_clear(&this->key);
+               chunk_clear(&this->value);
+               free(this);
+       }
+}
+
+/**
+ * See header
+ */
+drbg_hmac_t *drbg_hmac_create(drbg_type_t type, uint32_t strength,
+                                                         rng_t *entropy, chunk_t personalization_str)
+{
+       private_drbg_hmac_t *this;
+       pseudo_random_function_t prf_type = PRF_UNDEFINED;
+       size_t out_len, entropy_len;
+       uint32_t max_requests;
+       chunk_t seed;
+       prf_t * prf;
+       bool success;
+
+       switch (type)
+       {
+               case DRBG_HMAC_SHA1:
+                       prf_type = PRF_HMAC_SHA1;
+                       break;
+               case DRBG_HMAC_SHA256:
+                       prf_type = PRF_HMAC_SHA2_256;
+                       break;
+               case DRBG_HMAC_SHA384:
+                       prf_type = PRF_HMAC_SHA2_384;
+                       break;
+               case DRBG_HMAC_SHA512:
+                       prf_type = PRF_HMAC_SHA2_512;
+                       break;
+               default:
+                       DBG1(DBG_LIB, "%N not supported", drbg_type_names, type);
+                       return NULL;
+       }
+
+       prf = lib->crypto->create_prf(lib->crypto, prf_type);
+       if (!prf)
+       {
+               DBG1(DBG_LIB, "creation of %N for DRBG failed",
+                        pseudo_random_function_names, prf_type);
+               return NULL;
+       }
+       out_len = prf->get_key_size(prf);
+
+       if (strength >  out_len * BITS_PER_BYTE)
+       {
+               DBG1(DBG_LIB, "%N not sufficient for security strength of % bits",
+                        pseudo_random_function_names, prf_type, strength);
+               prf->destroy(prf);
+               return NULL;
+       }
+
+       max_requests = lib->settings->get_int(lib->settings,
+                                                                                 "%s.plugins.drbg.max_drbg_requests",
+                                                                                 MAX_DRBG_REQUESTS, lib->ns);
+
+       INIT(this,
+               .public = {
+                       .interface = {
+                               .get_type = _get_type,
+                               .get_strength = _get_strength,
+                               .reseed = _reseed,
+                               .generate = _generate,
+                               .get_ref = _get_ref,
+                               .destroy = _destroy,
+                       },
+               },
+               .type = type,
+               .strength = strength,
+               .entropy = entropy,
+               .prf = prf,
+               .key = chunk_alloc(out_len),
+               .value = chunk_alloc(out_len),
+               .max_requests = max_requests,
+               .reseed_counter = 1,
+               .ref = 1,
+       );
+
+       memset(this->key.ptr,   0x00, out_len);
+       memset(this->value.ptr, 0x01, out_len);
+
+       entropy_len = (strength + strength/2) / BITS_PER_BYTE;
+       seed = chunk_alloc(entropy_len + personalization_str.len);
+       DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", entropy_len);
+
+       if (!this->entropy->get_bytes(this->entropy, entropy_len, seed.ptr))
+       {
+               chunk_free(&seed);
+               destroy(this);
+               return NULL;
+       }
+       memcpy(seed.ptr + entropy_len,
+                  personalization_str.ptr, personalization_str.len);
+       DBG4(DBG_LIB, "seed: %B", &seed);
+
+       success = update(this, seed);
+       chunk_clear(&seed);
+
+       if (!success)
+       {
+               destroy(this);
+               return NULL;
+       }
+
+       return &this->public;
+}
diff --git a/src/libstrongswan/plugins/drbg/drbg_hmac.h b/src/libstrongswan/plugins/drbg/drbg_hmac.h
new file mode 100644 (file)
index 0000000..fafd24d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Andreas Steffen
+ * HSR 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 drbg_hmac drbg_hmac
+ * @{ @ingroup drbg
+ */
+
+#ifndef DRBG_HMAC_H_
+#define DRBG_HMAC_H_
+
+#include <crypto/drbgs/drbg.h>
+
+typedef struct drbg_hmac_t drbg_hmac_t;
+
+/**
+ * NIST SP 800-90A HMAC DRBC implementation
+ */
+struct drbg_hmac_t {
+
+       /**
+        * Public Deterministic Random Bit Generator (DRBG) Interface
+        */
+       drbg_t interface;
+};
+
+/**
+ * Create a drbg_hmac instance.
+ *
+ * @param type                                 DRBG HMAC type
+ * @param strength                             security strength in bits
+ * @param entropy                              entropy source to be used
+ * @param personalization_str  optional personalization string
+ * @return                                             drbg_hmac_t object, NULL if not supported
+ */
+drbg_hmac_t *drbg_hmac_create(drbg_type_t type, uint32_t strength,
+                                                         rng_t *entropy, chunk_t personalization_str);
+
+#endif /** DRBG_HMAC_H_ @}*/
diff --git a/src/libstrongswan/plugins/drbg/drbg_plugin.c b/src/libstrongswan/plugins/drbg/drbg_plugin.c
new file mode 100644 (file)
index 0000000..bdf17b1
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 Andreas Steffen
+ * HSR 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 "drbg_plugin.h"
+#include "drbg_ctr.h"
+#include "drbg_hmac.h"
+
+#include <library.h>
+
+typedef struct private_drbg_plugin_t private_drbg_plugin_t;
+
+/**
+ * private data of drbg_plugin
+ */
+struct private_drbg_plugin_t {
+
+       /**
+        * public functions
+        */
+       drbg_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+       private_drbg_plugin_t *this)
+{
+       return "drbg";
+}
+
+METHOD(plugin_t, get_features, int,
+       private_drbg_plugin_t *this, plugin_feature_t *features[])
+{
+       static plugin_feature_t f[] = {
+               /* NIST CTR DRBG */
+               PLUGIN_REGISTER(DRBG, drbg_ctr_create),
+                       PLUGIN_PROVIDE(DRBG, DRBG_CTR_AES128),
+                               PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16),
+                       PLUGIN_PROVIDE(DRBG, DRBG_CTR_AES192),
+                               PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 24),
+                       PLUGIN_PROVIDE(DRBG, DRBG_CTR_AES256),
+                               PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 32),
+               /* NIST HMAC DRBG */
+               PLUGIN_REGISTER(DRBG, drbg_hmac_create),
+                       PLUGIN_PROVIDE(DRBG, DRBG_HMAC_SHA1),
+                               PLUGIN_DEPENDS(PRF, PRF_HMAC_SHA1),
+                       PLUGIN_PROVIDE(DRBG, DRBG_HMAC_SHA256),
+                               PLUGIN_DEPENDS(PRF, PRF_HMAC_SHA2_256),
+                       PLUGIN_PROVIDE(DRBG, DRBG_HMAC_SHA384),
+                               PLUGIN_DEPENDS(PRF, PRF_HMAC_SHA2_384),
+                       PLUGIN_PROVIDE(DRBG, DRBG_HMAC_SHA512),
+                               PLUGIN_DEPENDS(PRF, PRF_HMAC_SHA2_512),
+       };
+       *features = f;
+       return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+       private_drbg_plugin_t *this)
+{
+       free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *drbg_plugin_create()
+{
+       private_drbg_plugin_t *this;
+
+       INIT(this,
+               .public = {
+                       .plugin = {
+                               .get_name = _get_name,
+                               .get_features = _get_features,
+                               .destroy = _destroy,
+                       },
+               },
+       );
+
+       return &this->public.plugin;
+}
diff --git a/src/libstrongswan/plugins/drbg/drbg_plugin.h b/src/libstrongswan/plugins/drbg/drbg_plugin.h
new file mode 100644 (file)
index 0000000..f2fc743
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 Andreas Steffen
+ * HSR 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 drbg_p drbg
+ * @ingroup plugins
+ *
+ * @defgroup drbg_plugin drbg_plugin
+ * @{ @ingroup drbg_p
+ */
+
+#ifndef DRBG_PLUGIN_H_
+#define DRBG_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct drbg_plugin_t drbg_plugin_t;
+
+/**
+ * Plugin providing a NIST CTR and HMAC DRBG implementation
+ */
+struct drbg_plugin_t {
+
+       /**
+        * implements plugin interface
+        */
+       plugin_t plugin;
+};
+
+#endif /** DRBG_PLUGIN_H_ @}*/
index 2d2d5c6..852e235 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2017-2018 Tobias Brunner
  * Copyright (C) 2005 Jan Hutter
  * Copyright (C) 2005-2009 Martin Willi
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2019 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -155,31 +155,23 @@ static void mpz_clear_sensitive(mpz_t z)
 /**
  * Create a mpz prime of at least prime_size
  */
-static status_t compute_prime(size_t prime_size, bool safe, mpz_t *p, mpz_t *q)
+static status_t compute_prime(drbg_t *drbg, size_t prime_size, bool safe, mpz_t *p, mpz_t *q)
 {
-       rng_t *rng;
        chunk_t random_bytes;
        int count = 0;
 
-       rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
-       if (!rng)
-       {
-               DBG1(DBG_LIB, "no RNG of quality %N found", rng_quality_names,
-                        RNG_TRUE);
-               return FAILED;
-       }
-
        mpz_init(*p);
        mpz_init(*q);
+       random_bytes = chunk_alloc(prime_size);
 
        do
        {
-               if (!rng->allocate_bytes(rng, prime_size, &random_bytes))
+               if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr))
                {
                        DBG1(DBG_LIB, "failed to allocate random prime");
                        mpz_clear(*p);
                        mpz_clear(*q);
-                       rng->destroy(rng);
+                       chunk_free(&random_bytes);
                        return FAILED;
                }
 
@@ -205,13 +197,11 @@ static status_t compute_prime(size_t prime_size, bool safe, mpz_t *p, mpz_t *q)
                        mpz_import(*p, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
                        mpz_nextprime (*p, *p);
                }
-               chunk_clear(&random_bytes);
        }
-
        /* check if the prime isn't too large */
        while (((mpz_sizeinbase(*p, 2) + 7) / 8) > prime_size);
 
-       rng->destroy(rng);
+       chunk_clear(&random_bytes);
 
        /* additionally return p-1 */
        mpz_sub_ui(*q, *p, 1);
@@ -789,10 +779,14 @@ static private_gmp_rsa_private_key_t *gmp_rsa_private_key_create_empty(void)
 gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args)
 {
        private_gmp_rsa_private_key_t *this;
-       u_int key_size = 0, shares = 0, threshold = 1;
-       bool safe_prime = FALSE, rng_failed = FALSE, invert_failed = FALSE;
-       mpz_t p, q, p1, q1, d;
-;
+       drbg_type_t drbg_type = DRBG_HMAC_SHA512;
+       drbg_t* drbg;
+       rng_t *rng;
+       u_int strength = 256, key_size = 0, shares = 0, threshold = 1;
+       bool safe_prime = FALSE, drbg_failed = FALSE, invert_failed = FALSE;
+       mpz_t p, q, p1, q1;
+       int i;
+
 
        while (TRUE)
        {
@@ -823,15 +817,35 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args)
        }
        key_size = key_size / BITS_PER_BYTE;
 
+       /* Initiate a NIST SP 800-90A DRBG fed by a true random generator */
+       rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
+       if (!rng)
+       {
+               DBG1(DBG_LIB, "no RNG of quality %N found", rng_quality_names, RNG_TRUE);
+               return NULL;
+       }
+       drbg = lib->crypto->create_drbg(lib->crypto, drbg_type, strength, rng,
+                                                                       chunk_empty);
+       if (!drbg)
+       {
+               DBG1(DBG_LIB, "instantiation of %N failed", drbg_type_names, drbg_type);
+               rng->destroy(rng);
+               return NULL;
+       }
+
        /* Get values of primes p and q  */
-       if (compute_prime(key_size/2, safe_prime, &p, &p1) != SUCCESS)
+       if (compute_prime(drbg, key_size/2, safe_prime, &p, &p1) != SUCCESS)
        {
+               drbg->destroy(drbg);
+               rng->destroy(rng);
                return NULL;
        }
-       if (compute_prime(key_size/2, safe_prime, &q, &q1) != SUCCESS)
+       if (compute_prime(drbg, key_size/2, safe_prime, &q, &q1) != SUCCESS)
        {
                mpz_clear(p);
                mpz_clear(p1);
+               drbg->destroy(drbg);
+               rng->destroy(rng);
                return NULL;
        }
 
@@ -844,11 +858,17 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args)
 
        /* Create and initialize RSA private key object */
        this = gmp_rsa_private_key_create_empty();
+       *this->p = *p;
+       *this->q = *q;
+
+       /* allocate space for private exponent d with optional threshold scheme */
        this->shares = shares;
        this->threshold = threshold;
        this->d = malloc(threshold * sizeof(mpz_t));
-       *this->p = *p;
-       *this->q = *q;
+       for (i = 0; i < threshold; i++)
+       {
+               mpz_init(this->d[i]);
+       }
 
        mpz_init_set_ui(this->e, PUBLIC_EXPONENT);
        mpz_init(this->n);
@@ -857,71 +877,62 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args)
        mpz_init(this->exp2);
        mpz_init(this->coeff);
        mpz_init(this->v);
-       mpz_init(d);
 
-       mpz_mul(this->n, p, q);                                 /* n = p*q */
-       mpz_lcm(this->m, p1, q1);                               /* m = lcm(p-1,q-1) */
-       mpz_invert(d, this->e, this->m);                /* e has an inverse mod m */
-       mpz_mod(this->exp1, d, p1);                             /* exp1 = d mod p-1 */
-       mpz_mod(this->exp2, d, q1);                             /* exp2 = d mod q-1 */
-       mpz_invert(this->coeff, q, p);                  /* coeff = q^-1 mod p */
+       mpz_mul(this->n, p, q);                    /* n = p*q */
+       mpz_lcm(this->m, p1, q1);                  /* m = lcm(p-1,q-1) */
+       mpz_invert(this->d[0], this->e, this->m);  /* e has an inverse mod m */
+       mpz_mod(this->exp1, this->d[0], p1);       /* exp1 = d mod p-1 */
+       mpz_mod(this->exp2, this->d[0], q1);       /* exp2 = d mod q-1 */
+       mpz_invert(this->coeff, q, p);             /* coeff = q^-1 mod p */
 
        invert_failed = mpz_cmp_ui(this->m, 0) == 0 ||
                                        mpz_cmp_ui(this->coeff, 0) == 0;
 
-    /* store secret exponent d */
-       (*this->d)[0] = *d;
-
        /* generate and store random coefficients of secret sharing polynomial */
        if (threshold > 1)
        {
-               rng_t *rng;
                chunk_t random_bytes;
                mpz_t u;
-               int i;
 
-               rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
                mpz_init(u);
+               random_bytes = chunk_alloc(key_size);
 
                for (i = 1; i < threshold; i++)
                {
-                       mpz_init(d);
-
-                       if (!rng->allocate_bytes(rng, key_size, &random_bytes))
+                       if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr))
                        {
-                               rng_failed = TRUE;
+                               drbg_failed = TRUE;
                                continue;
                        }
-                       mpz_import(d, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
-                       mpz_mod(d, d, this->m);
-                       (*this->d)[i] = *d;
-                       chunk_clear(&random_bytes);
+                       mpz_import(this->d[i], random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
+                       mpz_mod(this->d[i], this->d[i], this->m);
                }
 
                /* generate verification key v as a square number */
                do
                {
-                       if (!rng->allocate_bytes(rng, key_size, &random_bytes))
+                       if (!drbg->generate(drbg, random_bytes.len, random_bytes.ptr))
                        {
-                               rng_failed = TRUE;
+                               drbg_failed = TRUE;
                                break;
                        }
                        mpz_import(this->v, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
                        mpz_mul(this->v, this->v, this->v);
                        mpz_mod(this->v, this->v, this->n);
                        mpz_gcd(u, this->v, this->n);
-                       chunk_free(&random_bytes);
                }
                while (mpz_cmp_ui(u, 1) != 0);
 
                mpz_clear(u);
-               rng->destroy(rng);
+               chunk_clear(&random_bytes);
        }
 
        mpz_clear_sensitive(p1);
        mpz_clear_sensitive(q1);
+       drbg->destroy(drbg);
+       rng->destroy(rng);
 
-       if (rng_failed || invert_failed)
+       if (drbg_failed || invert_failed)
        {
                DBG1(DBG_LIB, "rsa key generation failed");
                destroy(this);
index 4045544..b46afe1 100644 (file)
@@ -13,7 +13,6 @@ endif
 libstrongswan_ntru_la_SOURCES = \
        ntru_plugin.h ntru_plugin.c \
        ntru_convert.h ntru_convert.c \
-       ntru_drbg.h ntru_drbg.c \
        ntru_ke.h ntru_ke.c \
        ntru_param_set.h ntru_param_set.c \
        ntru_poly.h ntru_poly.c \
diff --git a/src/libstrongswan/plugins/ntru/ntru_drbg.c b/src/libstrongswan/plugins/ntru/ntru_drbg.c
deleted file mode 100644 (file)
index b7a951d..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (C) 2013 Andreas Steffen
- * HSR 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 "ntru_drbg.h"
-
-#include <utils/debug.h>
-#include <utils/test.h>
-
-#define        MAX_STRENGTH_BITS       256
-#define MAX_DRBG_REQUESTS      0xfffffffe
-
-typedef struct private_ntru_drbg_t private_ntru_drbg_t;
-
-/**
- * Private data of an ntru_drbg_t object.
- */
-struct private_ntru_drbg_t {
-       /**
-        * Public ntru_drbg_t interface.
-        */
-       ntru_drbg_t public;
-
-       /**
-        * Security strength in bits of the DRBG
-        */
-       uint32_t strength;
-
-       /**
-        * Number of requests for pseudorandom bits
-        */
-       uint32_t reseed_counter;
-
-       /**
-        * Maximum number of requests for pseudorandom bits
-        */
-       uint32_t max_requests;
-
-       /**
-        * True entropy source
-        */
-       rng_t *entropy;
-
-       /**
-        * HMAC-SHA256
-        */
-       signer_t *hmac;
-
-       /**
-        * Internal state of HMAC-SHA256: key
-        */
-       chunk_t key;
-
-       /**
-        * Internal state of HMAC-SHA256: value
-        */
-       chunk_t value;
-
-       /**
-        * reference count
-        */
-       refcount_t ref;
-};
-
-/**
- * Update the internal state of the HMAC_DRBG
- */
-static bool update(private_ntru_drbg_t *this, chunk_t data)
-{
-       chunk_t ch_00 = chunk_from_chars(0x00);
-       chunk_t ch_01 = chunk_from_chars(0x01);
-
-       if (!this->hmac->set_key(this->hmac, this->key) ||
-               !this->hmac->get_signature(this->hmac, this->value, NULL) ||
-           !this->hmac->get_signature(this->hmac, ch_00, NULL) ||
-           !this->hmac->get_signature(this->hmac, data, this->key.ptr) ||
-               !this->hmac->set_key(this->hmac, this->key) ||
-           !this->hmac->get_signature(this->hmac, this->value,
-                                                                                          this->value.ptr))
-       {
-               return FALSE;
-       }
-
-       if (data.len > 0)
-       {
-               if (!this->hmac->set_key(this->hmac, this->key) ||
-                       !this->hmac->get_signature(this->hmac, this->value, NULL) ||
-                       !this->hmac->get_signature(this->hmac, ch_01, NULL) ||
-                       !this->hmac->get_signature(this->hmac, data, this->key.ptr) ||
-                       !this->hmac->set_key(this->hmac, this->key) ||
-                       !this->hmac->get_signature(this->hmac, this->value,
-                                                                                                  this->value.ptr))
-               {
-                       return FALSE;
-               }
-       }
-       DBG4(DBG_LIB, "HMAC_DRBG V: %B", &this->value);
-       DBG4(DBG_LIB, "HMAC_DRBG K: %B", &this->key);
-
-       return TRUE;
-}
-
-METHOD(ntru_drbg_t, get_strength, uint32_t,
-       private_ntru_drbg_t *this)
-{
-       return this->strength;
-}
-
-METHOD(ntru_drbg_t, reseed, bool,
-       private_ntru_drbg_t *this)
-{
-       chunk_t seed;
-
-       seed = chunk_alloc(this->strength / BITS_PER_BYTE);
-       DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", seed.len);
-
-       if (!this->entropy->get_bytes(this->entropy, seed.len, seed.ptr))
-       {
-               chunk_free(&seed);
-               return FALSE;
-       }
-       if (!update(this, seed))
-       {
-               chunk_free(&seed);
-               return FALSE;
-       }
-       chunk_clear(&seed);
-       this->reseed_counter = 1;
-
-       return TRUE;
-}
-
-METHOD(ntru_drbg_t, generate, bool,
-       private_ntru_drbg_t *this, uint32_t strength, uint32_t len, uint8_t *out)
-{
-       size_t delta;
-       chunk_t output;
-
-       DBG2(DBG_LIB, "DRBG generates %u pseudorandom bytes", len);
-       if (!out || len == 0)
-       {
-               return FALSE;
-       }
-       output = chunk_create(out, len);
-
-       if (this->reseed_counter > this->max_requests)
-       {
-               if (!reseed(this))
-               {
-                       return FALSE;
-               }
-       }
-       while (len)
-       {
-               if (!this->hmac->get_signature(this->hmac, this->value,
-                                                                                                  this->value.ptr))
-               {
-                       return FALSE;
-               }
-               delta = min(len, this->value.len);
-               memcpy(out, this->value.ptr, delta);
-               len -= delta;
-               out += delta;
-       }
-       DBG4(DBG_LIB, "HMAC_DRBG Out: %B", &output);
-
-       if (!update(this, chunk_empty))
-       {
-               return FALSE;
-       }
-       this->reseed_counter++;
-
-       return TRUE;
-}
-
-METHOD(ntru_drbg_t, get_ref, ntru_drbg_t*,
-       private_ntru_drbg_t *this)
-{
-       ref_get(&this->ref);
-       return &this->public;
-}
-
-METHOD(ntru_drbg_t, destroy, void,
-       private_ntru_drbg_t *this)
-{
-       if (ref_put(&this->ref))
-       {
-               this->hmac->destroy(this->hmac);
-               chunk_clear(&this->key);
-               chunk_clear(&this->value);
-               free(this);
-       }
-}
-
-/*
- * Described in header.
- */
-ntru_drbg_t *ntru_drbg_create(uint32_t strength, chunk_t pers_str,
-                                                         rng_t *entropy)
-{
-       private_ntru_drbg_t *this;
-       chunk_t seed;
-       signer_t *hmac;
-       size_t entropy_len;
-       uint32_t max_requests;
-
-       if (strength > MAX_STRENGTH_BITS)
-       {
-               return NULL;
-       }
-       if (strength <= 112)
-       {
-               strength = 112;
-       }
-       else if (strength <= 128)
-       {
-               strength = 128;
-       }
-       else if (strength <= 192)
-       {
-               strength = 192;
-       }
-       else
-       {
-               strength = 256;
-       }
-
-       hmac = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_SHA2_256_256);
-       if (!hmac)
-       {
-               DBG1(DBG_LIB, "could not instantiate HMAC-SHA256");
-               return NULL;
-       }
-
-       max_requests = lib->settings->get_int(lib->settings,
-                                                                                 "%s.plugins.ntru.max_drbg_requests",
-                                                                                 MAX_DRBG_REQUESTS, lib->ns);
-
-       INIT(this,
-               .public = {
-                       .get_strength = _get_strength,
-                       .reseed = _reseed,
-                       .generate = _generate,
-                       .get_ref = _get_ref,
-                       .destroy = _destroy,
-               },
-               .strength = strength,
-               .entropy = entropy,
-               .hmac = hmac,
-               .key = chunk_alloc(hmac->get_key_size(hmac)),
-               .value = chunk_alloc(hmac->get_block_size(hmac)),
-               .max_requests = max_requests,
-               .reseed_counter = 1,
-               .ref = 1,
-       );
-
-       memset(this->key.ptr, 0x00, this->key.len);
-       memset(this->value.ptr, 0x01, this->value.len);
-
-       entropy_len = (strength + strength/2) / BITS_PER_BYTE;
-       seed = chunk_alloc(entropy_len + pers_str.len);
-       DBG2(DBG_LIB, "DRBG requests %u bytes of entropy", entropy_len);
-
-       if (!this->entropy->get_bytes(this->entropy, entropy_len, seed.ptr))
-       {
-               chunk_free(&seed);
-               destroy(this);
-               return NULL;
-       }
-       memcpy(seed.ptr + entropy_len, pers_str.ptr, pers_str.len);
-       DBG4(DBG_LIB, "seed: %B", &seed);
-
-       if (!update(this, seed))
-       {
-               chunk_free(&seed);
-               destroy(this);
-               return NULL;
-       }
-       chunk_clear(&seed);
-
-       return &this->public;
-}
-
-EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_drbg_create);
diff --git a/src/libstrongswan/plugins/ntru/ntru_drbg.h b/src/libstrongswan/plugins/ntru/ntru_drbg.h
deleted file mode 100644 (file)
index 31c12e4..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2013 Andreas Steffen
- * HSR 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 ntru_drbg ntru_drbg
- * @{ @ingroup ntru_p
- */
-
-#ifndef NTRU_DRBG_H_
-#define NTRU_DRBG_H_
-
-typedef struct ntru_drbg_t ntru_drbg_t;
-
-#include <library.h>
-
-/**
- * Implements a HMAC Deterministic Random Bit Generator (HMAC_DRBG)
- * compliant with NIST SP 800-90A
- */
-struct ntru_drbg_t {
-
-       /**
-        * Reseed the instantiated DRBG
-        *
-        * @return                      configured security strength in bits
-        */
-       uint32_t (*get_strength)(ntru_drbg_t *this);
-
-       /**
-        * Reseed the instantiated DRBG
-        *
-        * @return                      TRUE if successful
-        */
-       bool (*reseed)(ntru_drbg_t *this);
-
-       /**
-        * Generate pseudorandom bytes.
-        * If the maximum number of requests has been reached, reseeding occurs
-        *
-        * @param strength      requested security strength in bits
-        * @param len           number of octets to generate
-        * @param out           address of output buffer
-        * @return                      TRUE if successful
-        */
-       bool (*generate)(ntru_drbg_t *this, uint32_t strength, uint32_t len,
-                                                                               uint8_t *out);
-
-       /**
-        * Get a reference on an ntru_drbg_t object increasing the count by one
-        *
-        * @return                      reference to the ntru_drbg_t object
-        */
-       ntru_drbg_t* (*get_ref)(ntru_drbg_t *this);
-
-       /**
-        * Uninstantiate and destroy the DRBG object
-        */
-       void (*destroy)(ntru_drbg_t *this);
-};
-
-/**
- * Create and instantiate a new DRBG object.
- *
- * @param strength             security strength in bits
- * @param pers_str             personalization string
- * @param entropy              entropy source to use
- */
-ntru_drbg_t *ntru_drbg_create(uint32_t strength, chunk_t pers_str,
-                                                         rng_t *entropy);
-
-#endif /** NTRU_DRBG_H_ @}*/
-
index 17309b1..7fb4439 100644 (file)
  */
 
 #include "ntru_ke.h"
-#include "ntru_drbg.h"
 #include "ntru_param_set.h"
 #include "ntru_private_key.h"
 #include "ntru_public_key.h"
 
 #include <crypto/diffie_hellman.h>
+#include <crypto/drbgs/drbg.h>
 #include <utils/debug.h>
 
 typedef struct private_ntru_ke_t private_ntru_ke_t;
@@ -106,7 +106,7 @@ struct private_ntru_ke_t {
        /**
         * Deterministic Random Bit Generator
         */
-       ntru_drbg_t *drbg;
+       drbg_t *drbg;
 };
 
 METHOD(diffie_hellman_t, get_my_public_value, bool,
@@ -199,8 +199,8 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
                this->shared_secret = chunk_alloc(2 * this->strength / BITS_PER_BYTE);
 
                /* generate the random shared secret */
-               if (!this->drbg->generate(this->drbg, this->strength,
-                               this->shared_secret.len, this->shared_secret.ptr))
+               if (!this->drbg->generate(this->drbg, this->shared_secret.len,
+                                                                                         this->shared_secret.ptr))
                {
                        DBG1(DBG_LIB, "generation of shared secret failed");
                        chunk_free(&this->shared_secret);
@@ -246,7 +246,7 @@ ntru_ke_t *ntru_ke_create(diffie_hellman_group_t group, chunk_t g, chunk_t p)
        const ntru_param_set_id_t *param_sets;
        ntru_param_set_id_t param_set_id;
        rng_t *entropy;
-       ntru_drbg_t *drbg;
+       drbg_t *drbg;
        char *parameter_set;
        uint32_t strength;
 
@@ -301,7 +301,8 @@ ntru_ke_t *ntru_ke_create(diffie_hellman_group_t group, chunk_t g, chunk_t p)
                return NULL;
        }
 
-       drbg = ntru_drbg_create(strength, chunk_from_str("IKE NTRU-KE"), entropy);
+       drbg = lib->crypto->create_drbg(lib->crypto, DRBG_HMAC_SHA256, strength,
+                                                                       entropy, chunk_from_str("IKE NTRU-KE"));
        if (!drbg)
        {
                DBG1(DBG_LIB, "could not instantiate DRBG at %u bit security", strength);
index 1acab3b..c86044a 100644 (file)
@@ -58,7 +58,7 @@ struct private_ntru_private_key_t {
        /**
         * Deterministic Random Bit Generator
         */
-       ntru_drbg_t *drbg;
+       drbg_t *drbg;
 
 };
 
@@ -640,7 +640,7 @@ static bool ring_inv(uint16_t *a, uint16_t N, uint16_t q, uint16_t *t,
 /*
  * Described in header.
  */
-ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg,
+ntru_private_key_t *ntru_private_key_create(drbg_t *drbg,
                                                                                        const ntru_param_set_t *params)
 {
        private_ntru_private_key_t *this;
@@ -671,8 +671,7 @@ ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg,
        seed =chunk_alloc(params->sec_strength_len + 8);
 
        /* get random seed for generating trinary F as a list of indices */
-       if (!drbg->generate(drbg, params->sec_strength_len * BITS_PER_BYTE,
-                                                         seed.len, seed.ptr))
+       if (!drbg->generate(drbg, seed.len, seed.ptr))
        {
                goto err;
        }
@@ -715,8 +714,7 @@ ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg,
        }
 
        /* get random seed for generating trinary g as a list of indices */
-       if (!drbg->generate(drbg, params->sec_strength_len * BITS_PER_BYTE,
-                                                         seed.len, seed.ptr))
+       if (!drbg->generate(drbg, seed.len, seed.ptr))
        {
                goto err;
        }
@@ -760,7 +758,7 @@ err:
 /*
  * Described in header.
  */
-ntru_private_key_t *ntru_private_key_create_from_data(ntru_drbg_t *drbg,
+ntru_private_key_t *ntru_private_key_create_from_data(drbg_t *drbg,
                                                                                                          chunk_t data)
 {
        private_ntru_private_key_t *this;
index ced806d..69a7c06 100644 (file)
 
 typedef struct ntru_private_key_t ntru_private_key_t;
 
-#include "ntru_drbg.h"
 #include "ntru_param_set.h"
 #include "ntru_public_key.h"
 
 #include <library.h>
+#include <crypto/drbgs/drbg.h>
 
 /**
  * Implements an NTRU encryption public/private key pair
@@ -77,7 +77,7 @@ struct ntru_private_key_t {
  * @param drbg                 Digital Random Bit Generator used for key generation
  * @param params               NTRU encryption parameter set to be used
  */
-ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg,
+ntru_private_key_t *ntru_private_key_create(drbg_t *drbg,
                                                                                        const ntru_param_set_t *params);
 
 /**
@@ -86,7 +86,7 @@ ntru_private_key_t *ntru_private_key_create(ntru_drbg_t *drbg,
  * @param drbg                 Deterministic random bit generator
  * @param data                 Encoded NTRU private key
  */
-ntru_private_key_t *ntru_private_key_create_from_data(ntru_drbg_t *drbg,
+ntru_private_key_t *ntru_private_key_create_from_data(drbg_t *drbg,
                                                                                                          chunk_t data);
 
 #endif /** NTRU_PRIVATE_KEY_H_ @}*/
index 36d9abf..3d70e23 100644 (file)
@@ -52,7 +52,7 @@ struct private_ntru_public_key_t {
        /**
         * Deterministic Random Bit Generator
         */
-       ntru_drbg_t *drbg;
+       drbg_t *drbg;
 
 };
 
@@ -152,9 +152,7 @@ METHOD(ntru_public_key_t, encrypt, bool,
        /* loop until a message representative with proper weight is achieved */
        do
        {
-               if (!this->drbg->generate(this->drbg,
-                                                                 this->params->sec_strength_len * BITS_PER_BYTE,
-                                                                 this->params->sec_strength_len, b))
+               if (!this->drbg->generate(this->drbg, this->params->sec_strength_len, b))
                {
                        goto err;
                }
@@ -319,7 +317,7 @@ METHOD(ntru_public_key_t, destroy, void,
 /*
  * Described in header.
  */
-ntru_public_key_t *ntru_public_key_create(ntru_drbg_t *drbg,
+ntru_public_key_t *ntru_public_key_create(drbg_t *drbg,
                                                                                  const ntru_param_set_t *params,
                                                                                  uint16_t *pubkey)
 {
@@ -352,7 +350,7 @@ ntru_public_key_t *ntru_public_key_create(ntru_drbg_t *drbg,
 /*
  * Described in header.
  */
-ntru_public_key_t *ntru_public_key_create_from_data(ntru_drbg_t *drbg,
+ntru_public_key_t *ntru_public_key_create_from_data(drbg_t *drbg,
                                                                                                        chunk_t data)
 {
        private_ntru_public_key_t *this;
index 4f098f2..9803211 100644 (file)
@@ -24,9 +24,9 @@
 typedef struct ntru_public_key_t ntru_public_key_t;
 
 #include "ntru_param_set.h"
-#include "ntru_drbg.h"
 
 #include <library.h>
+#include <crypto/drbgs/drbg.h>
 
 /**
  * Implements an NTRU encryption public key
@@ -70,7 +70,7 @@ struct ntru_public_key_t {
  * @param params               NTRU encryption parameter set to be used
  * @param pubkey               Coefficients of public key polynomial h
  */
-ntru_public_key_t *ntru_public_key_create(ntru_drbg_t *drbg,
+ntru_public_key_t *ntru_public_key_create(drbg_t *drbg,
                                                                                  const ntru_param_set_t *params,
                                                                                  uint16_t *pubkey);
 
@@ -80,7 +80,7 @@ ntru_public_key_t *ntru_public_key_create(ntru_drbg_t *drbg,
  * @param drbg                 Deterministic random bit generator
  * @param data                 Encoded NTRU public key
  */
-ntru_public_key_t *ntru_public_key_create_from_data(ntru_drbg_t *drbg,
+ntru_public_key_t *ntru_public_key_create_from_data(drbg_t *drbg,
                                                                                                        chunk_t data);
 
 
index b42632f..6967ac2 100644 (file)
@@ -49,7 +49,7 @@ ENUM_NEXT(ck_rv_names, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID,
        "ATTRIBUTE_VALUE_INVALID");
 ENUM_NEXT(ck_rv_names, CKR_DATA_INVALID, CKR_DATA_LEN_RANGE,
                CKR_ATTRIBUTE_VALUE_INVALID,
-       "DATA_INVALID"
+       "DATA_INVALID",
        "DATA_LEN_RANGE");
 ENUM_NEXT(ck_rv_names, CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED,
                CKR_DATA_LEN_RANGE,
@@ -540,6 +540,7 @@ ENUM_NEXT(ck_attr_names, CKA_HW_FEATURE_TYPE, CKA_HAS_RESET,
        "HAS_RESET");
 ENUM_NEXT(ck_attr_names, CKA_PIXEL_X, CKA_BITS_PER_PIXEL, CKA_HAS_RESET,
        "PIXEL_X",
+       "PIXEL_Y",
        "RESOLUTION",
        "CHAR_ROWS",
        "CHAR_COLUMNS",
index 844698b..fa3d1f3 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2012-2015 Tobias Brunner
+ * Copyright (C) 2016-2019 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * Copyright (C) 2011 Martin Willi
@@ -31,6 +32,7 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
        "HASHER",
        "PRF",
        "XOF",
+       "DRBG",
        "DH",
        "RNG",
        "NONCE_GEN",
@@ -91,6 +93,9 @@ uint32_t plugin_feature_hash(plugin_feature_t *feature)
                case FEATURE_XOF:
                        data = chunk_from_thing(feature->arg.xof);
                        break;
+               case FEATURE_DRBG:
+                       data = chunk_from_thing(feature->arg.drbg);
+                       break;
                case FEATURE_DH:
                        data = chunk_from_thing(feature->arg.dh_group);
                        break;
@@ -166,6 +171,8 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
                                return a->arg.prf == b->arg.prf;
                        case FEATURE_XOF:
                                return a->arg.xof == b->arg.xof;
+                       case FEATURE_DRBG:
+                               return a->arg.drbg == b->arg.drbg;
                        case FEATURE_DH:
                                return a->arg.dh_group == b->arg.dh_group;
                        case FEATURE_RNG:
@@ -225,6