From 43f40dd55fa9d20b6ff29e4eca45de88ef01a2d7 Mon Sep 17 00:00:00 2001 From: defanor Date: Sat, 2 Oct 2021 14:36:31 +0300 Subject: Use libgcrypt for hashing and random Libgsasl will probably be made optional, so another source of random is needed. Libgsasl uses libgcrypt underneath. Gcrypt, unlike nettle, handles random seeding on its own, which would be annoying to implement for different platforms otherwise. --- README | 4 ++-- configure.ac | 2 +- src/Makefile.am | 4 ++-- src/rexmpp.c | 38 +++++++++++++++++++++++--------------- src/rexmpp_jingle.c | 32 ++++++++++++++++++-------------- src/rexmpp_openpgp.c | 10 +++------- 6 files changed, 49 insertions(+), 41 deletions(-) diff --git a/README b/README index 6f0b183..bf5c72c 100644 --- a/README +++ b/README @@ -14,8 +14,8 @@ rely on any particular UI, should be flexible and not stay in the way of implementing additional XEPs on top of it, and should try to make it easy to implement a decent client application using it. -Current dependencies: libxml2, gsasl, nettle. Optionally libunbound or -c-ares, gnutls with gnutls-dane or openssl, icu-i18n, gpgme, curl. +Current dependencies: libxml2, gsasl, libgcrypt. Optionally libunbound +or c-ares, gnutls with gnutls-dane or openssl, icu-i18n, gpgme, curl. A rough roadmap: diff --git a/configure.ac b/configure.ac index ca97aae..116598a 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ PKG_CHECK_MODULES([LIBXML], [libxml-2.0]) PKG_CHECK_MODULES([GSASL], [libgsasl]) -PKG_CHECK_MODULES([NETTLE], [nettle]) +AM_PATH_LIBGCRYPT # DNS: libunbound or c-ares, optional diff --git a/src/Makefile.am b/src/Makefile.am index c4b5591..b77083c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,8 +28,8 @@ include_HEADERS = config.h rexmpp_roster.h rexmpp_tcp.h rexmpp_socks.h rexmpp.h librexmpp_la_CFLAGS = $(AM_CFLAGS) $(LIBXML_CFLAGS) \ $(GNUTLS_CFLAGS) $(LIBDANE_CFLAGS) $(OPENSSL_CFLAGS) \ $(GSASL_CFLAGS) $(UNBOUND_CFLAGS) $(CARES_CFLAGS) $(GPGME_CFLAGS) \ - $(ICU_I18N_CFLAGS) $(NETTLE_CFLAGS) $(CURL_CFLAGS) + $(ICU_I18N_CFLAGS) $(LIBGCRYPT_CFLAGS) $(CURL_CFLAGS) librexmpp_la_LIBADD = $(LIBXML_LIBS) \ $(GNUTLS_LIBS) $(LIBDANE_LIBS) $(OPENSSL_LIBS) \ $(GSASL_LIBS) $(UNBOUND_LIBS) $(CARES_LIBS) $(GPGME_LIBS) $(ICU_I18N_LIBS) \ - $(NETTLE_LIBS) $(CURL_LIBS) + $(LIBGCRYPT_LIBS) $(CURL_LIBS) diff --git a/src/rexmpp.c b/src/rexmpp.c index de01b2a..5d45f6e 100644 --- a/src/rexmpp.c +++ b/src/rexmpp.c @@ -17,7 +17,7 @@ #include "config.h" -#include +#include #include #include #include @@ -216,15 +216,19 @@ char *rexmpp_capabilities_string (rexmpp_t *s, xmlNodePtr info) { char *rexmpp_capabilities_hash (rexmpp_t *s, xmlNodePtr info) { - struct sha1_ctx ctx; - sha1_init(&ctx); - char hash[SHA1_DIGEST_SIZE]; - char *str = rexmpp_capabilities_string(s, info); - sha1_update(&ctx, strlen(str), str); - sha1_digest(&ctx, SHA1_DIGEST_SIZE, hash); char *out = NULL; size_t out_len = 0; - gsasl_base64_to(hash, SHA1_DIGEST_SIZE, &out, &out_len); + char *str = rexmpp_capabilities_string(s, info); + if (str != NULL) { + unsigned int sha1_len = gcry_md_get_algo_dlen(GCRY_MD_SHA1); + char *sha1 = malloc(sha1_len); + if (sha1 != NULL) { + gcry_md_hash_buffer(GCRY_MD_SHA1, sha1, str, strlen(str)); + gsasl_base64_to(sha1, sha1_len, &out, &out_len); + free(sha1); + } + free(str); + } return out; } @@ -599,6 +603,15 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s, return REXMPP_E_JID; } + if (! gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) { + rexmpp_log(s, LOG_DEBUG, "Initializing libgcrypt"); + if (gcry_check_version(NULL) == NULL) { + rexmpp_log(s, LOG_CRIT, "Failed to initialize libgcrypt"); + return REXMPP_E_OTHER; + } + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + } + s->xml_parser = xmlCreatePushParserCtxt(&sax, s, "", 0, NULL); if (s->xml_parser == NULL) { @@ -790,7 +803,7 @@ void rexmpp_schedule_reconnect (rexmpp_t *s) { return; } if (s->reconnect_number == 0) { - gsasl_nonce((char*)&s->reconnect_seconds, sizeof(time_t)); + gcry_create_nonce((char*)&s->reconnect_seconds, sizeof(time_t)); if (s->reconnect_seconds < 0) { s->reconnect_seconds = - s->reconnect_seconds; } @@ -825,12 +838,7 @@ char *rexmpp_gen_id (rexmpp_t *s) { int sasl_err; char buf_raw[18], *buf_base64 = NULL; size_t buf_base64_len = 0; - sasl_err = gsasl_nonce(buf_raw, 18); - if (sasl_err != GSASL_OK) { - rexmpp_log(s, LOG_ERR, "Random generation failure: %s", - gsasl_strerror(sasl_err)); - return NULL; - } + gcry_create_nonce(buf_raw, 18); sasl_err = gsasl_base64_to(buf_raw, 18, &buf_base64, &buf_base64_len); if (sasl_err != GSASL_OK) { rexmpp_log(s, LOG_ERR, "Base-64 encoding failure: %s", diff --git a/src/rexmpp_jingle.c b/src/rexmpp_jingle.c index 25cbdb4..1e0674c 100644 --- a/src/rexmpp_jingle.c +++ b/src/rexmpp_jingle.c @@ -17,8 +17,7 @@ The following XEPs are handled here so far: #include #include #include -#include -#include +#include #include "rexmpp.h" #include "rexmpp_jingle.h" @@ -279,38 +278,43 @@ rexmpp_jingle_send_file (rexmpp_t *s, char buf[4096]; - char hash_sha256[SHA256_DIGEST_SIZE]; - struct sha256_ctx sha2_ctx; - sha256_init(&sha2_ctx); - char hash_sha3_256[SHA3_256_DIGEST_SIZE]; - struct sha3_256_ctx sha3_ctx; - sha3_256_init(&sha3_ctx); + gcry_md_hd_t hd; + /* todo: check for hashing errors */ + gcry_md_open(&hd, GCRY_MD_SHA256, 0); + gcry_md_enable(hd, GCRY_MD_SHA3_256); size_t len = fread(buf, 1, 4096, fh); while (len > 0) { - sha256_update(&sha2_ctx, len, buf); - sha3_256_update(&sha3_ctx, len, buf); + gcry_md_write(hd, buf, len); len = fread(buf, 1, 4096, fh); } - sha256_digest(&sha2_ctx, SHA256_DIGEST_SIZE, hash_sha256); + gcry_md_final(hd); + char *hash_base64 = NULL; size_t hash_base64_len = 0; - gsasl_base64_to(hash_sha256, SHA256_DIGEST_SIZE, &hash_base64, &hash_base64_len); + gsasl_base64_to(gcry_md_read(hd, GCRY_MD_SHA256), + gcry_md_get_algo_dlen(GCRY_MD_SHA256), + &hash_base64, + &hash_base64_len); xmlNodePtr file_hash = rexmpp_xml_new_node("hash", "urn:xmpp:hashes:2"); xmlNewProp(file_hash, "algo", "sha-256"); xmlNodeAddContent(file_hash, hash_base64); free(hash_base64); xmlAddChild(file, file_hash); - sha3_256_digest(&sha3_ctx, SHA3_256_DIGEST_SIZE, hash_sha3_256); hash_base64 = NULL; hash_base64_len = 0; - gsasl_base64_to(hash_sha3_256, SHA3_256_DIGEST_SIZE, &hash_base64, &hash_base64_len); + gsasl_base64_to(gcry_md_read(hd, GCRY_MD_SHA3_256), + gcry_md_get_algo_dlen(GCRY_MD_SHA3_256), + &hash_base64, + &hash_base64_len); file_hash = rexmpp_xml_new_node("hash", "urn:xmpp:hashes:2"); xmlNewProp(file_hash, "algo", "sha3-256"); xmlNodeAddContent(file_hash, hash_base64); free(hash_base64); xmlAddChild(file, file_hash); + gcry_md_close(hd); + long fsize = ftell(fh); fseek(fh, 0, SEEK_SET); snprintf(buf, 11, "%ld", fsize); diff --git a/src/rexmpp_openpgp.c b/src/rexmpp_openpgp.c index 3e71169..09b2b4e 100644 --- a/src/rexmpp_openpgp.c +++ b/src/rexmpp_openpgp.c @@ -48,6 +48,7 @@ Possible future improvements: #include #endif #include +#include #include #include "rexmpp.h" @@ -755,14 +756,9 @@ char *rexmpp_openpgp_payload (rexmpp_t *s, /* A random-length random-content padding. */ char *rand_str, rand[256]; - gsasl_nonce(rand, 1); + gcry_create_nonce(rand, 1); size_t rand_str_len = 0, rand_len = (unsigned char)rand[0] % (255 - 16) + 16; - sasl_err = gsasl_nonce(rand, rand_len); - if (sasl_err != GSASL_OK) { - rexmpp_log(s, LOG_ERR, "Random generation failure: %s", - gsasl_strerror(sasl_err)); - return NULL; - } + gcry_create_nonce(rand, rand_len); sasl_err = gsasl_base64_to(rand, rand_len, &rand_str, &rand_str_len); if (sasl_err != GSASL_OK) { rexmpp_log(s, LOG_ERR, "Base-64 encoding failure: %s", -- cgit v1.2.3