summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordefanor <defanor@uberspace.net>2021-10-02 14:36:31 +0300
committerdefanor <defanor@uberspace.net>2021-10-02 14:36:31 +0300
commit43f40dd55fa9d20b6ff29e4eca45de88ef01a2d7 (patch)
tree1bdad06a9e43a29aa4a83ba4334442043a982261
parent3af2e52b7b98d894fc5c74e674e95eac24b74f6b (diff)
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.
-rw-r--r--README4
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/rexmpp.c38
-rw-r--r--src/rexmpp_jingle.c32
-rw-r--r--src/rexmpp_openpgp.c10
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 <nettle/sha1.h>
+#include <gcrypt.h>
#include <libxml/tree.h>
#include <libxml/xmlsave.h>
#include <gsasl.h>
@@ -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 <errno.h>
#include <libgen.h>
#include <gsasl.h>
-#include <nettle/sha2.h>
-#include <nettle/sha3.h>
+#include <gcrypt.h>
#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 <gpgme.h>
#endif
#include <libxml/tree.h>
+#include <gcrypt.h>
#include <gsasl.h>
#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",