diff options
-rwxr-xr-x | configure.pl | 34 | ||||
-rwxr-xr-x | configure.py | 6 | ||||
-rw-r--r-- | doc/examples/cryptobox.cpp | 50 | ||||
-rw-r--r-- | doc/log.txt | 9 | ||||
-rwxr-xr-x | doc/scripts/dist.sh | 6 | ||||
-rw-r--r-- | readme.txt | 2 | ||||
-rw-r--r-- | src/cryptobox/cryptobox.cpp | 146 | ||||
-rw-r--r-- | src/cryptobox/cryptobox.h | 42 | ||||
-rw-r--r-- | src/cryptobox/info.txt | 22 |
9 files changed, 293 insertions, 24 deletions
diff --git a/configure.pl b/configure.pl index 1d100fb6a..39948f489 100755 --- a/configure.pl +++ b/configure.pl @@ -15,9 +15,9 @@ my $MAJOR_VERSION = 1; my $MINOR_VERSION = 8; my $PATCH_VERSION = 6; -my $VERSION_SUFFIX = '-pre'; +my $VERSION_SUFFIX = ''; -my $SO_PATCH_VERSION = 6; +my $SO_PATCH_VERSION = 2; my $VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION$VERSION_SUFFIX"; my $SO_VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$SO_PATCH_VERSION$VERSION_SUFFIX"; @@ -40,10 +40,6 @@ my $TRACING = 0; ################################################## my $config = {}; -print STDERR "* WARNING\n" . - "* $0 is deprecated; consider trying configure.py instead\n" . - "* If it works, great. If not, file a bug and continue using $0\n*\n"; - main(); exit; @@ -60,12 +56,18 @@ sub exec_uname { return ''; } +sub deprecation_warning { + warning("$0 is deprecated; migration to ./configure.py strongly recommended"); +} + ################################################## # Main Driver # ################################################## sub main { my $base_dir = where_am_i(); + deprecation_warning(); + $$config{'uname'} = exec_uname(); $$config{'base-dir'} = $base_dir; @@ -201,6 +203,8 @@ sub main { generate_makefile($config); copy_include_files($config); + + deprecation_warning(); } sub where_am_i { @@ -508,8 +512,6 @@ sub module_runs_on { sub scan_modules { my ($config) = @_; - my %dep_mods = (); - foreach my $mod (sort keys %MODULES) { my %modinfo = %{ $MODULES{$mod} }; @@ -520,7 +522,8 @@ sub scan_modules { if($modinfo{'load_on'} eq 'auto' or ($modinfo{'load_on'} eq 'asm_ok' and $$config{'asm_ok'})) { - $$config{'modules'}{$mod} = 1; + my %maybe_load = (); + my $all_deps_found = 1; LINE: foreach (@{$modinfo{'requires'}}) { for my $req_mod (split(/\|/, $_)) { @@ -529,18 +532,19 @@ sub scan_modules { next if(defined($$config{'modules'}{$req_mod}) && $$config{'modules'}{$req_mod} < 0); next unless(module_runs_on($config, $MODULES{$req_mod}, $req_mod, 0)); - $dep_mods{$req_mod} = 1; + $maybe_load{$req_mod} = 1; next LINE; } + $all_deps_found = 0; } - next; + if($all_deps_found) { + foreach my $depmod (keys %maybe_load) + { $$config{'modules'}{$depmod} = 1; } + $$config{'modules'}{$mod} = 1; + } } } - - foreach my $mod (sort keys %dep_mods) { - $$config{'modules'}{$mod} = 1; - } } sub print_enabled_modules { diff --git a/configure.py b/configure.py index e4e6063e1..75e57f95e 100755 --- a/configure.py +++ b/configure.py @@ -38,8 +38,8 @@ class BuildConfigurationInformation(object): version_major = 1 version_minor = 8 version_patch = 6 - version_so_patch = 6 - version_suffix = '-pre' + version_so_patch = 2 + version_suffix = '' version_string = '%d.%d.%d%s' % ( version_major, version_minor, version_patch, version_suffix) @@ -1043,7 +1043,7 @@ def main(argv = None): if options.compiler == 'gcc': def is_64bit_arch(arch): - if arch.endswith('64') or arch in ['alpha', 's930x']: + if arch.endswith('64') or arch in ['alpha', 's390x']: return True return False diff --git a/doc/examples/cryptobox.cpp b/doc/examples/cryptobox.cpp new file mode 100644 index 000000000..0a769b0cd --- /dev/null +++ b/doc/examples/cryptobox.cpp @@ -0,0 +1,50 @@ +/* +* Cryptobox example +*/ +#include <botan/botan.h> +#include <botan/cryptobox.h> +#include <fstream> +#include <iostream> +#include <vector> + +using namespace Botan; + +int main(int argc, char* argv[]) + { + LibraryInitializer init; + + AutoSeeded_RNG rng; + + if(argc != 3) + { + std::cout << "Usage: cryptobox pass filename\n"; + return 1; + } + + std::string pass = argv[1]; + std::string filename = argv[2]; + + std::ifstream input(filename.c_str()); + + std::vector<byte> file_contents; + while(input.good()) + { + byte filebuf[4096] = { 0 }; + input.read((char*)filebuf, sizeof(filebuf)); + size_t got = input.gcount(); + + file_contents.insert(file_contents.end(), filebuf, filebuf+got); + } + + std::string ciphertext = CryptoBox::encrypt(&file_contents[0], + file_contents.size(), + pass, rng); + + std::cout << ciphertext; + + /* + std::cout << CryptoBox::decrypt((const byte*)&ciphertext[0], + ciphertext.length(), + pass); + */ + } diff --git a/doc/log.txt b/doc/log.txt index 734c8c99c..57baaa3c9 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,9 +1,14 @@ -* 1.8.6-pre, 2009-??-?? +* 1.8.6, 2009-08-13 + - Add Cryptobox, a set of simple password-based encryption routines - Only read world-readable files when walking /proc for entropy + - Fix building with TR1 disabled + - Fix x86 bswap support for Visual C++ + - Fixes for compilation under Sun C++ - Add support for Dragonfly BSD (contributed by Patrick Georgi) - Add support for the Open64 C++ compiler - - Minor changes to license to be equivalent to the FreeBSD/NetBSD license + - Build fixes for MIPS systems running Linux + - Minor changes to license, now equivalent to the FreeBSD/NetBSD license * 1.8.5, 2009-07-23 - Change configure.py to work on stock Python 2.4 diff --git a/doc/scripts/dist.sh b/doc/scripts/dist.sh index d66066173..0062d43bf 100755 --- a/doc/scripts/dist.sh +++ b/doc/scripts/dist.sh @@ -5,8 +5,8 @@ SELECTOR=h:net.randombit.botan KEY_ID=EFBADFBC -MTN_DB=~/var/mtn/botan.mtn -WEB_DIR=~/var/www +MTN_DB=/storage/mtn/botan.mtn +WEB_DIR=~/projects/www DIST_DIR=~/Botan-dist # You shouldn't have to change anything after this @@ -15,7 +15,7 @@ cd $DIST_DIR mtn -d $MTN_DB checkout -r $SELECTOR Botan -VERSION=$(Botan/configure.pl --version | sed 's/Botan //') +VERSION=$(Botan/configure.py --version) mv Botan Botan-$VERSION diff --git a/readme.txt b/readme.txt index 102999cce..dfa258b83 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -Botan 1.8.6-pre 2009-??-?? +Botan 1.8.6 2009-08-13 Botan is a C++ class library for performing a wide variety of cryptographic operations. diff --git a/src/cryptobox/cryptobox.cpp b/src/cryptobox/cryptobox.cpp new file mode 100644 index 000000000..c27bbaffa --- /dev/null +++ b/src/cryptobox/cryptobox.cpp @@ -0,0 +1,146 @@ +/* +* Cryptobox Message Routines +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/cryptobox.h> +#include <botan/filters.h> +#include <botan/pipe.h> +#include <botan/serpent.h> +#include <botan/sha2_64.h> +#include <botan/ctr.h> +#include <botan/hmac.h> +#include <botan/pbkdf2.h> +#include <botan/pem.h> +#include <botan/loadstor.h> +#include <botan/mem_ops.h> + +namespace Botan { + +namespace CryptoBox { + +namespace { + +/* +First 24 bits of SHA-256("Botan Cryptobox"), followed by 8 0 bits +for later use as flags, etc if needed +*/ +const u32bit CRYPTOBOX_VERSION_CODE = 0xEFC22400; + +const u32bit VERSION_CODE_LEN = 4; +const u32bit CIPHER_KEY_LEN = 32; +const u32bit CIPHER_IV_LEN = 16; +const u32bit MAC_KEY_LEN = 32; +const u32bit MAC_OUTPUT_LEN = 20; +const u32bit PBKDF_SALT_LEN = 10; +const u32bit PBKDF_ITERATIONS = 8 * 1024; + +const u32bit PBKDF_OUTPUT_LEN = CIPHER_KEY_LEN + CIPHER_IV_LEN + MAC_KEY_LEN; + +} + +std::string encrypt(const byte input[], u32bit input_len, + const std::string& passphrase, + RandomNumberGenerator& rng) + { + SecureVector<byte> pbkdf_salt(PBKDF_SALT_LEN); + rng.randomize(pbkdf_salt.begin(), pbkdf_salt.size()); + + PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512)); + pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size()); + pbkdf.set_iterations(PBKDF_ITERATIONS); + + OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase); + + SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN); + SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN); + InitializationVector iv(mk.begin() + CIPHER_KEY_LEN + MAC_KEY_LEN, + CIPHER_IV_LEN); + + Pipe pipe(new CTR_BE(new Serpent, cipher_key, iv), + new Fork( + 0, + new MAC_Filter(new HMAC(new SHA_512), + mac_key, MAC_OUTPUT_LEN))); + + pipe.process_msg(input, input_len); + + /* + Output format is: + version # (4 bytes) + salt (10 bytes) + mac (20 bytes) + ciphertext + */ + u32bit ciphertext_len = pipe.remaining(0); + + SecureVector<byte> out_buf; + + for(u32bit i = 0; i != VERSION_CODE_LEN; ++i) + out_buf.append(get_byte(i, CRYPTOBOX_VERSION_CODE)); + + out_buf.append(pbkdf_salt.begin(), pbkdf_salt.size()); + + out_buf.grow_to(out_buf.size() + MAC_OUTPUT_LEN + ciphertext_len); + pipe.read(out_buf + VERSION_CODE_LEN + PBKDF_SALT_LEN, MAC_OUTPUT_LEN, 1); + pipe.read(out_buf + VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN, + ciphertext_len, 0); + + return PEM_Code::encode(out_buf.begin(), out_buf.size(), + "BOTAN CRYPTOBOX MESSAGE"); + } + +std::string decrypt(const byte input[], u32bit input_len, + const std::string& passphrase) + { + DataSource_Memory input_src(input, input_len); + SecureVector<byte> ciphertext = + PEM_Code::decode_check_label(input_src, + "BOTAN CRYPTOBOX MESSAGE"); + + if(ciphertext.size() < (VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN)) + throw Decoding_Error("Invalid CryptoBox input"); + + for(u32bit i = 0; i != VERSION_CODE_LEN; ++i) + if(ciphertext[i] != get_byte(i, CRYPTOBOX_VERSION_CODE)) + throw Decoding_Error("Bad CryptoBox version"); + + SecureVector<byte> pbkdf_salt(ciphertext + VERSION_CODE_LEN, PBKDF_SALT_LEN); + + PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512)); + pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size()); + pbkdf.set_iterations(PBKDF_ITERATIONS); + + OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase); + + SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN); + SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN); + InitializationVector iv(mk.begin() + CIPHER_KEY_LEN + MAC_KEY_LEN, + CIPHER_IV_LEN); + + Pipe pipe(new Fork( + new CTR_BE(new Serpent, cipher_key, iv), + new MAC_Filter(new HMAC(new SHA_512), + mac_key, MAC_OUTPUT_LEN))); + + const u32bit ciphertext_offset = + VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN; + + pipe.process_msg(ciphertext + ciphertext_offset, + ciphertext.size() - ciphertext_offset); + + byte computed_mac[MAC_OUTPUT_LEN]; + pipe.read(computed_mac, MAC_OUTPUT_LEN, 1); + + if(!same_mem(computed_mac, ciphertext + VERSION_CODE_LEN + PBKDF_SALT_LEN, + MAC_OUTPUT_LEN)) + throw Integrity_Failure("CryptoBox integrity failure"); + + return pipe.read_all_as_string(0); + } + +} + +} diff --git a/src/cryptobox/cryptobox.h b/src/cryptobox/cryptobox.h new file mode 100644 index 000000000..a30cb244a --- /dev/null +++ b/src/cryptobox/cryptobox.h @@ -0,0 +1,42 @@ +/* +* Cryptobox Message Routines +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_CRYPTOBOX_H__ +#define BOTAN_CRYPTOBOX_H__ + +#include <string> +#include <botan/rng.h> + +namespace Botan { + +namespace CryptoBox { + +/** +* Encrypt a message +* @param input the input data +* @param input_len the length of input in bytes +* @param passphrase the passphrase used to encrypt the message +* @param rng a ref to a random number generator, such as AutoSeeded_RNG +*/ +BOTAN_DLL std::string encrypt(const byte input[], u32bit input_len, + const std::string& passphrase, + RandomNumberGenerator& rng); + +/** +* Decrypt a message encrypted with CryptoBox::encrypt +* @param input the input data +* @param input_len the length of input in bytes +* @param passphrase the passphrase used to encrypt the message +*/ +BOTAN_DLL std::string decrypt(const byte input[], u32bit input_len, + const std::string& passphrase); + +} + +} + +#endif diff --git a/src/cryptobox/info.txt b/src/cryptobox/info.txt new file mode 100644 index 000000000..b9b98060f --- /dev/null +++ b/src/cryptobox/info.txt @@ -0,0 +1,22 @@ +realname "Crypto Box" + +load_on auto + +define CRYPTO_BOX + +<add> +cryptobox.h +cryptobox.cpp +</add> + +<requires> +filters +ctr +hmac +rng +serpent +sha2 +base64 +pbkdf2 +pem +</requires> |