diff --git a/doc/crypt.tex b/doc/crypt.tex index fc2f47b74..34ee32e50 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -7002,7 +7002,7 @@ \subsection{PKCS \#5} The OpenSSL project implemented an extension to Algorithm One that allows for arbitrary keylengths; we have a compatible implementation described below. -\subsection{Algorithm One} +\subsubsection{Algorithm One} Algorithm One accepts as input a password, an 8--byte salt, and an iteration counter. The iteration counter is meant to act as delay for people trying to brute force guess the password. The higher the iteration counter the longer the delay. This algorithm also requires a hash algorithm and produces an output no longer than the output of the hash. @@ -7035,7 +7035,7 @@ \subsection{Algorithm One} unsigned long *outlen) \end{alltt} As above, but we generate as many bytes as requested in outlen per the OpenSSL extension to Algorithm One. If you are trying to be compatible with OpenSSL's EVP\_BytesToKey() or the "openssl enc" command line (or variants such as perl's Crypt::CBC), then use this function with MD5 as your hash (ick!) and iteration\_count=1 (double-ick!!). -\subsection{Algorithm Two} +\subsubsection{Algorithm Two} Algorithm Two is the recommended algorithm for this task. It allows variable length salts, and can produce outputs larger than the hash functions output. As such, it can easily be used to derive session keys for ciphers and MACs as well initialization vectors as required @@ -7091,6 +7091,35 @@ \subsection{Algorithm Two} } \end{verbatim} + +\subsection{bcrypt} +\index{bcrypt} + +bcrypt is a password hashing function, similar to PKCS \#5, but it is based on the blowfish symmetric cipher. +It is widely used in e.g. OpenBSD as default password hash algorithm, or in encrypted OpenSSH key files. + +This implementation provides the PBKDF version as used in OpenSSH key files. + +The OpenBSD implementation is fixed to SHA512 as hashing algorithm, but this generalized implementation works with any hashing algorithm. + +To hash a password with the bcrypt PBKDF algorithm, the following API function is provided. + +\index{bcrypt()} +\begin{alltt} +int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, + const unsigned char *salt, unsigned long salt_len, + unsigned int rounds, int hash_idx, + unsigned char *out, unsigned long *outlen); +\end{alltt} + +The \textit{secret} parameter is the secret of length \textit{secret\_len} (most of the time a utf-8 encoded user password). +The \textit{salt} parameter is a pointer to the array of octets of length \textit{salt\_len} containing the salt. +The \textit{rounds} parameter defines the number of iterations of the expensive key setup that shall be executed. +The \textit{hash\_idx} parameter defines the hash algorithm that shall be used. +The \textit{out} parameter shall be a pointer to a buffer of at least 32 octets, +where \textit{outlen} contains the available buffer size on input and the written size after the invocation. + + \mysection{PKCS \#8} \index{PKCS \#8} @@ -7127,6 +7156,7 @@ \subsection{Algorithm Two} The PKCS \#8 import has no direct API endpoints, but it is available through Public Key Algorithm-specific \textit{pkaX\_import\_pkcs8()} functions. + \mysection{Key Derviation Functions} \subsection{HKDF} \index{HKDF} diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index 3fb38c5fe..92a3abc62 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -1415,6 +1415,14 @@ > + + + + diff --git a/makefile.mingw b/makefile.mingw index 7fbfc71a0..a9a6ff21f 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -93,20 +93,20 @@ src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math src/math/radix_to_bin.o src/math/rand_bn.o src/math/rand_prime.o src/math/tfm_desc.o src/misc/adler32.o \ src/misc/base16/base16_decode.o src/misc/base16/base16_encode.o src/misc/base32/base32_decode.o \ src/misc/base32/base32_encode.o src/misc/base64/base64_decode.o src/misc/base64/base64_encode.o \ -src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o src/misc/crc32.o \ -src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o src/misc/crypt/crypt_cipher_descriptor.o \ -src/misc/crypt/crypt_cipher_is_valid.o src/misc/crypt/crypt_constants.o \ -src/misc/crypt/crypt_find_cipher.o src/misc/crypt/crypt_find_cipher_any.o \ -src/misc/crypt/crypt_find_cipher_id.o src/misc/crypt/crypt_find_hash.o \ -src/misc/crypt/crypt_find_hash_any.o src/misc/crypt/crypt_find_hash_id.o \ -src/misc/crypt/crypt_find_hash_oid.o src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o \ -src/misc/crypt/crypt_hash_descriptor.o src/misc/crypt/crypt_hash_is_valid.o \ -src/misc/crypt/crypt_inits.o src/misc/crypt/crypt_ltc_mp_descriptor.o \ -src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \ -src/misc/crypt/crypt_prng_rng_descriptor.o src/misc/crypt/crypt_register_all_ciphers.o \ -src/misc/crypt/crypt_register_all_hashes.o src/misc/crypt/crypt_register_all_prngs.o \ -src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \ -src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ +src/misc/bcrypt/bcrypt.o src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o \ +src/misc/crc32.o src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o \ +src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \ +src/misc/crypt/crypt_constants.o src/misc/crypt/crypt_find_cipher.o \ +src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \ +src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \ +src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \ +src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \ +src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_inits.o \ +src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \ +src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \ +src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \ +src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ +src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ @@ -223,12 +223,13 @@ src/stream/sosemanuk/sosemanuk.o src/stream/sosemanuk/sosemanuk_memory.o \ src/stream/sosemanuk/sosemanuk_test.o #List of test objects to compile -TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/cipher_hash_test.o \ -tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o \ -tests/file_test.o tests/mac_test.o tests/misc_test.o tests/modes_test.o tests/mpi_test.o \ -tests/multi_test.o tests/no_prng.o tests/padding_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ -tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ -tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ +tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ +tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ +tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_prng.o tests/padding_test.o \ +tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o \ +tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o \ +tests/store_test.o tests/test.o tests/x25519_test.o #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile.msvc b/makefile.msvc index 1661e6ec1..7bd9d9d6d 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -86,20 +86,20 @@ src/math/fp/ltc_ecc_fp_mulmod.obj src/math/gmp_desc.obj src/math/ltm_desc.obj sr src/math/radix_to_bin.obj src/math/rand_bn.obj src/math/rand_prime.obj src/math/tfm_desc.obj src/misc/adler32.obj \ src/misc/base16/base16_decode.obj src/misc/base16/base16_encode.obj src/misc/base32/base32_decode.obj \ src/misc/base32/base32_encode.obj src/misc/base64/base64_decode.obj src/misc/base64/base64_encode.obj \ -src/misc/burn_stack.obj src/misc/compare_testvector.obj src/misc/copy_or_zeromem.obj src/misc/crc32.obj \ -src/misc/crypt/crypt.obj src/misc/crypt/crypt_argchk.obj src/misc/crypt/crypt_cipher_descriptor.obj \ -src/misc/crypt/crypt_cipher_is_valid.obj src/misc/crypt/crypt_constants.obj \ -src/misc/crypt/crypt_find_cipher.obj src/misc/crypt/crypt_find_cipher_any.obj \ -src/misc/crypt/crypt_find_cipher_id.obj src/misc/crypt/crypt_find_hash.obj \ -src/misc/crypt/crypt_find_hash_any.obj src/misc/crypt/crypt_find_hash_id.obj \ -src/misc/crypt/crypt_find_hash_oid.obj src/misc/crypt/crypt_find_prng.obj src/misc/crypt/crypt_fsa.obj \ -src/misc/crypt/crypt_hash_descriptor.obj src/misc/crypt/crypt_hash_is_valid.obj \ -src/misc/crypt/crypt_inits.obj src/misc/crypt/crypt_ltc_mp_descriptor.obj \ -src/misc/crypt/crypt_prng_descriptor.obj src/misc/crypt/crypt_prng_is_valid.obj \ -src/misc/crypt/crypt_prng_rng_descriptor.obj src/misc/crypt/crypt_register_all_ciphers.obj \ -src/misc/crypt/crypt_register_all_hashes.obj src/misc/crypt/crypt_register_all_prngs.obj \ -src/misc/crypt/crypt_register_cipher.obj src/misc/crypt/crypt_register_hash.obj \ -src/misc/crypt/crypt_register_prng.obj src/misc/crypt/crypt_sizes.obj \ +src/misc/bcrypt/bcrypt.obj src/misc/burn_stack.obj src/misc/compare_testvector.obj src/misc/copy_or_zeromem.obj \ +src/misc/crc32.obj src/misc/crypt/crypt.obj src/misc/crypt/crypt_argchk.obj \ +src/misc/crypt/crypt_cipher_descriptor.obj src/misc/crypt/crypt_cipher_is_valid.obj \ +src/misc/crypt/crypt_constants.obj src/misc/crypt/crypt_find_cipher.obj \ +src/misc/crypt/crypt_find_cipher_any.obj src/misc/crypt/crypt_find_cipher_id.obj \ +src/misc/crypt/crypt_find_hash.obj src/misc/crypt/crypt_find_hash_any.obj \ +src/misc/crypt/crypt_find_hash_id.obj src/misc/crypt/crypt_find_hash_oid.obj \ +src/misc/crypt/crypt_find_prng.obj src/misc/crypt/crypt_fsa.obj src/misc/crypt/crypt_hash_descriptor.obj \ +src/misc/crypt/crypt_hash_is_valid.obj src/misc/crypt/crypt_inits.obj \ +src/misc/crypt/crypt_ltc_mp_descriptor.obj src/misc/crypt/crypt_prng_descriptor.obj \ +src/misc/crypt/crypt_prng_is_valid.obj src/misc/crypt/crypt_prng_rng_descriptor.obj \ +src/misc/crypt/crypt_register_all_ciphers.obj src/misc/crypt/crypt_register_all_hashes.obj \ +src/misc/crypt/crypt_register_all_prngs.obj src/misc/crypt/crypt_register_cipher.obj \ +src/misc/crypt/crypt_register_hash.obj src/misc/crypt/crypt_register_prng.obj src/misc/crypt/crypt_sizes.obj \ src/misc/crypt/crypt_unregister_cipher.obj src/misc/crypt/crypt_unregister_hash.obj \ src/misc/crypt/crypt_unregister_prng.obj src/misc/error_to_string.obj src/misc/hkdf/hkdf.obj \ src/misc/hkdf/hkdf_test.obj src/misc/mem_neq.obj src/misc/padding/padding_depad.obj \ @@ -216,12 +216,13 @@ src/stream/sosemanuk/sosemanuk.obj src/stream/sosemanuk/sosemanuk_memory.obj \ src/stream/sosemanuk/sosemanuk_test.obj #List of test objects to compile -TOBJECTS=tests/base16_test.obj tests/base32_test.obj tests/base64_test.obj tests/cipher_hash_test.obj \ -tests/common.obj tests/der_test.obj tests/dh_test.obj tests/dsa_test.obj tests/ecc_test.obj tests/ed25519_test.obj \ -tests/file_test.obj tests/mac_test.obj tests/misc_test.obj tests/modes_test.obj tests/mpi_test.obj \ -tests/multi_test.obj tests/no_prng.obj tests/padding_test.obj tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj \ -tests/pkcs_1_oaep_test.obj tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj tests/prng_test.obj \ -tests/rotate_test.obj tests/rsa_test.obj tests/ssh_test.obj tests/store_test.obj tests/test.obj tests/x25519_test.obj +TOBJECTS=tests/base16_test.obj tests/base32_test.obj tests/base64_test.obj tests/bcrypt_test.obj \ +tests/cipher_hash_test.obj tests/common.obj tests/der_test.obj tests/dh_test.obj tests/dsa_test.obj \ +tests/ecc_test.obj tests/ed25519_test.obj tests/file_test.obj tests/mac_test.obj tests/misc_test.obj \ +tests/modes_test.obj tests/mpi_test.obj tests/multi_test.obj tests/no_prng.obj tests/padding_test.obj \ +tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj tests/pkcs_1_oaep_test.obj tests/pkcs_1_pss_test.obj \ +tests/pkcs_1_test.obj tests/prng_test.obj tests/rotate_test.obj tests/rsa_test.obj tests/ssh_test.obj \ +tests/store_test.obj tests/test.obj tests/x25519_test.obj #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile.unix b/makefile.unix index 59e9ece37..9ea44360a 100644 --- a/makefile.unix +++ b/makefile.unix @@ -103,20 +103,20 @@ src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math src/math/radix_to_bin.o src/math/rand_bn.o src/math/rand_prime.o src/math/tfm_desc.o src/misc/adler32.o \ src/misc/base16/base16_decode.o src/misc/base16/base16_encode.o src/misc/base32/base32_decode.o \ src/misc/base32/base32_encode.o src/misc/base64/base64_decode.o src/misc/base64/base64_encode.o \ -src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o src/misc/crc32.o \ -src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o src/misc/crypt/crypt_cipher_descriptor.o \ -src/misc/crypt/crypt_cipher_is_valid.o src/misc/crypt/crypt_constants.o \ -src/misc/crypt/crypt_find_cipher.o src/misc/crypt/crypt_find_cipher_any.o \ -src/misc/crypt/crypt_find_cipher_id.o src/misc/crypt/crypt_find_hash.o \ -src/misc/crypt/crypt_find_hash_any.o src/misc/crypt/crypt_find_hash_id.o \ -src/misc/crypt/crypt_find_hash_oid.o src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o \ -src/misc/crypt/crypt_hash_descriptor.o src/misc/crypt/crypt_hash_is_valid.o \ -src/misc/crypt/crypt_inits.o src/misc/crypt/crypt_ltc_mp_descriptor.o \ -src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \ -src/misc/crypt/crypt_prng_rng_descriptor.o src/misc/crypt/crypt_register_all_ciphers.o \ -src/misc/crypt/crypt_register_all_hashes.o src/misc/crypt/crypt_register_all_prngs.o \ -src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \ -src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ +src/misc/bcrypt/bcrypt.o src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o \ +src/misc/crc32.o src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o \ +src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \ +src/misc/crypt/crypt_constants.o src/misc/crypt/crypt_find_cipher.o \ +src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \ +src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \ +src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \ +src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \ +src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_inits.o \ +src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \ +src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \ +src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \ +src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ +src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ @@ -233,12 +233,13 @@ src/stream/sosemanuk/sosemanuk.o src/stream/sosemanuk/sosemanuk_memory.o \ src/stream/sosemanuk/sosemanuk_test.o #List of test objects to compile (all goes to libtomcrypt_prof.a) -TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/cipher_hash_test.o \ -tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o \ -tests/file_test.o tests/mac_test.o tests/misc_test.o tests/modes_test.o tests/mpi_test.o \ -tests/multi_test.o tests/no_prng.o tests/padding_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ -tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ -tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ +tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ +tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ +tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_prng.o tests/padding_test.o \ +tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o \ +tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o \ +tests/store_test.o tests/test.o tests/x25519_test.o #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile_include.mk b/makefile_include.mk index b40caa641..c7d663218 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -264,20 +264,20 @@ src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math src/math/radix_to_bin.o src/math/rand_bn.o src/math/rand_prime.o src/math/tfm_desc.o src/misc/adler32.o \ src/misc/base16/base16_decode.o src/misc/base16/base16_encode.o src/misc/base32/base32_decode.o \ src/misc/base32/base32_encode.o src/misc/base64/base64_decode.o src/misc/base64/base64_encode.o \ -src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o src/misc/crc32.o \ -src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o src/misc/crypt/crypt_cipher_descriptor.o \ -src/misc/crypt/crypt_cipher_is_valid.o src/misc/crypt/crypt_constants.o \ -src/misc/crypt/crypt_find_cipher.o src/misc/crypt/crypt_find_cipher_any.o \ -src/misc/crypt/crypt_find_cipher_id.o src/misc/crypt/crypt_find_hash.o \ -src/misc/crypt/crypt_find_hash_any.o src/misc/crypt/crypt_find_hash_id.o \ -src/misc/crypt/crypt_find_hash_oid.o src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o \ -src/misc/crypt/crypt_hash_descriptor.o src/misc/crypt/crypt_hash_is_valid.o \ -src/misc/crypt/crypt_inits.o src/misc/crypt/crypt_ltc_mp_descriptor.o \ -src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \ -src/misc/crypt/crypt_prng_rng_descriptor.o src/misc/crypt/crypt_register_all_ciphers.o \ -src/misc/crypt/crypt_register_all_hashes.o src/misc/crypt/crypt_register_all_prngs.o \ -src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \ -src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ +src/misc/bcrypt/bcrypt.o src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o \ +src/misc/crc32.o src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o \ +src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \ +src/misc/crypt/crypt_constants.o src/misc/crypt/crypt_find_cipher.o \ +src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \ +src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \ +src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \ +src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \ +src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_inits.o \ +src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \ +src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \ +src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \ +src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ +src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ @@ -394,12 +394,13 @@ src/stream/sosemanuk/sosemanuk.o src/stream/sosemanuk/sosemanuk_memory.o \ src/stream/sosemanuk/sosemanuk_test.o # List of test objects to compile (all goes to libtomcrypt_prof.a) -TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/cipher_hash_test.o \ -tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o \ -tests/file_test.o tests/mac_test.o tests/misc_test.o tests/modes_test.o tests/mpi_test.o \ -tests/multi_test.o tests/no_prng.o tests/padding_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ -tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ -tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ +tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ +tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ +tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_prng.o tests/padding_test.o \ +tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o \ +tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o \ +tests/store_test.o tests/test.o tests/x25519_test.o # The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/src/ciphers/blowfish.c b/src/ciphers/blowfish.c index b53e05bc8..f661f8642 100644 --- a/src/ciphers/blowfish.c +++ b/src/ciphers/blowfish.c @@ -295,73 +295,128 @@ static const ulong32 ORIG_S[4][256] = { 0xB74E6132UL, 0xCE77E25BUL, 0x578FDFE3UL, 0x3AC372E6UL } }; +#ifndef __GNUC__ +#define F(x) ((S1[LTC_BYTE(x,3)] + S2[LTC_BYTE(x,2)]) ^ S3[LTC_BYTE(x,1)]) + S4[LTC_BYTE(x,0)] +#else +#define F(x) ((skey->blowfish.S[0][LTC_BYTE(x,3)] + skey->blowfish.S[1][LTC_BYTE(x,2)]) ^ skey->blowfish.S[2][LTC_BYTE(x,1)]) + skey->blowfish.S[3][LTC_BYTE(x,0)] +#endif + +static void s_blowfish_encipher(ulong32 *L, ulong32 *R, const symmetric_key *skey) +{ + int rounds; + + ulong32 l, r; +#ifndef __GNUC__ + const ulong32 *S1, *S2, *S3, *S4; + + S1 = skey->blowfish.S[0]; + S2 = skey->blowfish.S[1]; + S3 = skey->blowfish.S[2]; + S4 = skey->blowfish.S[3]; +#endif + + l = *L; + r = *R; + + /* do 16 rounds */ + for (rounds = 0; rounds < 16; ) { + l ^= skey->blowfish.K[rounds++]; r ^= F(l); + r ^= skey->blowfish.K[rounds++]; l ^= F(r); + l ^= skey->blowfish.K[rounds++]; r ^= F(l); + r ^= skey->blowfish.K[rounds++]; l ^= F(r); + } + + /* last keying */ + l ^= skey->blowfish.K[16]; + r ^= skey->blowfish.K[17]; + + *L = r; + *R = l; +} + +void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey) +{ + unsigned long i; + ulong32 *d = data; + + for (i = 0; i < blocks; ++i) { + s_blowfish_encipher(d, d + 1, skey); + d += 2; + } +} + +static ulong32 s_blowfish_stream2word(const unsigned char *d, int dlen, int *cur) +{ + unsigned int z; + int y = *cur; + ulong32 ret = 0; + + for (z = 0; z < 4; z++) { + ret = (ret << 8) | ((ulong32)d[y++] & 255); + if (y == dlen) { + y = 0; + } + } + + *cur = y; + return ret; +} + /** - Initialize the Blowfish block cipher + Expand the Blowfish internal state @param key The symmetric key you wish to pass @param keylen The key length in bytes + @param data The additional data you wish to pass (can be NULL) + @param datalen The additional data length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ -int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, - symmetric_key *skey) +int blowfish_expand(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey) { - ulong32 x, y, z, A; - unsigned char B[8]; + ulong32 x, y, A, B[2]; + int i; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); - /* check key length */ - if (keylen < 8 || keylen > 56) { - return CRYPT_INVALID_KEYSIZE; - } - - /* check rounds */ - if (num_rounds != 0 && num_rounds != 16) { - return CRYPT_INVALID_ROUNDS; - } - /* load in key bytes (Supplied by David Hopwood) */ - for (x = y = 0; x < 18; x++) { - A = 0; - for (z = 0; z < 4; z++) { - A = (A << 8) | ((ulong32)key[y++] & 255); - if (y == (ulong32)keylen) { - y = 0; - } - } - skey->blowfish.K[x] = ORIG_P[x] ^ A; - } - - /* copy sboxes */ - for (x = 0; x < 4; x++) { - for (y = 0; y < 256; y++) { - skey->blowfish.S[x][y] = ORIG_S[x][y]; - } + i = 0; + for (x = 0; x < 18; x++) { + A = s_blowfish_stream2word(key, keylen, &i); + skey->blowfish.K[x] ^= A; } - /* encrypt K array */ - for (x = 0; x < 8; x++) { - B[x] = 0; - } + i = 0; + B[0] = 0; + B[1] = 0; for (x = 0; x < 18; x += 2) { - /* encrypt it */ - blowfish_ecb_encrypt(B, B, skey); - /* copy it */ - LOAD32H(skey->blowfish.K[x], &B[0]); - LOAD32H(skey->blowfish.K[x+1], &B[4]); + if (data != NULL) { + B[0] ^= s_blowfish_stream2word(data, datalen, &i); + B[1] ^= s_blowfish_stream2word(data, datalen, &i); + } + /* encrypt it */ + s_blowfish_encipher(&B[0], &B[1], skey); + /* copy it */ + skey->blowfish.K[x] = B[0]; + skey->blowfish.K[x+1] = B[1]; } /* encrypt S array */ for (x = 0; x < 4; x++) { for (y = 0; y < 256; y += 2) { + if (data != NULL) { + B[0] ^= s_blowfish_stream2word(data, datalen, &i); + B[1] ^= s_blowfish_stream2word(data, datalen, &i); + } /* encrypt it */ - blowfish_ecb_encrypt(B, B, skey); + s_blowfish_encipher(&B[0], &B[1], skey); /* copy it */ - LOAD32H(skey->blowfish.S[x][y], &B[0]); - LOAD32H(skey->blowfish.S[x][y+1], &B[4]); + skey->blowfish.S[x][y] = B[0]; + skey->blowfish.S[x][y+1] = B[1]; } } @@ -372,11 +427,48 @@ int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, return CRYPT_OK; } -#ifndef __GNUC__ -#define F(x) ((S1[LTC_BYTE(x,3)] + S2[LTC_BYTE(x,2)]) ^ S3[LTC_BYTE(x,1)]) + S4[LTC_BYTE(x,0)] -#else -#define F(x) ((skey->blowfish.S[0][LTC_BYTE(x,3)] + skey->blowfish.S[1][LTC_BYTE(x,2)]) ^ skey->blowfish.S[2][LTC_BYTE(x,1)]) + skey->blowfish.S[3][LTC_BYTE(x,0)] -#endif +/** + Initialize the Blowfish block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful +*/ +int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, + symmetric_key *skey) +{ + /* check key length */ + if (keylen < 8 || keylen > 56) { + return CRYPT_INVALID_KEYSIZE; + } + /* check rounds */ + if (num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + return blowfish_setup_with_data(key, keylen, NULL, 0, skey); +} + +/** + Alternative initialize of the Blowfish block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param data The additional data you wish to pass (can be NULL) + @param datalen The additional data length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful +*/ + +int blowfish_setup_with_data(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey) +{ + XMEMCPY(skey->blowfish.K, ORIG_P, sizeof(ORIG_P)); + XMEMCPY(skey->blowfish.S, ORIG_S, sizeof(ORIG_S)); + return blowfish_expand(key, keylen, data, datalen, skey); +} /** Encrypts a block of text with Blowfish @@ -392,41 +484,20 @@ int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symme #endif { ulong32 L, R; - int r; -#ifndef __GNUC__ - const ulong32 *S1, *S2, *S3, *S4; -#endif - - LTC_ARGCHK(pt != NULL); - LTC_ARGCHK(ct != NULL); - LTC_ARGCHK(skey != NULL); -#ifndef __GNUC__ - S1 = skey->blowfish.S[0]; - S2 = skey->blowfish.S[1]; - S3 = skey->blowfish.S[2]; - S4 = skey->blowfish.S[3]; -#endif + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); /* load it */ LOAD32H(L, &pt[0]); LOAD32H(R, &pt[4]); - /* do 16 rounds */ - for (r = 0; r < 16; ) { - L ^= skey->blowfish.K[r++]; R ^= F(L); - R ^= skey->blowfish.K[r++]; L ^= F(R); - L ^= skey->blowfish.K[r++]; R ^= F(L); - R ^= skey->blowfish.K[r++]; L ^= F(R); - } - - /* last keying */ - R ^= skey->blowfish.K[17]; - L ^= skey->blowfish.K[16]; + s_blowfish_encipher(&L, &R, skey); /* store */ - STORE32H(R, &ct[0]); - STORE32H(L, &ct[4]); + STORE32H(L, &ct[0]); + STORE32H(R, &ct[4]); return CRYPT_OK; } @@ -557,6 +628,8 @@ int blowfish_test(void) for (y = 0; y < 1000; y++) blowfish_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } + + return CRYPT_OK; #endif } diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index 920f4cbc4..449895889 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -490,6 +490,12 @@ /* Base16/hex encoding/decoding */ #define LTC_BASE16 +#define LTC_BCRYPT + +#ifndef LTC_BCRYPT_DEFAULT_ROUNDS +#define LTC_BCRYPT_DEFAULT_ROUNDS 10 +#endif + /* Keep LTC_NO_HKDF for compatibility reasons * superseeded by LTC_NO_MISC*/ #ifndef LTC_NO_HKDF @@ -601,6 +607,10 @@ #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled #endif +#if defined(LTC_BCRYPT) && !defined(LTC_BLOWFISH) + #error LTC_BCRYPT requires LTC_BLOWFISH +#endif + #if defined(LTC_CHACHA20POLY1305_MODE) && (!defined(LTC_CHACHA) || !defined(LTC_POLY1305)) #error LTC_CHACHA20POLY1305_MODE requires LTC_CHACHA + LTC_POLY1305 #endif diff --git a/src/headers/tomcrypt_misc.h b/src/headers/tomcrypt_misc.h index cad857bb9..4860a1b35 100644 --- a/src/headers/tomcrypt_misc.h +++ b/src/headers/tomcrypt_misc.h @@ -59,6 +59,13 @@ int base16_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); #endif +#ifdef LTC_BCRYPT +int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, + const unsigned char *salt, unsigned long salt_len, + unsigned int rounds, int hash_idx, + unsigned char *out, unsigned long *outlen); +#endif + /* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ #ifdef LTC_HKDF diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 51c0733f6..d080d6c2f 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -72,6 +72,17 @@ typedef struct * Internal functions */ + +/* tomcrypt_cipher.h */ + +void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey); +int blowfish_expand(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey); +int blowfish_setup_with_data(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey); + /* tomcrypt_hash.h */ /* a simple macro for making hash "process" functions */ diff --git a/src/misc/bcrypt/bcrypt.c b/src/misc/bcrypt/bcrypt.c new file mode 100644 index 000000000..3a80d7ebd --- /dev/null +++ b/src/misc/bcrypt/bcrypt.c @@ -0,0 +1,201 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt_private.h" + +/** + @file bcrypt.c + bcrypt pbkdf, Steffen Jaeckel +*/ +#ifdef LTC_BCRYPT + +#define BCRYPT_WORDS 8 +#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4) + +static int _bcrypt_hash(const unsigned char *pt, + const unsigned char *pass, unsigned long passlen, + const unsigned char *salt, unsigned long saltlen, + unsigned char *out, unsigned long *outlen) +{ + symmetric_key key; + int err, n; + ulong32 ct[BCRYPT_WORDS]; + + if ((err = blowfish_setup_with_data(pass, passlen, salt, saltlen, &key)) != CRYPT_OK) { + return err; + } + for (n = 0; n < 64; ++n) { + if ((err = blowfish_expand(salt, saltlen, NULL, 0, &key)) != CRYPT_OK) { + return err; + } + if ((err = blowfish_expand(pass, passlen, NULL, 0, &key)) != CRYPT_OK) { + return err; + } + } + + for (n = 0; n < BCRYPT_WORDS; ++n) { + LOAD32H(ct[n], &pt[n*4]); + } + + for (n = 0; n < 64; ++n) { + blowfish_enc(ct, BCRYPT_WORDS/2, &key); + } + + for (n = 0; n < BCRYPT_WORDS; ++n) { + STORE32L(ct[n], &out[4 * n]); + } + *outlen = sizeof(ct); +#ifdef LTC_CLEAN_STACK + zeromem(&key, sizeof(key)); + zeromem(ct, sizeof(ct)); +#endif + + return CRYPT_OK; +} + +static int _bcrypt_pbkdf_hash(const unsigned char *pass, unsigned long passlen, + const unsigned char *salt, unsigned long saltlen, + unsigned char *out, unsigned long *outlen) +{ + const unsigned char pt[] = "OxychromaticBlowfishSwatDynamite"; + return _bcrypt_hash(pt, pass, passlen, salt, saltlen, out, outlen); +} + +/** + Compatible to bcrypt_pbkdf() as provided in OpenBSD + @param password The input password (or key) + @param password_len The length of the password (octets) + @param salt The salt (or nonce) + @param salt_len The length of the salt (octets) + @param rounds # of iterations desired [read specs for more] + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The desired size of the algorithm output + @return CRYPT_OK if successful +*/ +int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, + const unsigned char *salt, unsigned long salt_len, + unsigned int rounds, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err; + ulong32 blkno; + unsigned long left, itts, x, y, hashed_pass_len, step_size, steps, dest, used_rounds; + unsigned char *buf[3], blkbuf[4]; + unsigned char *hashed_pass; + + LTC_ARGCHK(secret != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((secret_len == 0) || (salt_len == 0) || (*outlen == 0)) { + return CRYPT_INVALID_ARG; + } + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + /* set default value for rounds if not given */ + if (rounds == 0) { + used_rounds = LTC_BCRYPT_DEFAULT_ROUNDS; + } else { + used_rounds = rounds; + } + + buf[0] = XMALLOC(MAXBLOCKSIZE * 3); + hashed_pass = XMALLOC(MAXBLOCKSIZE); + if (buf[0] == NULL || hashed_pass == NULL) { + if (hashed_pass != NULL) { + XFREE(hashed_pass); + } + if (buf[0] != NULL) { + XFREE(buf[0]); + } + return CRYPT_MEM; + } + /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ + buf[1] = buf[0] + MAXBLOCKSIZE; + buf[2] = buf[1] + MAXBLOCKSIZE; + + step_size = (*outlen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE; + steps = (*outlen + step_size - 1) / step_size; + + hashed_pass_len = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, (unsigned char*)secret, secret_len, hashed_pass, &hashed_pass_len)) != CRYPT_OK) { + goto LBL_ERR; + } + + left = *outlen; + blkno = 0; + while (left != 0) { + /* increment and store current block number */ + ++blkno; + STORE32H(blkno, blkbuf); + + /* process block number blkno */ + zeromem(buf[0], MAXBLOCKSIZE*2); + + x = MAXBLOCKSIZE; + if ((err = hash_memory_multi(hash_idx, buf[0], &x, + salt, salt_len, + blkbuf, 4uL, + NULL, 0)) != CRYPT_OK) { + goto LBL_ERR; + } + y = MAXBLOCKSIZE; + if ((err = _bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + XMEMCPY(buf[2], buf[1], y); + + /* now compute repeated and XOR it in buf[2] */ + for (itts = 1; itts < used_rounds; ++itts) { + x = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, buf[1], y, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y = MAXBLOCKSIZE; + if ((err = _bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + for (x = 0; x < y; x++) { + buf[2][x] ^= buf[1][x]; + } + } + + /* now emit upto `steps` bytes of buf[2] to output */ + steps = MIN(steps, left); + for (y = 0; y < steps; ++y) { + dest = y * step_size + (blkno - 1); + if (dest >= *outlen) + break; + out[dest] = buf[2][y]; + } + left -= y; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf[0], MAXBLOCKSIZE*3); + zeromem(hashed_pass, MAXBLOCKSIZE); +#endif + + XFREE(hashed_pass); + XFREE(buf[0]); + + return err; +} + +#endif + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index 1b4815991..f66978146 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -434,6 +434,10 @@ const char *crypt_build_settings = #if defined(LTC_BASE16) " BASE16 " #endif +#if defined(LTC_BCRYPT) + " BCRYPT " + " " NAME_VALUE(LTC_BCRYPT_DEFAULT_ROUNDS) " " +#endif #if defined(LTC_CRC32) " CRC32 " #endif diff --git a/tests/bcrypt_test.c b/tests/bcrypt_test.c new file mode 100644 index 000000000..d05639dee --- /dev/null +++ b/tests/bcrypt_test.c @@ -0,0 +1,156 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include + +#ifdef LTC_BCRYPT + +/** These tests were shamelessly c&p'ed from the OpenBSD sources + * https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/lib/libutil/bcrypt_pbkdf/bcrypt_pbkdf_test.c */ + +struct test { + unsigned int rounds; + unsigned long passlen; + const char *password; + unsigned long saltlen; + const char *salt; + unsigned long keylen; + const char *key; +}; + +struct test tests[] = { + /* basic */ + { 4, 8, "password", 4, "salt", 32, + "\x5b\xbf\x0c\xc2\x93\x58\x7f\x1c\x36\x35\x55\x5c\x27\x79\x65\x98" + "\xd4\x7e\x57\x90\x71\xbf\x42\x7e\x9d\x8f\xbe\x84\x2a\xba\x34\xd9" + }, + { 4, 8, "password", 1, "", 16, + "\xc1\x2b\x56\x62\x35\xee\xe0\x4c\x21\x25\x98\x97\x0a\x57\x9a\x67" + }, + { 4, 1, "", 4, "salt", 16, + "\x60\x51\xbe\x18\xc2\xf4\xf8\x2c\xbf\x0e\xfe\xe5\x47\x1b\x4b\xb9" + }, + /* nul bytes in password and string */ + { 4, 9, "password", 5, "salt", 32, + "\x74\x10\xe4\x4c\xf4\xfa\x07\xbf\xaa\xc8\xa9\x28\xb1\x72\x7f\xac" + "\x00\x13\x75\xe7\xbf\x73\x84\x37\x0f\x48\xef\xd1\x21\x74\x30\x50" + }, + { 4, 8, "pass\0word", 4, "sa\0lt", 16, + "\xc2\xbf\xfd\x9d\xb3\x8f\x65\x69\xef\xef\x43\x72\xf4\xde\x83\xc0" + }, + { 4, 9, "pass\0word", 5, "sa\0lt", 16, + "\x4b\xa4\xac\x39\x25\xc0\xe8\xd7\xf0\xcd\xb6\xbb\x16\x84\xa5\x6f" + }, + /* bigger key */ + { 8, 8, "password", 4, "salt", 64, + "\xe1\x36\x7e\xc5\x15\x1a\x33\xfa\xac\x4c\xc1\xc1\x44\xcd\x23\xfa" + "\x15\xd5\x54\x84\x93\xec\xc9\x9b\x9b\x5d\x9c\x0d\x3b\x27\xbe\xc7" + "\x62\x27\xea\x66\x08\x8b\x84\x9b\x20\xab\x7a\xa4\x78\x01\x02\x46" + "\xe7\x4b\xba\x51\x72\x3f\xef\xa9\xf9\x47\x4d\x65\x08\x84\x5e\x8d" + }, + /* more rounds */ + { 42, 8, "password", 4, "salt", 16, + "\x83\x3c\xf0\xdc\xf5\x6d\xb6\x56\x08\xe8\xf0\xdc\x0c\xe8\x82\xbd" + }, + /* longer password */ + { 8, 446, + "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do " + "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut " + "enim ad minim veniam, quis nostrud exercitation ullamco laboris " + "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor " + "in reprehenderit in voluptate velit esse cillum dolore eu fugiat " + "nulla pariatur. Excepteur sint occaecat cupidatat non proident, " + "sunt in culpa qui officia deserunt mollit anim id est laborum.", + 6, "salis", 16, + "\x10\x97\x8b\x07\x25\x3d\xf5\x7f\x71\xa1\x62\xeb\x0e\x8a\xd3\x0a" + }, + /* "unicode" */ + { 8, + 16, "\x0d\xb3\xac\x94\xb3\xee\x53\x28\x4f\x4a\x22\x89\x3b\x3c\x24\xae", + 16, "\x3a\x62\xf0\xf0\xdb\xce\xf8\x23\xcf\xcc\x85\x48\x56\xea\x10\x28", + 16, "\x20\x44\x38\x17\x5e\xee\x7c\xe1\x36\xc9\x1b\x49\xa6\x79\x23\xff" + }, + /* very large key */ + { 8, + 16, "\x0d\xb3\xac\x94\xb3\xee\x53\x28\x4f\x4a\x22\x89\x3b\x3c\x24\xae", + 16, "\x3a\x62\xf0\xf0\xdb\xce\xf8\x23\xcf\xcc\x85\x48\x56\xea\x10\x28", + 256, + "\x20\x54\xb9\xff\xf3\x4e\x37\x21\x44\x03\x34\x74\x68\x28\xe9\xed" + "\x38\xde\x4b\x72\xe0\xa6\x9a\xdc\x17\x0a\x13\xb5\xe8\xd6\x46\x38" + "\x5e\xa4\x03\x4a\xe6\xd2\x66\x00\xee\x23\x32\xc5\xed\x40\xad\x55" + "\x7c\x86\xe3\x40\x3f\xbb\x30\xe4\xe1\xdc\x1a\xe0\x6b\x99\xa0\x71" + "\x36\x8f\x51\x8d\x2c\x42\x66\x51\xc9\xe7\xe4\x37\xfd\x6c\x91\x5b" + "\x1b\xbf\xc3\xa4\xce\xa7\x14\x91\x49\x0e\xa7\xaf\xb7\xdd\x02\x90" + "\xa6\x78\xa4\xf4\x41\x12\x8d\xb1\x79\x2e\xab\x27\x76\xb2\x1e\xb4" + "\x23\x8e\x07\x15\xad\xd4\x12\x7d\xff\x44\xe4\xb3\xe4\xcc\x4c\x4f" + "\x99\x70\x08\x3f\x3f\x74\xbd\x69\x88\x73\xfd\xf6\x48\x84\x4f\x75" + "\xc9\xbf\x7f\x9e\x0c\x4d\x9e\x5d\x89\xa7\x78\x39\x97\x49\x29\x66" + "\x61\x67\x07\x61\x1c\xb9\x01\xde\x31\xa1\x97\x26\xb6\xe0\x8c\x3a" + "\x80\x01\x66\x1f\x2d\x5c\x9d\xcc\x33\xb4\xaa\x07\x2f\x90\xdd\x0b" + "\x3f\x54\x8d\x5e\xeb\xa4\x21\x13\x97\xe2\xfb\x06\x2e\x52\x6e\x1d" + "\x68\xf4\x6a\x4c\xe2\x56\x18\x5b\x4b\xad\xc2\x68\x5f\xbe\x78\xe1" + "\xc7\x65\x7b\x59\xf8\x3a\xb9\xab\x80\xcf\x93\x18\xd6\xad\xd1\xf5" + "\x93\x3f\x12\xd6\xf3\x61\x82\xc8\xe8\x11\x5f\x68\x03\x0a\x12\x44" + }, +}; + +int bcrypt_test(void) +{ + unsigned long l; + unsigned char key[1024]; + unsigned int i; + int idx; + struct test *t; + + idx = find_hash("sha512"); + + XMEMSET(key, 0, sizeof(key)); + l = 88; + DO(bcrypt_pbkdf_openbsd("password", 8, (unsigned char*)"salt", 4, 0, idx, key, &l)); + for (i = 1; i < 88; ++i) { + key[0] |= key[i]; + } + if (key[0] == 0) { + return CRYPT_FAIL_TESTVECTOR; + } + if (key[88] || key[89] || key[90]) { + return CRYPT_BUFFER_OVERFLOW; + } +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + printf("BCRYPT overflow-test OK\n"); +#endif + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + t = &tests[i]; + l = t->keylen; + XMEMSET(key, 0, sizeof(key)); + DO(bcrypt_pbkdf_openbsd(t->password, t->passlen, (unsigned char*)t->salt, t->saltlen, t->rounds, idx, key, &l)); + DO(do_compare_testvector(key, l, (unsigned char*)t->key, t->keylen, "OpenBSD testvectors", i)); + +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + printf("BCRYPT test #%d OK\n", i); +#endif + } + + return CRYPT_OK; +} + +#else + + +int bcrypt_test(void) +{ + return CRYPT_NOP; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/tests/misc_test.c b/tests/misc_test.c index 2847af8a0..858c326cc 100644 --- a/tests/misc_test.c +++ b/tests/misc_test.c @@ -10,6 +10,9 @@ int misc_test(void) { +#ifdef LTC_BCRYPT + DO(bcrypt_test()); +#endif #ifdef LTC_HKDF DO(hkdf_test()); #endif diff --git a/tests/tomcrypt_test.h b/tests/tomcrypt_test.h index f190fa360..69d24fc7e 100644 --- a/tests/tomcrypt_test.h +++ b/tests/tomcrypt_test.h @@ -47,6 +47,7 @@ int padding_test(void); int x25519_test(void); int ed25519_test(void); int ssh_test(void); +int bcrypt_test(void); #ifdef LTC_PKCS_1 struct ltc_prng_descriptor* no_prng_desc_get(void);