diff --git a/configure b/configure index a08dda7..d8b876e 100755 --- a/configure +++ b/configure @@ -85,6 +85,7 @@ For better control, use the options below. --with-readline-library=DIR Specify where readline lib directory is --with-ncurses-library=DIR Specify where ncurses lib directory is --disable-sechash Disable support for hashes other than MD5 + --without-nettle Don't use nettle even if it is available --without-nss Don't use NSS even if it is available --without-tomcrypt Don't use libtomcrypt even if it is available --disable-cmdmon Disable command and monitoring support @@ -198,6 +199,7 @@ feat_readline=1 try_readline=1 try_editline=1 feat_sechash=1 +try_nettle=1 try_nss=1 try_tomcrypt=1 feat_rtc=1 @@ -360,6 +362,9 @@ do --disable-sechash ) feat_sechash=0 ;; + --without-nettle ) + try_nettle=0 + ;; --without-nss ) try_nss=0 ;; @@ -857,7 +862,22 @@ fi HASH_OBJ="hash_intmd5.o" HASH_LINK="" -if [ $feat_sechash = "1" ] && [ $try_nss = "1" ]; then +if [ $feat_sechash = "1" ] && [ "x$HASH_LINK" = "x" ] && [ $try_nettle = "1" ]; then + test_cflags="`pkg_config --cflags nettle`" + test_link="`pkg_config --libs nettle`" + if test_code 'nettle' 'nettle/nettle-meta.h nettle/sha2.h' \ + "$test_cflags" "$test_link" \ + 'return nettle_get_hashes()[0]->context_size;' + then + HASH_OBJ="hash_nettle.o" + HASH_LINK="$test_link" + LIBS="$LIBS $HASH_LINK" + MYCPPFLAGS="$MYCPPFLAGS $test_cflags" + add_def FEAT_SECHASH + fi +fi + +if [ $feat_sechash = "1" ] && [ "x$HASH_LINK" = "x" ] && [ $try_nss = "1" ]; then test_cflags="`pkg_config --cflags nss`" test_link="`pkg_config --libs-only-L nss` -lfreebl3" if test_code 'NSS' 'nss.h hasht.h nsslowhash.h' \ diff --git a/hash_nettle.c b/hash_nettle.c new file mode 100644 index 0000000..cc9b8ad --- /dev/null +++ b/hash_nettle.c @@ -0,0 +1,125 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Miroslav Lichvar 2018 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + ********************************************************************** + + ======================================================================= + + Routines implementing crypto hashing using the nettle library. + + */ + +#include "config.h" + +#include "sysincl.h" + +#include + +#include "hash.h" +#include "memory.h" + +struct hash { + const char *name; + const char *int_name; + const struct nettle_hash *nettle_hash; + void *context; +}; + +static struct hash hashes[] = { + { "MD5", "md5", NULL, NULL }, + { "RMD160", "ripemd160", NULL, NULL }, + { "SHA1", "sha1", NULL, NULL }, + { "SHA256", "sha256", NULL, NULL }, + { "SHA384", "sha384", NULL, NULL }, + { "SHA512", "sha512", NULL, NULL }, + { "SHA3-224", "sha3_224", NULL, NULL }, + { "SHA3-256", "sha3_256", NULL, NULL }, + { "SHA3-384", "sha3_384", NULL, NULL }, + { "SHA3-512", "sha3_512", NULL, NULL }, + { NULL, NULL, NULL, NULL } +}; + +int +HSH_GetHashId(const char *name) +{ + const struct nettle_hash *const *nhashes; + int id, nid; + + for (id = 0; hashes[id].name; id++) { + if (!strcmp(name, hashes[id].name)) + break; + } + + if (!hashes[id].name) + return -1; + + if (hashes[id].context) + return id; + + nhashes = nettle_get_hashes(); + if (!nhashes) + return -1; + + for (nid = 0; nhashes[nid]; nid++) { + if (!strcmp(hashes[id].int_name, nhashes[nid]->name)) + break; + } + + if (!nhashes[nid] || !nhashes[nid]->context_size || !nhashes[nid]->init) + return -1; + + hashes[id].nettle_hash = nhashes[nid]; + hashes[id].context = Malloc(hashes[id].nettle_hash->context_size); + + return id; +} + +unsigned int +HSH_Hash(int id, const unsigned char *in1, unsigned int in1_len, + const unsigned char *in2, unsigned int in2_len, + unsigned char *out, unsigned int out_len) +{ + const struct nettle_hash *hash; + void *context; + + hash = hashes[id].nettle_hash; + context = hashes[id].context; + + if (out_len > hash->digest_size) + out_len = hash->digest_size; + + hash->init(context); + hash->update(context, in1_len, in1); + if (in2) + hash->update(context, in2_len, in2); + hash->digest(context, out_len, out); + + return out_len; +} + +void +HSH_Finalise(void) +{ + int i; + + for (i = 0; hashes[i].name; i++) { + if (hashes[i].context) + Free(hashes[i].context); + } +}