aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/win32/Configure.py
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/win32/Configure.py')
-rw-r--r--SoftHSMv2/win32/Configure.py1167
1 files changed, 1167 insertions, 0 deletions
diff --git a/SoftHSMv2/win32/Configure.py b/SoftHSMv2/win32/Configure.py
new file mode 100644
index 0000000..a39a046
--- /dev/null
+++ b/SoftHSMv2/win32/Configure.py
@@ -0,0 +1,1167 @@
+#!python
+
+# Configure -- python version
+#
+# this script builds Visual Studio files
+
+from __future__ import print_function
+
+import sys
+import os
+import os.path
+import re
+import subprocess
+
+# files to configure
+
+filelist = ["config.h",
+ "softhsm2.sln",
+ "convarch\\convarch.vcxproj.filters",
+ "convarch\\convarch.vcxproj",
+ "cryptotest\\cryptotest.vcxproj",
+ "datamgrtest\\datamgrtest.vcxproj",
+ "dump\\dump.vcxproj",
+ "handlemgrtest\\handlemgrtest.vcxproj",
+ "keyconv\\keyconv.vcxproj.filters",
+ "keyconv\\keyconv.vcxproj",
+ "objstoretest\\objstoretest.vcxproj",
+ "p11test\\p11test.vcxproj",
+ "sessionmgrtest\\sessionmgrtest.vcxproj",
+ "slotmgrtest\\slotmgrtest.vcxproj",
+ "softhsm2\\softhsm2.vcxproj",
+ "util\\util.vcxproj.filters",
+ "util\\util.vcxproj"]
+
+# test files
+testlist = ["botan",
+ "ecc",
+ "gnump",
+ "gost",
+ "ossl",
+ "osslv",
+ "rawpss",
+ "rfc3394",
+ "rfc5649"]
+
+# variables to expand
+
+varvals = {}
+
+varnames = ["CUINCPATH",
+ "CULIBPATH",
+ "DEBUGDLLPATH",
+ "DEBUGINCPATH",
+ "DEBUGLIBPATH",
+ "DLLPATH",
+ "EXTRALIBS",
+ "INCLUDEPATH",
+ "LIBNAME",
+ "LIBPATH",
+ "PLATFORM",
+ "PLATFORMDIR",
+ "PLATFORMTOOLSET",
+ "RUNTIMELIBRARY"]
+
+# conditions to stack
+
+condvals = {}
+
+condnames = ["AESGCM",
+ "BOTAN",
+ "ECC",
+ "GOST",
+ "NONPAGE",
+ "OPENSSL",
+ "RAWPSS",
+ "RFC3394",
+ "RFC5649",
+ "TESTS"]
+
+# enable-xxx/disable-xxx arguments
+
+enablelist = ["64bit",
+ "debug",
+ "ecc",
+ "gost",
+ "keep",
+ "non-paged-memory",
+ "static-runtime",
+ "verbose"]
+
+# with-xxx/without-xxx arguments
+
+withlist = ["botan",
+ "cppunit",
+ "crypto-backend",
+ "debug-botan",
+ "debug-openssl",
+ "openssl",
+ "toolset"]
+
+# general commands
+
+commandlist = ["help", "clean"] # verbose, keep
+
+# usage
+
+usage = ["Usage: python Configure.py help",
+ " python Configure.py options*",
+ " python Configure.py clean"]
+
+# help
+
+myhelp = ["'python Configure.py' configures SoftHSMv2 build files.\n"] +\
+usage + [\
+"\nGeneral Commands:",
+" help print this help",
+" clean clean up generated files",
+" <none> print a summary of the configuration",
+"\nOptional Features:",
+" enable-verbose print messages [default=no]",
+" enable-keep keep test files after config [default=no]",
+" enable-64bit enable 64-bit compiling [default=no]",
+" enable-debug enable build of Debug config [default=yes]",
+" enable-ecc enable support for ECC [default=yes]",
+" enable-gost enable support for GOST [default=yes]",
+" enable-static-runtime enable build with static CRT (/MT) [default=no]",
+" enable-non-paged-memory enable non-paged memory [default=yes]",
+"\nOptional Packages:",
+" with-crypto-backend select the crypto backend [openssl|botan]",
+" with-botan=PATH speficy prefix of path of Botan (Release)",
+" with-debug-botan=PATH speficy prefix of path of Botan (Debug)",
+" with-openssl=PATH speficy prefix of path of OpenSSL (Release)",
+" with-debug-openssl=PATH speficy prefix of path of OpenSSL (Debug)",
+" with-cppunit=PATH specify prefix of path of CppUnit",
+" with-toolset=VALUE set Visual Studio platform toolset version (eg v110 for vs2012)",
+]
+
+# variables for parsing
+
+verbose = False
+configargs = None
+want_help = False
+want_clean = False
+want_unknown = False
+unknown_value = None
+enable_keep = False
+enable_debug = True
+enable_ecc = True
+enable_gost = True
+enable_static_runtime = False
+enable_non_paged = True
+platform = 32
+crypto_backend = "openssl"
+botan_path = "..\\..\\btn"
+debug_botan_path = None
+openssl_path = "..\\..\\ssl"
+debug_openssl_path = None
+want_tests = True
+cppunit_path = "..\\..\\cu"
+toolset = ""
+
+def dodetectplatform(visualstudio):
+ # detect platform tool set >= VS2010
+ global toolset
+
+ if "Microsoft Visual Studio 10.0" in visualstudio:
+ toolset="v100"
+ elif "Microsoft Visual Studio 11.0" in visualstudio:
+ toolset="v110"
+ elif "Microsoft Visual Studio 12.0" in visualstudio:
+ toolset="v120"
+ elif "Microsoft Visual Studio 14.0" in visualstudio:
+ toolset="v140"
+ else:
+ print("PlatformToolset for \""+visualstudio+"\" not supported")
+ toolset=""
+
+def dodetectvisualstudio():
+ """detect visual studio version"""
+ if os.environ.get('VSINSTALLDIR'):
+ dodetectplatform(os.environ.get('VSINSTALLDIR'))
+
+def parseargs(args):
+ """parse arguments"""
+ global verbose
+ global enable_keep
+ global want_help
+ global want_clean
+ global want_unknown
+ global unknown_value
+ global debug_botan_path
+ global debug_openssl_path
+ for arg in args:
+ if arg.lower() == "verbose":
+ verbose = True
+ continue
+ if arg.lower() == "keep":
+ enable_keep = True
+ continue
+ if arg.lower() == "help":
+ want_help = True
+ continue
+ di = re.match(r'disable-(.*)', arg, re.I)
+ if di:
+ appargs(arg)
+ myenable(di.group(1), False)
+ continue
+ en = re.match(r'enable-(.*)', arg, re.I)
+ if en:
+ appargs(arg)
+ myenable(en.group(1), True)
+ continue
+ wo = re.match(r'without-(.*)', arg, re.I)
+ if wo:
+ appargs(arg)
+ mywith(wo.group(1), False)
+ continue
+ wv = re.match(r'with-(.*)=(.*)', arg, re.I)
+ if wv:
+ appargs(arg)
+ if wv.group(2).lower() == "no":
+ mywith(wv.group(1), False)
+ continue
+ mywith(wv.group(1), True, wv.group(2))
+ continue
+ wi = re.match(r'with-(.*)', arg, re.I)
+ if wi:
+ appargs(arg)
+ mywith(wi.group(1), True)
+ continue
+ if arg.lower() == "clean":
+ want_clean = True
+ continue
+ want_unknown = True
+ unknown_value = arg
+ break
+
+ # debug
+ if enable_debug:
+ if debug_botan_path is None:
+ debug_botan_path = botan_path + "_d"
+ if debug_openssl_path is None:
+ debug_openssl_path = openssl_path + "_d"
+
+def appargs(arg):
+ """append seen arguments to configargs"""
+ global configargs
+ # escape backslashes, spaces and double quotes
+ escaped = ""
+
+ for x in arg:
+ if (x == "\\") or (x == " ") or (x == "\""):
+ escaped += "\\"
+ escaped += x
+ if configargs:
+ configargs += " " + escaped
+ else:
+ configargs = escaped
+
+def myenable(key, val):
+ """parse enable/disable"""
+ global platform
+ global enable_debug
+ global enable_ecc
+ global enable_gost
+ global enable_static_runtime
+ global enable_non_paged
+ global enable_keep
+ global verbose
+ global want_unknown
+ global unknown_value
+ if key.lower() == "64bit":
+ if val:
+ platform = 64
+ return
+ if key.lower() == "debug":
+ if not val:
+ enable_debug = False
+ return
+ if key.lower() == "ecc":
+ if not val:
+ enable_ecc = False
+ return
+ if key.lower() == "gost":
+ if not val:
+ enable_gost = False
+ return
+ if key.lower() == "static-runtime":
+ if val:
+ enable_static_runtime = True
+ return
+ if key.lower() == "non-paged-memory":
+ if not val:
+ enable_non_paged = False
+ return
+ if key.lower() == "keep":
+ if val:
+ enable_keep = True
+ return
+ if key.lower() == "verbose":
+ if val:
+ verbose = True
+ return
+ want_unknown = True
+ if not val:
+ unknown_value = "disable-" + key
+ else:
+ unknown_value = "enable-" + key
+
+def mywith(key, val, detail=None):
+ """parse with/without"""
+ global crypto_backend
+ global botan_path
+ global debug_botan_path
+ global openssl_path
+ global debug_openssl_path
+ global want_tests
+ global cppunit_path
+ global want_unknown
+ global unknown_value
+ global toolset
+
+ if key.lower() == "crypto-backend":
+ if val and (detail.lower() == "openssl"):
+ crypto_backend = "openssl"
+ return
+ if val and (detail.lower() == "botan"):
+ crypto_backend = "botan"
+ return
+ want_unknown = True
+ unknown_value = "with-crypto-backend=" + detail
+ return
+ if key.lower() == "botan":
+ if not val:
+ want_unknown = True
+ unknown_value = "without-botan doesn't make sense"
+ return
+ if detail.lower() != "yes":
+ botan_path = detail
+ return
+ if key.lower() == "debug-botan":
+ if not val:
+ want_unknown = True
+ unknown_value = "without-debug-botan doesn't make sense"
+ return
+ if detail.lower() != "yes":
+ debug_botan_path = detail
+ return
+ if key.lower() == "openssl":
+ if not val:
+ want_unknown = True
+ unknown_value = "without-openssl doesn't make sense"
+ return
+ if detail.lower() != "yes":
+ openssl_path = detail
+ return
+ if key.lower() == "debug-openssl":
+ if not val:
+ want_unknown = True
+ unknown_value = "without-debug-openssl doesn't make sense"
+ return
+ if detail.lower() != "yes":
+ debug_openssl_path = detail
+ return
+ if key.lower() == "cppunit":
+ if not val:
+ want_tests = False
+ return
+ if detail.lower() != "yes":
+ cppunit_path = detail
+ return
+ if key.lower() == "toolset":
+ if not val:
+ want_tests = False
+ return
+ if detail:
+ toolset=detail.lower()
+ return
+ want_unknown = True
+ if not val:
+ unknown_value = "without-" + key
+ else:
+ unknown_value = "with-" + key
+
+def dohelp():
+ """help"""
+ for line in myhelp:
+ print(line)
+ sys.exit(1)
+
+def docleantest():
+ """clean test files"""
+ for basename in testlist:
+ filename = "test" + basename + ".c"
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ filename = "test" + basename + ".cpp"
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ filename = "test" + basename + ".obj"
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ filename = "test" + basename + ".exe"
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ if os.path.isfile("botan.dll"):
+ os.unlink("botan.dll")
+ if os.path.isfile("libeay32.dll"):
+ os.unlink("libeay32.dll")
+ if os.path.isfile("libeaycompat32.dll"):
+ os.unlink("libeaycompat32.dll")
+ if os.path.isfile("libcrypto-1_1.dll"):
+ os.unlink("libcrypto-1_1.dll")
+ if os.path.isfile("libcrypto-1_1-x64.dll"):
+ os.unlink("libcrypto-1_1-x64.dll")
+
+def doclean():
+ """clean"""
+ docleantest()
+ for filename in filelist:
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ sys.exit(0)
+
+def dounknown():
+ """parsing error"""
+ print("can't parse " + unknown_value + "", file=sys.stderr)
+ sys.exit(1)
+
+def doconfig():
+ """config itself"""
+ global botan_path
+ global debug_botan_path
+ global openssl_path
+ global debug_openssl_path
+ global cppunit_path
+
+ # configure the platform
+ if platform == 32:
+ varvals["PLATFORM"] = "Win32"
+ else:
+ varvals["PLATFORM"] = "x64"
+ varvals["PLATFORMDIR"] = "x64\\"
+
+ # configure the runtime library
+ if enable_static_runtime:
+ varvals["RUNTIMELIBRARY"] = "MultiThreaded"
+ else:
+ varvals["RUNTIMELIBRARY"] = "MultiThreadedDLL"
+
+ # configure ECC and GOST
+ if enable_ecc:
+ condvals["ECC"] = True
+ if enable_gost:
+ condvals["GOST"] = True
+
+ # configure the crypto
+ if crypto_backend == "botan":
+ condvals["BOTAN"] = True
+ varvals["LIBNAME"] = "botan.lib"
+ botan_path = os.path.abspath(botan_path)
+ botan_inc = os.path.join(botan_path, "include")
+ botan_dll = ""
+ if os.path.exists(os.path.join(botan_inc, "botan-2\\botan\\init.h")):
+ varvals["INCLUDEPATH"] = os.path.join(botan_inc, "botan-2")
+ elif os.path.exists(os.path.join(botan_inc, "botan-1.11\\botan\\init.h")):
+ varvals["INCLUDEPATH"] = os.path.join(botan_inc, "botan-1.11")
+ elif os.path.exists(os.path.join(botan_inc, "botan\\init.h")):
+ varvals["INCLUDEPATH"] = botan_inc
+ else:
+ print("can't find Botan includes", file=sys.stderr)
+ sys.exit(1)
+ if os.path.exists(os.path.join(botan_path, "lib\\botan.lib")):
+ varvals["LIBPATH"] = os.path.join(botan_path, "lib")
+ botan_dll = os.path.join(botan_path, "lib\\botan.dll")
+ elif os.path.exists(os.path.join(botan_path, "botan.lib")):
+ varvals["LIBPATH"] = botan_path
+ botan_dll = os.path.join(botan_path, "botan.dll")
+ else:
+ print("can't find Botan library", file=sys.stderr)
+ sys.exit(1)
+ varvals["DLLPATH"] = botan_dll
+ if enable_debug:
+ debug_botan_path = os.path.abspath(debug_botan_path)
+ debug_botan_inc = os.path.join(debug_botan_path, "include")
+ debug_botan_dll = ""
+ if os.path.exists(os.path.join(debug_botan_inc, "botan-2\\botan\\init.h")):
+ varvals["DEBUGINCPATH"] = os.path.join(debug_botan_inc, "botan-2")
+ elif os.path.exists(os.path.join(debug_botan_inc, "botan-1.11\\botan\\init.h")):
+ varvals["DEBUGINCPATH"] = os.path.join(debug_botan_inc, "botan-1.11")
+ elif os.path.exists(os.path.join(debug_botan_inc, "botan\\init.h")):
+ varvals["DEBUGINCPATH"] = debug_botan_inc
+ else:
+ print("can't find debug Botan includes", file=sys.stderr)
+ sys.exit(1)
+ if os.path.exists(os.path.join(debug_botan_path, "lib\\botan.lib")):
+ varvals["DEBUGLIBPATH"] = os.path.join(debug_botan_path, "lib")
+ debug_botan_dll = os.path.join(debug_botan_path, "lib\\botan.dll")
+ if os.path.exists(os.path.join(debug_botan_path, "botan.lib")):
+ varvals["DEBUGLIBPATH"] = debug_botan_path
+ debug_botan_dll = os.path.join(debug_botan_path, "botan.dll")
+ else:
+ print("can't find debug Botan library", file=sys.stderr)
+ sys.exit(1)
+ varvals["DEBUGDLLPATH"] = debug_botan_dll
+ else:
+ varvals["DEBUGDLLPATH"] = varvals["DLLPATH"]
+ varvals["DEBUGINCPATH"] = varvals["INCLUDEPATH"]
+ varvals["DEBUGLIBPATH"] = varvals["LIBPATH"]
+
+ # Botan version
+ if verbose:
+ print("checking Botan version")
+ botan_version_major = 0
+ botan_version_minor = 0
+ system_libs = []
+ if os.path.exists(botan_dll):
+ subprocess.call(["copy", botan_dll, "."], shell=True)
+ else:
+ system_libs = ["user32.lib", "advapi32.lib"]
+ inc = varvals["INCLUDEPATH"]
+ lib = os.path.join(varvals["LIBPATH"], "botan.lib")
+ testfile = open("testbotan.cpp", "w")
+ print('\
+#include <botan/version.h>\n\
+int main() {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)\n\
+ return 3;\n\
+#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)\n\
+ return 2;\n\
+#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)\n\
+ return 1;\n\
+#else\n\
+ return 0;\n\
+#endif\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testbotan.cpp", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testbotan.exe"):
+ print("can't create .\\testbotan.exe", file=sys.stderr)
+ sys.exit(1)
+ ret = subprocess.call(".\\testbotan.exe")
+ if ret == 0:
+ print("Botan version too old", file=sys.stderr)
+ sys.exit(1)
+ elif ret == 1:
+ botan_version_major = 1
+ botan_version_minor = 10
+ elif ret == 2:
+ botan_version_major = 1
+ botan_version_minor = 11
+ print("Botan version 1.11 not yet supported", file=sys.stderr)
+ sys.exit(1)
+ elif ret == 3:
+ botan_version_major = 2
+ botan_version_minor = 0
+ print("Botan version 2.0 not yet supported", file=sys.stderr)
+ sys.exit(1)
+ else:
+ print("Botan test failed", file=sys.stderr)
+ sys.exit(1)
+
+ # Botan ECC support
+ if enable_ecc:
+ if verbose:
+ print("checking Botan ECC support")
+ testfile = open("testecc.cpp", "w")
+ print('\
+#include <botan/init.h>\n\
+#include <botan/ec_group.h>\n\
+#include <botan/oids.h>\n\
+#include <botan/version.h>\n\
+int main() {\n\
+ Botan::LibraryInitializer::initialize();\n\
+ const std::string name("secp256r1");\n\
+ const Botan::OID oid(Botan::OIDS::lookup(name));\n\
+ const Botan::EC_Group ecg(oid);\n\
+ try {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)\n\
+ const std::vector<Botan::byte> der =\n\
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);\n\
+#else\n\
+ const Botan::SecureVector<Botan::byte> der =\n\
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);\n\
+#endif\n\
+ } catch(...) {\n\
+ return 1;\n\
+ }\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testecc.cpp", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testecc.exe"):
+ print("can't create .\\testecc.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testecc.exe") != 0:
+ print("can't find P256: upgrade to Botan >= 1.10.6", file=sys.stderr)
+ sys.exit(1)
+
+ # Botan GOST support
+ if enable_gost:
+ if verbose:
+ print("checking Botan GOST support")
+ testfile = open("testgost.cpp", "w")
+ print('\
+#include <botan/init.h>\n\
+#include <botan/gost_3410.h>\n\
+#include <botan/oids.h>\n\
+#include <botan/version.h>\n\
+int main() {\n\
+ Botan::LibraryInitializer::initialize();\n\
+ const std::string name("gost_256A");\n\
+ const Botan::OID oid(Botan::OIDS::lookup(name));\n\
+ const Botan::EC_Group ecg(oid);\n\
+ try {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)\n\
+ const std::vector<Botan::byte> der =\n\
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);\n\
+#else\n\
+ const Botan::SecureVector<Botan::byte> der =\n\
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);\n\
+#endif\n\
+ } catch(...) {\n\
+ return 1;\n\
+ }\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testgost.cpp", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testgost.exe"):
+ print("can't create .\\testgost.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testgost.exe") != 0:
+ print("can't find GOST: upgrade to Botan >= 1.10.6", file=sys.stderr)
+ sys.exit(1)
+
+ # no check for Botan RFC3394 support
+ condvals["RFC3394"] = True
+
+ # Botan RFC5649 support
+ if verbose:
+ print("checking Botan RFC5649 support")
+ testfile = open("testrfc5649.cpp", "w")
+ print('\
+#include <botan/botan.h>\n\
+#include <botan/rfc3394.h>\n\
+#include <botan/version.h>\n\
+using namespace Botan;\n\
+int main() {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)\n\
+ secure_vector<byte> key(10);\n\
+ SymmetricKey kek("AABB");\n\
+ secure_vector<byte> x = rfc5649_keywrap(key, kek);\n\
+#else\n\
+ SecureVector<byte> key(10);\n\
+ SymmetricKey kek("AABB");\n\
+ Algorithm_Factory& af = global_state().algorithm_factory();\n\
+ SecureVector<byte> x = rfc5649_keywrap(key, kek, af);\n\
+#endif\n\
+ return 1;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/EHsc","/I", inc, "testrfc5649.cpp", lib]
+ command.extend(system_libs)
+ subprocess.call(command)
+ if os.path.exists(".\\testrfc5649.exe"):
+ if verbose:
+ print("Found AES key wrap with pad")
+ condvals["RFC5649"] = True
+ else:
+ if verbose:
+ print("can't compile Botan AES key wrap with pad")
+
+ # Botan GNU MP support
+ if botan_version_major == 1 and botan_version_minor == 10:
+ if verbose:
+ print("checking Botan GNU MP support")
+ testfile = open("testgnump.cpp", "w")
+ print('\
+#include <botan/build.h>\n\
+int main() {\n\
+#ifndef BOTAN_HAS_ENGINE_GNU_MP\n\
+#error "No GNU MP support";\n\
+#endif\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testgnump.cpp", lib]
+ command.extend(system_libs)
+ subprocess.call(command)
+ if os.path.exists(".\\testgnump.exe"):
+ if verbose:
+ print("Botan GNU MP is supported")
+ else:
+ if verbose:
+ print("Botan GNU MP is not supported")
+
+ # Botan raw PSS support
+ if verbose:
+ print("checking Botan raw PSS support")
+ testfile = open("testrawpss.cpp", "w")
+ print('\
+#include <botan/botan.h>\n\
+#include <botan/version.h>\n\
+int main() {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,3,0)\n\
+ return 0;\n\
+#endif\n\
+ return 1;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testrawpss.cpp", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testrawpss.exe"):
+ if verbose:
+ print("can't create .\\testrawpss.exe", file=sys.stderr)
+ else:
+ if subprocess.call(".\\testrawpss.exe") != 0:
+ if verbose:
+ print("can't find raw PSS: upgrade to Botan >= 2.3.0", file=sys.stderr)
+ else:
+ condvals["RAWPSS"] = True
+
+ else:
+
+ condvals["OPENSSL"] = True
+ varvals["EXTRALIBS"] = "crypt32.lib;ws2_32.lib;"
+ openssl_path = os.path.abspath(openssl_path)
+ openssl_inc = os.path.join(openssl_path, "include")
+ if not os.path.exists(os.path.join(openssl_inc, "openssl\\ssl.h")):
+ print("can't find OpenSSL headers", file=sys.stderr)
+ sys.exit(1)
+ varvals["INCLUDEPATH"] = openssl_inc
+ openssl_lib = os.path.join(openssl_path, "lib")
+ openssl_lib_name = ""
+ openssl_lib_dll = ""
+ if os.path.exists(os.path.join(openssl_lib, "libeay32.lib")):
+ openssl_lib_name = "libeay32.lib"
+ openssl_lib_dll = "bin\\libeay32.dll"
+ elif os.path.exists(os.path.join(openssl_lib, "libeaycompat32.lib")):
+ openssl_lib_name = "libeaycompat32.lib"
+ openssl_lib_dll = "bin\\libeaycompat32.dll"
+ elif os.path.exists(os.path.join(openssl_lib, "libcrypto.lib")):
+ openssl_lib_name = "libcrypto.lib"
+ if platform == 32:
+ openssl_lib_dll = "bin\\libcrypto-1_1.dll"
+ else:
+ openssl_lib_dll = "bin\\libcrypto-1_1-x64.dll"
+
+ else:
+ print("can't find OpenSSL library", file=sys.stderr)
+ sys.exit(1)
+ openssl_dll = os.path.join(openssl_path,openssl_lib_dll)
+ varvals["LIBPATH"] = openssl_lib
+ varvals["LIBNAME"] = openssl_lib_name
+ varvals["DLLPATH"] = openssl_dll
+ if enable_debug:
+ debug_openssl_path = os.path.abspath(debug_openssl_path)
+ varvals["DEBUGDLLPATH"] = \
+ os.path.join(debug_openssl_path, openssl_lib_dll)
+ debug_openssl_inc = os.path.join(debug_openssl_path, "include")
+ if not os.path.exists(os.path.join(debug_openssl_inc,
+ "openssl\\ssl.h")):
+ print("can't find debug OpenSSL headers", file=sys.stderr)
+ sys.exit(1)
+ varvals["DEBUGINCPATH"] = debug_openssl_inc
+ debug_openssl_lib = os.path.join(debug_openssl_path, "lib")
+ if not os.path.exists(os.path.join(debug_openssl_lib,
+ openssl_lib_name)):
+ print("can't find debug OpenSSL library", file=sys.stderr)
+ sys.exit(1)
+ varvals["DEBUGLIBPATH"] = debug_openssl_lib
+ else:
+ varvals["DEBUGDLLPATH"] = varvals["DLLPATH"]
+ varvals["DEBUGINCPATH"] = varvals["INCLUDEPATH"]
+ varvals["DEBUGLIBPATH"] = varvals["LIBPATH"]
+
+ # OpenSSL support
+ if verbose:
+ print("checking OpenSSL")
+ system_libs = []
+ if os.path.exists(openssl_dll):
+ subprocess.call(["copy", openssl_dll, "."], shell=True)
+ else:
+ system_libs = ["user32.lib", "advapi32.lib", "gdi32.lib", "crypt32.lib", "ws2_32.lib"]
+ inc = openssl_inc
+ lib = os.path.join(openssl_lib, openssl_lib_name)
+ testfile = open("testossl.c", "w")
+ print('\
+#include <openssl/err.h>\n\
+int main() {\n\
+ ERR_clear_error();\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testossl.c", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testossl.exe"):
+ print("can't create .\\testossl.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testossl.exe") != 0:
+ print("OpenSSL test failed", file=sys.stderr)
+ sys.exit(1)
+
+ # OpenSSL version
+ if verbose:
+ print("checking OpenSSL version")
+ testfile = open("testosslv.c", "w")
+ print('\
+#include <openssl/ssl.h>\n\
+#include <openssl/opensslv.h>\n\
+int main() {\n\
+#ifndef OPENSSL_VERSION_NUMBER\n\
+ return -1;\n\
+#endif\n\
+#if OPENSSL_VERSION_NUMBER >= 0x010000000L\n\
+ return 0;\n\
+#else\n\
+ return 1;\n\
+#endif\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testosslv.c", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testosslv.exe"):
+ print("can't create .\\testosslv.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testosslv.exe") != 0:
+ print("OpenSLL version too old (1.0.0 or later required)", file=sys.stderr)
+ sys.exit(1)
+
+ # OpenSSL ECC support
+ if enable_ecc:
+ if verbose:
+ print("checking OpenSSL ECC support")
+ testfile = open("testecc.c", "w")
+ print('\
+#include <openssl/ecdsa.h>\n\
+#include <openssl/objects.h>\n\
+int main() {\n\
+ EC_KEY *ec256, *ec384, *ec521;\n\
+ ec256 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);\n\
+ ec384 = EC_KEY_new_by_curve_name(NID_secp384r1);\n\
+ ec521 = EC_KEY_new_by_curve_name(NID_secp521r1);\n\
+ if (ec256 == NULL || ec384 == NULL || ec521 == NULL)\n\
+ return 1;\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testecc.c", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testecc.exe"):
+ print("can't create .\\testecc.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testecc.exe") != 0:
+ print("can't find P256, P384, or P521: no ECC support", file=sys.stderr)
+ sys.exit(1)
+
+ # OpenSSL GOST support
+ if enable_gost:
+ if verbose:
+ print("checking OpenSSL GOST support")
+ testfile = open("testgost.c", "w")
+ print('\
+#include <openssl/conf.h>\n\
+#include <openssl/engine.h>\n\
+#include <openssl/crypto.h>\n\
+#include <openssl/opensslv.h>\n\
+int main() {\n\
+ ENGINE *eg;\n\
+ const EVP_MD* EVP_GOST_34_11;\n\
+ OpenSSL_add_all_algorithms();\n\
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)\n\
+ ENGINE_load_builtin_engines();\n\
+#else\n\
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN | OPENSSL_INIT_LOAD_CONFIG, NULL);\n\
+#endif\n\
+ eg = ENGINE_by_id("gost");\n\
+ if (eg == NULL)\n\
+ return 1;\n\
+ if (ENGINE_init(eg) <= 0)\n\
+ return 1;\n\
+ EVP_GOST_34_11 = ENGINE_get_digest(eg, NID_id_GostR3411_94);\n\
+ if (EVP_GOST_34_11 == NULL)\n\
+ return 1;\n\
+ if (ENGINE_register_pkey_asn1_meths(eg) <= 0)\n\
+ return 1;\n\
+ if (ENGINE_ctrl_cmd_string(eg, "CRYPT_PARAMS",\n\
+ "id-Gost28147-89-CryptoPro-A-ParamSet", 0) <= 0)\n\
+ return 1;\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testgost.c", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testgost.exe"):
+ print("can't create .\\testgost.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testgost.exe") != 0:
+ print("can't find GOST: no GOST support", file=sys.stderr)
+ sys.exit(1)
+
+ # OpenSSL EVP interface for AES key wrapping (aka RFC 3394)
+ if verbose:
+ print("checking OpenSSL EVP interface for AES key wrapping")
+ testfile = open("testrfc3394.c", "w")
+ print('\
+#include <openssl/evp.h>\n\
+int main() {\n\
+ EVP_aes_128_wrap();\n\
+ return 1;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testrfc3394.c", lib]
+ command.extend(system_libs)
+ subprocess.call(command)
+ if os.path.exists(".\\testrfc3394.exe"):
+ if verbose:
+ print("RFC 3394 is supported")
+ condvals["RFC3394"] = True
+ else:
+ if verbose:
+ print("can't compile OpenSSL RFC 3394")
+
+ # OpenSSL EVP interface for AES key wrap with pad (aka RFC 5649)
+ if verbose:
+ print("checking OpenSSL EVP interface for AES key wrapping with pad")
+ testfile = open("testrfc5649.c", "w")
+ print('\
+#include <openssl/evp.h>\n\
+int main() {\n\
+ EVP_aes_128_wrap_pad();\n\
+ return 1;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testrfc5649.c", lib]
+ command.extend(system_libs)
+ subprocess.call(command)
+ if os.path.exists(".\\testrfc5649.exe"):
+ if verbose:
+ print("RFC 5649 is supported")
+ condvals["RFC5649"] = True
+ else:
+ if verbose:
+ print("can't compile OpenSSL RFC 5649")
+
+ # no check for OpenSSL raw PSS support
+ condvals["RAWPSS"] = True
+ # no check for OpenSSL AES GCM
+ condvals["AESGCM"] = True
+
+ # configure CppUnit
+ if want_tests:
+ condvals["TESTS"] = True
+ cppunit_path = os.path.abspath(cppunit_path)
+ cppunit_inc = os.path.join(cppunit_path, "include")
+ if not os.path.exists(os.path.join(cppunit_inc, "cppunit\\Test.h")):
+ print("can't find CppUnit headers", file=sys.stderr)
+ sys.exit(1)
+ varvals["CUINCPATH"] = cppunit_inc
+ cppunit_lib = os.path.join(cppunit_path, "lib")
+ if not os.path.exists(os.path.join(cppunit_lib, "cppunit.lib")):
+ cppunit_lib = cppunit_path
+ if not os.path.exists(os.path.join(cppunit_lib, "cppunit.lib")):
+ print("can't find CppUnit library", file=sys.stderr)
+ sys.exit(1)
+ if enable_debug:
+ if not os.path.exists(os.path.join(cppunit_lib, "cppunitd.lib")):
+ print("can't find debug CppUnit library", file=sys.stderr)
+ sys.exit(1)
+ varvals["CULIBPATH"] = cppunit_lib
+
+ # misc
+ if enable_non_paged:
+ condvals["NONPAGE"] = True
+
+def kw(path):
+ """escape spaces"""
+ if re.search(r' ', path):
+ return '"' + path + '"'
+ else:
+ return path
+
+def setupfile(filename):
+ """setup files with condition stacks and variable expansions"""
+ cond = "@@@"
+ conds = []
+ passing = True
+ passes = []
+ filein = open(filename + ".in", "r")
+ fileout = open(filename, "w")
+
+ for line in filein:
+ line = line.rstrip("\r\n")
+ cif = re.match(r'@IF (.*)', line)
+ if cif:
+ conds.append(cond)
+ passes.append(passing)
+ cond = cif.group(1)
+ if condvals.get(cond):
+ # do nothing
+ pass
+ else:
+ passing = False
+ continue
+ celse = re.match(r'@ELSE (.*)', line)
+ if celse:
+ if cond != celse.group(1):
+ raise SyntaxError("@ELSE " + celse.group(1) +
+ " mismatch in " + filename)
+ if condvals.get(cond):
+ passing = False
+ else:
+ if len(passes) > 0:
+ passing = passes[-1]
+ else:
+ passing = True
+ continue
+ cend = re.match(r'@END (.*)', line)
+ if cend:
+ if cond != cend.group(1):
+ raise SyntaxError("@END " + cend.group(1) +
+ " mismatch in " + filename)
+ cond = conds.pop()
+ if len(passes) > 0:
+ passing = passes.pop()
+ else:
+ passing = True
+ continue
+ if not passing:
+ continue
+ while True:
+ vm = re.match(r'([^@]*)@([^@ ]*)@(.*)', line)
+ if vm:
+ if vm.group(2) in varnames:
+ if varvals.get(vm.group(2)):
+ val = kw(varvals[vm.group(2)])
+ else:
+ val = ""
+ line = vm.group(1) + val + vm.group(3)
+ continue
+ else:
+ raise SyntaxError("unknown control @" + vm.group(2) +
+ "@ in " + filename)
+ break
+ print(line, file=fileout)
+ if verbose:
+ print("Setting up " + filename)
+ filein.close()
+ fileout.close()
+
+def main(args):
+ """run it"""
+
+ # no arguments -> usage
+ if len(args) <= 1:
+ for line in usage:
+ print(line)
+ sys.exit(1)
+
+ parseargs(args[1:])
+
+ if want_help:
+ dohelp()
+ if want_clean:
+ doclean()
+ if want_unknown:
+ dounknown()
+ if not toolset:
+ dodetectvisualstudio()
+ if not toolset:
+ print("Build skipped. To build, this file needs to run from VS command prompt.")
+ sys.exit(1)
+
+ varvals["PLATFORMTOOLSET"] = toolset
+
+ # status before config
+ if verbose:
+ if enable_keep:
+ print("keep: enabled")
+ else:
+ print("keep: disabled")
+ if platform == 64:
+ print("64bit: enabled")
+ else:
+ print("64bit: disabled")
+ if enable_debug:
+ print("debug: enabled")
+ else:
+ print("debug: disabled")
+ if enable_ecc:
+ print("ecc: enabled")
+ else:
+ print("ecc: disabled")
+ if enable_gost:
+ print("gost: enabled")
+ else:
+ print("gost: disabled")
+ if enable_non_paged:
+ print("non-paged-memory: enabled")
+ else:
+ print("non-paged-memory: disabled")
+ print("crypto-backend: " + crypto_backend)
+ if crypto_backend == "botan":
+ print("botan-path: " + botan_path)
+ if enable_debug:
+ print("debug-botan-path: " + debug_botan_path)
+ else:
+ print("openssl-path: " + openssl_path)
+ if enable_debug:
+ print("debug-openssl-path: " + debug_openssl_path)
+ if want_tests:
+ print("cppunit-path: " + cppunit_path)
+ print("toolset: "+toolset)
+
+
+ doconfig()
+
+ # status after config
+ if verbose:
+ print("Configuration Status")
+ print("\tconditions:")
+ for name in condnames:
+ if condvals.get(name):
+ print("\t\t" + name + " is true")
+ else:
+ print("\t\t" + name + " is false")
+ print("\tsubstitutions:")
+ for name in varnames:
+ if varvals.get(name):
+ print("\t\t" + name + '-> "' + varvals[name] + '"')
+ print()
+
+ for filename in filelist:
+ setupfile(filename)
+
+ # clean test file
+ if not enable_keep:
+ docleantest()
+
+ print("Configured.")
+ sys.exit(0)
+
+main(sys.argv)
+
+# Notes: Unix configure.ac options
+# --enable-64bit supported
+# --enable-ecc supported
+# --enable-gost supported
+# --enable-non-paged-memory supported
+# --enable-visibility (enforced by DLLs)
+# --with-crypto-backend supported
+# --with-botan supported (Release and Debug)
+# --with-openssl supported (Release and Debug)
+# --with-migrate (useless as SoftHSMv1 is not supported)
+# --with-objectstore-backend-db (TODO)
+# --with-sqlite3 (useless until objectstore backend can be chosen)