aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-03-06 06:31:02 -0500
committerJack Lloyd <[email protected]>2016-03-06 06:31:02 -0500
commitdd40d492fc8c76954909445e1af6e32a3e03600e (patch)
treef8b041df0d69011ac90ae8a72c047375a5e4a8de
parent7827c50cbddec094412745d877dcf3ea118ad4d7 (diff)
parent028a5126095e4eecd4dd213218f241a990fcbddd (diff)
Merge GH #446 add --module-policy option
-rwxr-xr-xconfigure.py145
-rw-r--r--src/build-data/policy/bsi.txt156
-rw-r--r--src/build-data/policy/sane.txt120
-rw-r--r--src/lib/mac/mac.h2
-rw-r--r--src/lib/pubkey/dlies/dlies.cpp2
-rw-r--r--src/tests/test_dlies.cpp21
-rw-r--r--src/tests/test_fuzzer.cpp6
7 files changed, 383 insertions, 69 deletions
diff --git a/configure.py b/configure.py
index 529d3efe1..4739a8937 100755
--- a/configure.py
+++ b/configure.py
@@ -359,6 +359,10 @@ def process_command_line(args):
mods_group = optparse.OptionGroup(parser, 'Module selection')
+ mods_group.add_option('--module-policy', dest='module_policy',
+ help="module policy file (see src/build-data/policy)",
+ metavar='POL', default=None)
+
mods_group.add_option('--enable-modules', dest='enabled_modules',
metavar='MODS', action='append',
help='enable specific modules')
@@ -715,6 +719,11 @@ class ModuleInfo(object):
return 0
return 1
+class ModulePolicyInfo(object):
+ def __init__(self, infofile):
+ lex_me_harder(infofile, self,
+ ['required', 'if_available', 'prohibited'], {})
+
class ArchInfo(object):
def __init__(self, infofile):
lex_me_harder(infofile, self,
@@ -1398,7 +1407,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo):
"""
Determine which modules to load based on options, target, etc
"""
-def choose_modules_to_use(modules, archinfo, ccinfo, options):
+def choose_modules_to_use(modules, module_policy, archinfo, ccinfo, options):
for mod in modules.values():
mod.dependencies_exist(modules)
@@ -1410,6 +1419,18 @@ def choose_modules_to_use(modules, archinfo, ccinfo, options):
def cannot_use_because(mod, reason):
not_using_because.setdefault(reason, []).append(mod)
+ def check_usable(module, modname, options):
+ if not module.compatible_os(options.os):
+ cannot_use_because(modname, 'incompatible OS')
+ return False
+ elif not module.compatible_compiler(ccinfo, archinfo.basename):
+ cannot_use_because(modname, 'incompatible compiler')
+ return False
+ elif not module.compatible_cpu(archinfo, options):
+ cannot_use_because(modname, 'incompatible CPU')
+ return False
+ return True
+
for modname in options.enabled_modules:
if modname not in modules:
logging.error("Module not found: %s" % (modname))
@@ -1419,19 +1440,35 @@ def choose_modules_to_use(modules, archinfo, ccinfo, options):
logging.warning("Disabled module not found: %s" % (modname))
for (modname, module) in modules.items():
+ usable = check_usable(module, modname, options)
+
+ if module_policy is not None:
+
+ if modname in module_policy.required:
+ if not usable:
+ logging.error('Module policy requires module %s not usable on this platform' % (modname))
+ elif modname in options.disabled_modules:
+ logging.error('Module %s was disabled but is required by policy' % (modname))
+ to_load.append(modname)
+ continue
+ elif modname in module_policy.if_available:
+ if modname in options.disabled_modules:
+ cannot_use_because(modname, 'disabled by user')
+ elif usable:
+ logging.debug('Enabling optional module %s' % (modname))
+ to_load.append(modname)
+ continue
+ elif modname in module_policy.prohibited:
+ if modname in options.enabled_modules:
+ logging.error('Module %s was requested but is prohibited by policy' % (modname))
+ cannot_use_because(modname, 'prohibited by module policy')
+ continue
+
if modname in options.disabled_modules:
cannot_use_because(modname, 'disabled by user')
elif modname in options.enabled_modules:
to_load.append(modname) # trust the user
-
- elif not module.compatible_os(options.os):
- cannot_use_because(modname, 'incompatible OS')
- elif not module.compatible_compiler(ccinfo, archinfo.basename):
- cannot_use_because(modname, 'incompatible compiler')
- elif not module.compatible_cpu(archinfo, options):
- cannot_use_because(modname, 'incompatible CPU')
-
- else:
+ elif usable:
if module.load_on == 'never':
cannot_use_because(modname, 'disabled as buggy')
elif module.load_on == 'request':
@@ -1451,7 +1488,7 @@ def choose_modules_to_use(modules, archinfo, ccinfo, options):
to_load.append(modname)
elif module.load_on == 'auto':
- if options.no_autoload:
+ if options.no_autoload or module_policy is not None:
maybe_dep.append(modname)
else:
to_load.append(modname)
@@ -1487,7 +1524,7 @@ def choose_modules_to_use(modules, archinfo, ccinfo, options):
cannot_use_because(modname, 'dependency failure')
for not_a_dep in maybe_dep:
- cannot_use_because(not_a_dep, 'loaded only if needed by dependency')
+ cannot_use_because(not_a_dep, 'only used if needed or requested')
for reason in sorted(not_using_because.keys()):
disabled_mods = sorted(set([mod for mod in not_using_because[reason]]))
@@ -1514,52 +1551,6 @@ def choose_modules_to_use(modules, archinfo, ccinfo, options):
return to_load
"""
-Load the info files about modules, targets, etc
-"""
-def load_info_files(options):
-
- def find_files_named(desired_name, in_path):
- for (dirpath, dirnames, filenames) in os.walk(in_path):
- if desired_name in filenames:
- yield os.path.join(dirpath, desired_name)
-
- modules = dict([(mod.basename, mod) for mod in
- [ModuleInfo(info) for info in
- find_files_named('info.txt', options.lib_dir)]])
-
- def list_files_in_build_data(subdir):
- for (dirpath, dirnames, filenames) in \
- os.walk(os.path.join(options.build_data, subdir)):
- for filename in filenames:
- if filename.endswith('.txt'):
- yield os.path.join(dirpath, filename)
-
- def form_name(filepath):
- return os.path.basename(filepath).replace('.txt', '')
-
- archinfo = dict([(form_name(info), ArchInfo(info))
- for info in list_files_in_build_data('arch')])
-
- osinfo = dict([(form_name(info), OsInfo(info))
- for info in list_files_in_build_data('os')])
-
- ccinfo = dict([(form_name(info), CompilerInfo(info))
- for info in list_files_in_build_data('cc')])
-
- def info_file_load_report(type, num):
- if num > 0:
- logging.debug('Loaded %d %s info files' % (num, type))
- else:
- logging.warning('Failed to load any %s info files' % (type))
-
- info_file_load_report('CPU', len(archinfo));
- info_file_load_report('OS', len(osinfo))
- info_file_load_report('compiler', len(ccinfo))
-
- return (modules, archinfo, ccinfo, osinfo)
-
-
-"""
Choose the link method based on system availablity and user request
"""
def choose_link_method(options):
@@ -1860,7 +1851,35 @@ def main(argv = None):
options.build_data = os.path.join(options.src_dir, 'build-data')
options.makefile_dir = os.path.join(options.build_data, 'makefile')
- (modules, info_arch, info_cc, info_os) = load_info_files(options)
+ def find_files_named(desired_name, in_path):
+ for (dirpath, dirnames, filenames) in os.walk(in_path):
+ if desired_name in filenames:
+ yield os.path.join(dirpath, desired_name)
+
+ modules = dict([(mod.basename, mod) for mod in
+ [ModuleInfo(info) for info in
+ find_files_named('info.txt', options.lib_dir)]])
+
+ def load_build_data(descr, subdir, class_t):
+ info = {}
+
+ subdir = os.path.join(options.build_data, subdir)
+
+ for fsname in os.listdir(subdir):
+ if fsname.endswith('.txt'):
+ info[fsname.replace('.txt', '')] = class_t(os.path.join(subdir, fsname))
+ if len(info) == 0:
+ logging.warning('Failed to load any %s files' % (descr))
+ else:
+ logging.debug('Loaded %d %s files' % (len(info), descr))
+
+ return info
+
+ info_arch = load_build_data('CPU info', 'arch', ArchInfo)
+ info_os = load_build_data('OS info', 'os', OsInfo)
+ info_cc = load_build_data('compiler info', 'cc', CompilerInfo)
+
+ module_policies = load_build_data('module policy', 'policy', ModulePolicyInfo)
if options.list_modules:
for k in sorted(modules.keys()):
@@ -1936,6 +1955,12 @@ def main(argv = None):
cc = info_cc[options.compiler]
arch = info_arch[options.arch]
osinfo = info_os[options.os]
+ module_policy = None
+
+ if options.module_policy != None:
+ if options.module_policy not in module_policies:
+ logging.error("Unknown module set %s", options.module_policy)
+ module_policy = module_policies[options.module_policy]
if options.with_visibility is None:
options.with_visibility = True
@@ -1952,7 +1977,7 @@ def main(argv = None):
raise Exception('Botan does not support building as shared library on the target os. '
'Build static using --disable-shared.')
- loaded_mods = choose_modules_to_use(modules, arch, cc, options)
+ loaded_mods = choose_modules_to_use(modules, module_policy, arch, cc, options)
for m in loaded_mods:
if modules[m].load_on == 'vendor':
diff --git a/src/build-data/policy/bsi.txt b/src/build-data/policy/bsi.txt
new file mode 100644
index 000000000..9ab68a921
--- /dev/null
+++ b/src/build-data/policy/bsi.txt
@@ -0,0 +1,156 @@
+<required>
+# block
+aes
+
+# modes
+gcm
+cbc
+mode_pad
+
+# stream
+ctr
+
+# hash
+sha2_32
+sha2_64
+keccak
+
+# mac
+cmac
+hmac
+
+# pk_pad
+eme_oaep
+emsa_pssr
+
+# pubkey
+dlies
+dh
+rsa
+dsa
+ecdsa
+ecdh
+
+# rng
+auto_rng
+hmac_rng
+hmac_drbg
+</required>
+
+<if_available>
+# block
+aes_ni
+aes_ssse3
+
+# modes
+clmul
+
+# entropy sources
+beos_stats
+darwin_secrandom
+egd
+proc_walk
+unix_procs
+rdrand
+rdseed
+hres_timer
+dev_random
+system_rng
+cryptoapi_rng
+win32_stats
+
+# utils
+locking_allocator
+simd_altivec
+simd_scalar
+simd_sse2
+</if_available>
+
+<prohibited>
+# block
+blowfish
+camellia
+cascade
+cast
+gost_28147
+idea
+idea_sse2
+kasumi
+lion
+mars
+misty1
+noekeon
+noekeon_simd
+rc2
+rc5
+rc6
+safer
+seed
+serpent
+serpent_simd
+tea
+threefish
+threefish_avx2
+twofish
+xtea
+xtea_simd
+
+# modes
+ccm
+chacha20poly1305
+eax
+ocb
+siv
+cfb
+ecb
+
+# stream
+chacha
+ofb
+rc4
+salsa20
+
+# pubkey
+curve25519
+elgamal
+gost_3410
+mce
+mceies
+nr
+rw
+
+# pk_pad
+#eme_pkcs1 // needed for tls
+eme_raw
+#emsa_pkcs1 // needed for tls
+emsa_raw
+emsa_x931
+emsa1
+emsa1_bsi
+
+# hash
+blake2
+comb4p
+gost_3411
+has160
+md2
+md4
+#md5 // needed for tls
+rmd128
+rmd160
+#sha1 // needed for tls
+#sha1_sse2 // needed for tls
+skein
+tiger
+whirlpool
+
+# mac
+cbc_mac
+poly1305
+siphash
+x919_mac
+
+# rng
+x931_rng
+
+</prohibited>
diff --git a/src/build-data/policy/sane.txt b/src/build-data/policy/sane.txt
new file mode 100644
index 000000000..3482296d6
--- /dev/null
+++ b/src/build-data/policy/sane.txt
@@ -0,0 +1,120 @@
+<required>
+aes
+serpent
+threefish
+chacha
+
+sha2_32
+sha2_64
+blake2
+skein
+keccak
+
+gcm
+ocb
+chacha20poly1305
+
+kdf2
+hkdf
+cmac
+hmac
+poly1305
+siphash
+
+pbkdf2
+
+# required for private key encryption
+pbes2
+
+# required for TLS
+prf_tls
+
+curve25519
+ecdh
+ecdsa
+rsa
+
+eme_oaep
+emsa_pssr
+emsa1
+
+auto_rng
+hmac_rng
+
+ffi
+</required>
+
+<prohibited>
+cast
+des
+gost_28147
+idea
+idea_sse2
+kasumi
+lion
+mars
+misty1
+rc2
+rc4
+rc5
+rc6
+safer
+seed
+tea
+xtea
+xtea_simd
+
+cbc_mac
+x919_mac
+
+# MD5 and SHA1 are broken but not prohibited. They are widely in use
+# in non-crypto contexts and are required by TLS currently
+md2
+md4
+rmd128
+has160
+gost_3411
+
+cfb
+ecb
+ofb
+
+elgamal
+rw
+nr
+gost_3410
+
+emsa_x931
+pbkdf1
+prf_x942
+x931_rng
+
+passhash9
+cryptobox
+unix_procs
+</prohibited>
+
+<if_available>
+clmul
+locking_allocator
+
+sha1_sse2
+aes_ni
+aes_ssse3
+noekeon_simd
+serpent_simd
+threefish_avx2
+
+simd_scalar
+simd_sse2
+simd_altivec
+
+# entropy sources
+rdrand
+rdseed
+hres_timer
+dev_random
+system_rng
+cryptoapi_rng
+win32_stats
+</if_available>
diff --git a/src/lib/mac/mac.h b/src/lib/mac/mac.h
index 90ef4db15..fe3388f3b 100644
--- a/src/lib/mac/mac.h
+++ b/src/lib/mac/mac.h
@@ -53,6 +53,8 @@ class BOTAN_DLL MessageAuthenticationCode : public Buffered_Computation,
virtual MessageAuthenticationCode* clone() const = 0;
};
+typedef MessageAuthenticationCode MAC;
+
}
#endif
diff --git a/src/lib/pubkey/dlies/dlies.cpp b/src/lib/pubkey/dlies/dlies.cpp
index 86cd51e19..ba890ac3d 100644
--- a/src/lib/pubkey/dlies/dlies.cpp
+++ b/src/lib/pubkey/dlies/dlies.cpp
@@ -21,6 +21,8 @@ DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& key,
m_mac(mac_obj),
m_mac_keylen(mac_kl)
{
+ BOTAN_ASSERT_NONNULL(kdf_obj);
+ BOTAN_ASSERT_NONNULL(mac_obj);
m_my_key = key.public_value();
}
diff --git a/src/tests/test_dlies.cpp b/src/tests/test_dlies.cpp
index 1c7327ab4..ba8142dcb 100644
--- a/src/tests/test_dlies.cpp
+++ b/src/tests/test_dlies.cpp
@@ -42,20 +42,29 @@ class DLIES_KAT_Tests : public Text_Based_Test
Botan::DH_PrivateKey from(Test::rng(), domain, x1);
Botan::DH_PrivateKey to(Test::rng(), domain, x2);
- const std::string kdf = "KDF2(SHA-1)";
- const std::string mac = "HMAC(SHA-1)";
+ const std::string kdf_algo = "KDF2(SHA-1)";
+ const std::string mac_algo = "HMAC(SHA-1)";
const size_t mac_key_len = 16;
Test::Result result("DLIES");
+ std::unique_ptr<Botan::KDF> kdf(Botan::KDF::create(kdf_algo));
+ std::unique_ptr<Botan::MAC> mac(Botan::MAC::create(mac_algo));
+
+ if(!kdf || !mac)
+ {
+ result.test_note("Skipping due to missing KDF or MAC algo");
+ return result;
+ }
+
Botan::DLIES_Encryptor encryptor(from,
- Botan::KDF::create(kdf).release(),
- Botan::MessageAuthenticationCode::create(mac).release(),
+ kdf->clone(),
+ mac->clone(),
mac_key_len);
Botan::DLIES_Decryptor decryptor(to,
- Botan::KDF::create(kdf).release(),
- Botan::MessageAuthenticationCode::create(mac).release(),
+ kdf.release(),
+ mac.release(),
mac_key_len);
encryptor.set_other_key(to.public_value());
diff --git a/src/tests/test_fuzzer.cpp b/src/tests/test_fuzzer.cpp
index 18516a68c..2be8e7c08 100644
--- a/src/tests/test_fuzzer.cpp
+++ b/src/tests/test_fuzzer.cpp
@@ -6,12 +6,12 @@
#include "tests.h"
#include <chrono>
+#include <botan/internal/filesystem.h>
#if defined(BOTAN_HAS_X509_CERTIFICATES)
#include <botan/x509cert.h>
#include <botan/x509_crl.h>
#include <botan/base64.h>
- #include <botan/internal/filesystem.h>
#endif
#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
@@ -61,8 +61,8 @@ class Fuzzer_Input_Tests : public Test
{
try
{
- std::unique_ptr<Botan::Private_Key> key(Botan::PKCS8::load_key(vec_file, Test::rng()));
- Botan::X509_Certificate cert(vec_file);
+ std::unique_ptr<Botan::Private_Key> key(
+ Botan::PKCS8::load_key(vec_file, Test::rng()));
}
catch(std::exception&) {}