Skip to content

Commit 5ded083

Browse files
authored
Merge pull request #497 from libtom/bcrypt
Bcrypt
2 parents 238eb73 + 36260ae commit 5ded083

File tree

15 files changed

+665
-157
lines changed

15 files changed

+665
-157
lines changed

doc/crypt.tex

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7002,7 +7002,7 @@ \subsection{PKCS \#5}
70027002

70037003
The OpenSSL project implemented an extension to Algorithm One that allows for arbitrary keylengths; we have a compatible implementation described below.
70047004

7005-
\subsection{Algorithm One}
7005+
\subsubsection{Algorithm One}
70067006
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
70077007
people trying to brute force guess the password. The higher the iteration counter the longer the delay. This algorithm also requires a hash
70087008
algorithm and produces an output no longer than the output of the hash.
@@ -7035,7 +7035,7 @@ \subsection{Algorithm One}
70357035
unsigned long *outlen)
70367036
\end{alltt}
70377037
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!!).
7038-
\subsection{Algorithm Two}
7038+
\subsubsection{Algorithm Two}
70397039

70407040
Algorithm Two is the recommended algorithm for this task. It allows variable length salts, and can produce outputs larger than the
70417041
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}
70917091
}
70927092
\end{verbatim}
70937093

7094+
7095+
\subsection{bcrypt}
7096+
\index{bcrypt}
7097+
7098+
bcrypt is a password hashing function, similar to PKCS \#5, but it is based on the blowfish symmetric cipher.
7099+
It is widely used in e.g. OpenBSD as default password hash algorithm, or in encrypted OpenSSH key files.
7100+
7101+
This implementation provides the PBKDF version as used in OpenSSH key files.
7102+
7103+
The OpenBSD implementation is fixed to SHA512 as hashing algorithm, but this generalized implementation works with any hashing algorithm.
7104+
7105+
To hash a password with the bcrypt PBKDF algorithm, the following API function is provided.
7106+
7107+
\index{bcrypt()}
7108+
\begin{alltt}
7109+
int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len,
7110+
const unsigned char *salt, unsigned long salt_len,
7111+
unsigned int rounds, int hash_idx,
7112+
unsigned char *out, unsigned long *outlen);
7113+
\end{alltt}
7114+
7115+
The \textit{secret} parameter is the secret of length \textit{secret\_len} (most of the time a utf-8 encoded user password).
7116+
The \textit{salt} parameter is a pointer to the array of octets of length \textit{salt\_len} containing the salt.
7117+
The \textit{rounds} parameter defines the number of iterations of the expensive key setup that shall be executed.
7118+
The \textit{hash\_idx} parameter defines the hash algorithm that shall be used.
7119+
The \textit{out} parameter shall be a pointer to a buffer of at least 32 octets,
7120+
where \textit{outlen} contains the available buffer size on input and the written size after the invocation.
7121+
7122+
70947123
\mysection{PKCS \#8}
70957124
\index{PKCS \#8}
70967125

@@ -7127,6 +7156,7 @@ \subsection{Algorithm Two}
71277156
The PKCS \#8 import has no direct API endpoints, but it is available through Public Key Algorithm-specific
71287157
\textit{pkaX\_import\_pkcs8()} functions.
71297158

7159+
71307160
\mysection{Key Derviation Functions}
71317161
\subsection{HKDF}
71327162
\index{HKDF}

libtomcrypt_VS2008.vcproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,14 @@
14151415
>
14161416
</File>
14171417
</Filter>
1418+
<Filter
1419+
Name="bcrypt"
1420+
>
1421+
<File
1422+
RelativePath="src\misc\bcrypt\bcrypt.c"
1423+
>
1424+
</File>
1425+
</Filter>
14181426
<Filter
14191427
Name="crypt"
14201428
>

makefile.mingw

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,20 @@ src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math
9393
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 \
9494
src/misc/base16/base16_decode.o src/misc/base16/base16_encode.o src/misc/base32/base32_decode.o \
9595
src/misc/base32/base32_encode.o src/misc/base64/base64_decode.o src/misc/base64/base64_encode.o \
96-
src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o src/misc/crc32.o \
97-
src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o src/misc/crypt/crypt_cipher_descriptor.o \
98-
src/misc/crypt/crypt_cipher_is_valid.o src/misc/crypt/crypt_constants.o \
99-
src/misc/crypt/crypt_find_cipher.o src/misc/crypt/crypt_find_cipher_any.o \
100-
src/misc/crypt/crypt_find_cipher_id.o src/misc/crypt/crypt_find_hash.o \
101-
src/misc/crypt/crypt_find_hash_any.o src/misc/crypt/crypt_find_hash_id.o \
102-
src/misc/crypt/crypt_find_hash_oid.o src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o \
103-
src/misc/crypt/crypt_hash_descriptor.o src/misc/crypt/crypt_hash_is_valid.o \
104-
src/misc/crypt/crypt_inits.o src/misc/crypt/crypt_ltc_mp_descriptor.o \
105-
src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \
106-
src/misc/crypt/crypt_prng_rng_descriptor.o src/misc/crypt/crypt_register_all_ciphers.o \
107-
src/misc/crypt/crypt_register_all_hashes.o src/misc/crypt/crypt_register_all_prngs.o \
108-
src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \
109-
src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
96+
src/misc/bcrypt/bcrypt.o src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o \
97+
src/misc/crc32.o src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o \
98+
src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \
99+
src/misc/crypt/crypt_constants.o src/misc/crypt/crypt_find_cipher.o \
100+
src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \
101+
src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \
102+
src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \
103+
src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \
104+
src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_inits.o \
105+
src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \
106+
src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \
107+
src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \
108+
src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \
109+
src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
110110
src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \
111111
src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \
112112
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 \
223223
src/stream/sosemanuk/sosemanuk_test.o
224224

225225
#List of test objects to compile
226-
TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/cipher_hash_test.o \
227-
tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o \
228-
tests/file_test.o tests/mac_test.o tests/misc_test.o tests/modes_test.o tests/mpi_test.o \
229-
tests/multi_test.o tests/no_prng.o tests/padding_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \
230-
tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \
231-
tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o
226+
TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \
227+
tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \
228+
tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \
229+
tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_prng.o tests/padding_test.o \
230+
tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o \
231+
tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o \
232+
tests/store_test.o tests/test.o tests/x25519_test.o
232233

233234
#The following headers will be installed by "make install"
234235
HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \

makefile.msvc

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,20 @@ src/math/fp/ltc_ecc_fp_mulmod.obj src/math/gmp_desc.obj src/math/ltm_desc.obj sr
8686
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 \
8787
src/misc/base16/base16_decode.obj src/misc/base16/base16_encode.obj src/misc/base32/base32_decode.obj \
8888
src/misc/base32/base32_encode.obj src/misc/base64/base64_decode.obj src/misc/base64/base64_encode.obj \
89-
src/misc/burn_stack.obj src/misc/compare_testvector.obj src/misc/copy_or_zeromem.obj src/misc/crc32.obj \
90-
src/misc/crypt/crypt.obj src/misc/crypt/crypt_argchk.obj src/misc/crypt/crypt_cipher_descriptor.obj \
91-
src/misc/crypt/crypt_cipher_is_valid.obj src/misc/crypt/crypt_constants.obj \
92-
src/misc/crypt/crypt_find_cipher.obj src/misc/crypt/crypt_find_cipher_any.obj \
93-
src/misc/crypt/crypt_find_cipher_id.obj src/misc/crypt/crypt_find_hash.obj \
94-
src/misc/crypt/crypt_find_hash_any.obj src/misc/crypt/crypt_find_hash_id.obj \
95-
src/misc/crypt/crypt_find_hash_oid.obj src/misc/crypt/crypt_find_prng.obj src/misc/crypt/crypt_fsa.obj \
96-
src/misc/crypt/crypt_hash_descriptor.obj src/misc/crypt/crypt_hash_is_valid.obj \
97-
src/misc/crypt/crypt_inits.obj src/misc/crypt/crypt_ltc_mp_descriptor.obj \
98-
src/misc/crypt/crypt_prng_descriptor.obj src/misc/crypt/crypt_prng_is_valid.obj \
99-
src/misc/crypt/crypt_prng_rng_descriptor.obj src/misc/crypt/crypt_register_all_ciphers.obj \
100-
src/misc/crypt/crypt_register_all_hashes.obj src/misc/crypt/crypt_register_all_prngs.obj \
101-
src/misc/crypt/crypt_register_cipher.obj src/misc/crypt/crypt_register_hash.obj \
102-
src/misc/crypt/crypt_register_prng.obj src/misc/crypt/crypt_sizes.obj \
89+
src/misc/bcrypt/bcrypt.obj src/misc/burn_stack.obj src/misc/compare_testvector.obj src/misc/copy_or_zeromem.obj \
90+
src/misc/crc32.obj src/misc/crypt/crypt.obj src/misc/crypt/crypt_argchk.obj \
91+
src/misc/crypt/crypt_cipher_descriptor.obj src/misc/crypt/crypt_cipher_is_valid.obj \
92+
src/misc/crypt/crypt_constants.obj src/misc/crypt/crypt_find_cipher.obj \
93+
src/misc/crypt/crypt_find_cipher_any.obj src/misc/crypt/crypt_find_cipher_id.obj \
94+
src/misc/crypt/crypt_find_hash.obj src/misc/crypt/crypt_find_hash_any.obj \
95+
src/misc/crypt/crypt_find_hash_id.obj src/misc/crypt/crypt_find_hash_oid.obj \
96+
src/misc/crypt/crypt_find_prng.obj src/misc/crypt/crypt_fsa.obj src/misc/crypt/crypt_hash_descriptor.obj \
97+
src/misc/crypt/crypt_hash_is_valid.obj src/misc/crypt/crypt_inits.obj \
98+
src/misc/crypt/crypt_ltc_mp_descriptor.obj src/misc/crypt/crypt_prng_descriptor.obj \
99+
src/misc/crypt/crypt_prng_is_valid.obj src/misc/crypt/crypt_prng_rng_descriptor.obj \
100+
src/misc/crypt/crypt_register_all_ciphers.obj src/misc/crypt/crypt_register_all_hashes.obj \
101+
src/misc/crypt/crypt_register_all_prngs.obj src/misc/crypt/crypt_register_cipher.obj \
102+
src/misc/crypt/crypt_register_hash.obj src/misc/crypt/crypt_register_prng.obj src/misc/crypt/crypt_sizes.obj \
103103
src/misc/crypt/crypt_unregister_cipher.obj src/misc/crypt/crypt_unregister_hash.obj \
104104
src/misc/crypt/crypt_unregister_prng.obj src/misc/error_to_string.obj src/misc/hkdf/hkdf.obj \
105105
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 \
216216
src/stream/sosemanuk/sosemanuk_test.obj
217217

218218
#List of test objects to compile
219-
TOBJECTS=tests/base16_test.obj tests/base32_test.obj tests/base64_test.obj tests/cipher_hash_test.obj \
220-
tests/common.obj tests/der_test.obj tests/dh_test.obj tests/dsa_test.obj tests/ecc_test.obj tests/ed25519_test.obj \
221-
tests/file_test.obj tests/mac_test.obj tests/misc_test.obj tests/modes_test.obj tests/mpi_test.obj \
222-
tests/multi_test.obj tests/no_prng.obj tests/padding_test.obj tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj \
223-
tests/pkcs_1_oaep_test.obj tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj tests/prng_test.obj \
224-
tests/rotate_test.obj tests/rsa_test.obj tests/ssh_test.obj tests/store_test.obj tests/test.obj tests/x25519_test.obj
219+
TOBJECTS=tests/base16_test.obj tests/base32_test.obj tests/base64_test.obj tests/bcrypt_test.obj \
220+
tests/cipher_hash_test.obj tests/common.obj tests/der_test.obj tests/dh_test.obj tests/dsa_test.obj \
221+
tests/ecc_test.obj tests/ed25519_test.obj tests/file_test.obj tests/mac_test.obj tests/misc_test.obj \
222+
tests/modes_test.obj tests/mpi_test.obj tests/multi_test.obj tests/no_prng.obj tests/padding_test.obj \
223+
tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj tests/pkcs_1_oaep_test.obj tests/pkcs_1_pss_test.obj \
224+
tests/pkcs_1_test.obj tests/prng_test.obj tests/rotate_test.obj tests/rsa_test.obj tests/ssh_test.obj \
225+
tests/store_test.obj tests/test.obj tests/x25519_test.obj
225226

226227
#The following headers will be installed by "make install"
227228
HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \

makefile.unix

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,20 @@ src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math
103103
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 \
104104
src/misc/base16/base16_decode.o src/misc/base16/base16_encode.o src/misc/base32/base32_decode.o \
105105
src/misc/base32/base32_encode.o src/misc/base64/base64_decode.o src/misc/base64/base64_encode.o \
106-
src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o src/misc/crc32.o \
107-
src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o src/misc/crypt/crypt_cipher_descriptor.o \
108-
src/misc/crypt/crypt_cipher_is_valid.o src/misc/crypt/crypt_constants.o \
109-
src/misc/crypt/crypt_find_cipher.o src/misc/crypt/crypt_find_cipher_any.o \
110-
src/misc/crypt/crypt_find_cipher_id.o src/misc/crypt/crypt_find_hash.o \
111-
src/misc/crypt/crypt_find_hash_any.o src/misc/crypt/crypt_find_hash_id.o \
112-
src/misc/crypt/crypt_find_hash_oid.o src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o \
113-
src/misc/crypt/crypt_hash_descriptor.o src/misc/crypt/crypt_hash_is_valid.o \
114-
src/misc/crypt/crypt_inits.o src/misc/crypt/crypt_ltc_mp_descriptor.o \
115-
src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \
116-
src/misc/crypt/crypt_prng_rng_descriptor.o src/misc/crypt/crypt_register_all_ciphers.o \
117-
src/misc/crypt/crypt_register_all_hashes.o src/misc/crypt/crypt_register_all_prngs.o \
118-
src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \
119-
src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
106+
src/misc/bcrypt/bcrypt.o src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o \
107+
src/misc/crc32.o src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o \
108+
src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \
109+
src/misc/crypt/crypt_constants.o src/misc/crypt/crypt_find_cipher.o \
110+
src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \
111+
src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \
112+
src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \
113+
src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \
114+
src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_inits.o \
115+
src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \
116+
src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \
117+
src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \
118+
src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \
119+
src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
120120
src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \
121121
src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \
122122
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 \
233233
src/stream/sosemanuk/sosemanuk_test.o
234234

235235
#List of test objects to compile (all goes to libtomcrypt_prof.a)
236-
TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/cipher_hash_test.o \
237-
tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o \
238-
tests/file_test.o tests/mac_test.o tests/misc_test.o tests/modes_test.o tests/mpi_test.o \
239-
tests/multi_test.o tests/no_prng.o tests/padding_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \
240-
tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \
241-
tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o
236+
TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \
237+
tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \
238+
tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \
239+
tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_prng.o tests/padding_test.o \
240+
tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o \
241+
tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o \
242+
tests/store_test.o tests/test.o tests/x25519_test.o
242243

243244
#The following headers will be installed by "make install"
244245
HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \

0 commit comments

Comments
 (0)