libqaeda

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README | LICENSE

commit 9734f2f0f23e09432cca1dedc124b96e7be3f28f
parent ca1de5ef5c391b6d1ea74fa1e142ca011bdc5159
Author: lash <dev@holbrook.no>
Date:   Wed,  2 Apr 2025 22:06:44 +0100

Implement missing MAC verification in decrypt, cert test still croaking

Diffstat:
MMakefile | 2+-
Msrc/cli/main.c | 33+++++++++++++++++----------------
Msrc/crypto/gcrypt.c | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/lq/msg.c | 3++-
Msrc/test/Makefile | 17++++++++++-------
5 files changed, 149 insertions(+), 34 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,7 +2,7 @@ all: lib make -C src all lib: - make -C src lib + make -C src dev-lib test: all make -C src test diff --git a/src/cli/main.c b/src/cli/main.c @@ -119,25 +119,26 @@ int main(int argc, char **argv) { return 1; } cert = lq_certificate_new(NULL); - r = lq_certificate_request(cert, req, pk_alice); - if (r != ERR_OK) { - lq_ui_free(); - return 1; - } - - res = lq_msg_new("foo", 4); - if (res == NULL) { - lq_ui_free(); - return 1; - } - r = lq_certificate_respond(cert, res, pk_bob); - if (r != ERR_OK) { - lq_ui_free(); - return 1; - } +// r = lq_certificate_request(cert, req, pk_alice); +// if (r != ERR_OK) { +// lq_ui_free(); +// return 1; +// } +// +// res = lq_msg_new("foo", 4); +// if (res == NULL) { +// lq_ui_free(); +// return 1; +// } +// r = lq_certificate_respond(cert, res, pk_bob); +// if (r != ERR_OK) { +// lq_ui_free(); +// return 1; +// } r = lq_certificate_verify(cert, pubk_alice, NULL); + lq_msg_free(req); lq_certificate_free(cert); lq_ui_free(); diff --git a/src/crypto/gcrypt.c b/src/crypto/gcrypt.c @@ -18,6 +18,8 @@ #define CHACHA20_KEY_LENGTH_BYTES 32 #define CHACHA20_NONCE_LENGTH_BYTES 12 +#define POLY1305_MAC_LEN 16 +#define POLY1305_MAC_KEYLEN 32 /// Lookup mode for key in store. enum gpg_find_mode_e { @@ -47,10 +49,7 @@ static char *gpg_version = NULL; static int gpg_cfg_idx_dir; /// default digest id. -static int gpg_passphrase_digest = GCRY_MD_SHA256; - -/// digest length of hashed password. -static int gpg_passphrase_digest_len; +static int gpg_passphrase_digest = GCRY_MD_SHA512; /// zero fp value const static char gpg_fingerprint_zero[LQ_FP_LEN]; @@ -84,8 +83,6 @@ int lq_crypto_init(const char *base) { } debug_x(LLOG_DEBUG, "gpg", "using gpg", 1, MORGEL_TYP_STR, 0, "version", gpg_version); - //gpg_passphrase_digest_len = gcry_md_get_algo_dlen(GCRY_MD_SHA256); - gpg_passphrase_digest_len = gcry_md_get_algo_dlen(GCRY_MD_SHA512); gpg_cfg_idx_dir = lq_config_register(LQ_TYP_STR, "CRYPTODIR"); p = path; @@ -159,6 +156,103 @@ static void free_handle(gcry_cipher_hd_t *h) { gcry_cipher_close(*h); } +// Puts mac in mac and newly generated mac key in mac_key +// in is a buffer of in_len which must be cipher blocksize. +// no data validation checking is done. +static int create_mac(char *mac, char *mac_key, const char *in, size_t in_len) { + int r; + char *p; + size_t maclen; + gcry_mac_hd_t h; + gcry_error_t e; + + r = gcry_mac_open(&h, GCRY_MAC_POLY1305, 0, NULL); + if (r) { + return r; + } + + e = gcry_mac_setkey(h, mac_key, POLY1305_MAC_KEYLEN); + if (e) { + gcry_mac_close(h); + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + e = gcry_mac_write(h, in, in_len); + if (e) { + gcry_mac_close(h); + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + maclen = POLY1305_MAC_LEN; + e = gcry_mac_read(h, mac, &maclen); + if (e) { + gcry_mac_close(h); + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + gcry_mac_close(h); + + if (maclen != POLY1305_MAC_LEN) { + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + return ERR_OK; +} + +static int verify_mac(char *mac, char *mac_key, const char *in, size_t in_len) { + int r; + char *p; + size_t maclen; + gcry_mac_hd_t h; + gcry_error_t e; + + r = gcry_mac_open(&h, GCRY_MAC_POLY1305, 0, NULL); + if (r) { + return r; + } + + e = gcry_mac_setkey(h, mac_key, POLY1305_MAC_KEYLEN); + if (e) { + gcry_mac_close(h); + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + e = gcry_mac_write(h, in, in_len); + if (e) { + gcry_mac_close(h); + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + maclen = POLY1305_MAC_LEN; + e = gcry_mac_read(h, mac, &maclen); + if (e) { + gcry_mac_close(h); + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + e = gcry_mac_verify(h, mac, maclen); + if (e) { + gcry_mac_close(h); + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + gcry_mac_close(h); + + if (maclen != POLY1305_MAC_LEN) { + p = (char*)gcry_strerror(e); + return debug_logerr(LLOG_ERROR, ERR_CIPHER, p); + } + + return ERR_OK; +} int encryptb (char *ciphertext, size_t ciphertext_len, const char *indata, size_t indata_len, const char *key, const char *nonce) { const char *p; int r; @@ -181,6 +275,7 @@ int encryptb (char *ciphertext, size_t ciphertext_len, const char *indata, size_ free_handle(&h); + return ERR_OK; } @@ -379,7 +474,7 @@ LQStore *key_store_get() { /** * \todo consistent endianness for key length in persistent storage (fwrite) * \todo doc must have enough in path for path + fingerprint hex - * + * \todo check capacity in buffer for both ciphertext, nonce and mac. */ static int key_create_store(struct gpg_store *gpg, const char *passphrase, size_t passphrase_len) { char *p; @@ -396,6 +491,7 @@ static int key_create_store(struct gpg_store *gpg, const char *passphrase, size_ char buf_val[LQ_STORE_VAL_MAX]; char ciphertext[LQ_CRYPTO_BUFLEN]; char passphrase_hash[LQ_DIGEST_LEN]; + char mac[POLY1305_MAC_LEN]; // Create the private key and corresponding public key. r = key_create(gpg); @@ -430,6 +526,14 @@ static int key_create_store(struct gpg_store *gpg, const char *passphrase, size_ return debug_logerr(LLOG_ERROR, ERR_KEY_LOCK, "encrypt private key"); } + c += CHACHA20_NONCE_LENGTH_BYTES; + r = create_mac(mac, passphrase_hash + CHACHA20_KEY_LENGTH_BYTES, v, m+sizeof(int)); + if (r) { + return debug_logerr(LLOG_ERROR, ERR_CIPHER, "mac generation fail"); + return r; + } + lq_cpy(ciphertext + c, mac, POLY1305_MAC_LEN); + // Export the key (fingerprint) and value (ciphertext) to put in the store. // (We don't need the inner private key pointer anymore, so we re-use it.) pubk = lq_publickey_new(gpg->public_key); @@ -440,6 +544,7 @@ static int key_create_store(struct gpg_store *gpg, const char *passphrase, size_ lq_cpy(buf_key, gpg->fingerprint, LQ_FP_LEN); lq_cpy(buf_val, nonce, CHACHA20_NONCE_LENGTH_BYTES); lq_cpy(buf_val + CHACHA20_NONCE_LENGTH_BYTES, ciphertext, c); + lq_cpy(buf_val + CHACHA20_NONCE_LENGTH_BYTES + c, mac, POLY1305_MAC_LEN); lq_publickey_free(pubk); // Retrieve the store. @@ -449,7 +554,7 @@ static int key_create_store(struct gpg_store *gpg, const char *passphrase, size_ } // Write the ciphertext to the store. - l = c + CHACHA20_NONCE_LENGTH_BYTES; + l = c + CHACHA20_NONCE_LENGTH_BYTES + POLY1305_MAC_LEN; c = LQ_FP_LEN; r = store->put(LQ_CONTENT_KEY, store, buf_key, &c, buf_val, l); if (r) { @@ -589,7 +694,12 @@ static int key_from_store(struct gpg_store *gpg, const char *passphrase, size_t nonce = in; p = (char*)in + CHACHA20_NONCE_LENGTH_BYTES; in_len -= CHACHA20_NONCE_LENGTH_BYTES; - r = decryptb(out, p, in_len, passphrase_hash, nonce); + r = decryptb(out, p, in_len - POLY1305_MAC_LEN, passphrase_hash, nonce); + if (r) { + return ERR_KEY_UNLOCK; + } + + r = verify_mac(p + in_len - POLY1305_MAC_LEN, passphrase_hash + CHACHA20_KEY_LENGTH_BYTES, out, in_len - POLY1305_MAC_LEN); if (r) { return ERR_KEY_UNLOCK; } diff --git a/src/lq/msg.c b/src/lq/msg.c @@ -59,7 +59,8 @@ LQSig* lq_msg_sign_extra(LQMsg *msg, LQPrivKey *pk, const char *salt, const char } void lq_msg_free(LQMsg *msg) { - if (msg->pubkey->pk = NULL) { + //if (msg->pubkey->pk = NULL) { + if (msg->pubkey != NULL) { lq_free(msg->pubkey); } lq_free(msg->data); diff --git a/src/test/Makefile b/src/test/Makefile @@ -1,7 +1,8 @@ OBJS := $(patsubst %.c,%.o,$(wildcard *.c)) INCLUDES := -I.. -I../aux/include `pkg-config --cflags libtasn1 libgcrypt` CFLAGS += $(INCLUDES) -Wall -g3 -LIBS := ../asn1/defs_asn1_tab.o `pkg-config --libs libtasn1 libgcrypt` -L../aux/lib -llash -lhashmap +#LIBS := ../asn1/defs_asn1_tab.o `pkg-config --libs libtasn1 libgcrypt` -L../aux/lib -llash -lhashmap +LIBS := ../asn1/defs_asn1_tab.o `pkg-config --libs libtasn1 libgcrypt` -L.. -L../aux/lib -lqaeda -lhashmap #LDFLAGS := -lcheck -lsubunit -lm $(LIBS) LDFLAGS := -lcheck $(LIBS) COMMONOBJS = ../mem/std.o ../lq/config.o ../lq/err.o ../lq/base.o ../debug.o @@ -20,14 +21,16 @@ test: all build: #$(CC) $(CFLAGS) test_test.c -o test_test_bin $(COMMONOBJS) ../io/dummy.o ../store/mem.o $(LDFLAGS) - $(CC) $(CFLAGS) test_test.c -o test_test_bin $(COMMONOBJS) ../io/std.o ../store/file.o $(LDFLAGS) + #$(CC) $(CFLAGS) test_test.c -o test_test_bin $(COMMONOBJS) ../io/std.o ../store/file.o $(LDFLAGS) + $(CC) $(CFLAGS) test_test.c -o test_test_bin $(COMMONOBJS) $(LDFLAGS) $(CC) $(CFLAGS) test_debug.c -o test_debug_bin $(COMMONOBJS) $(LDFLAGS) $(CC) $(CFLAGS) test_config.c -o test_config_bin $(COMMONOBJS) $(LDFLAGS) - $(CC) $(CFLAGS) test_crypto.c -o test_crypto_bin $(COMMONOBJS) ../store/file.o ../io/std.o ../crypto/gcrypt.o $(LDFLAGS) -lgcrypt - $(CC) $(CFLAGS) test_msg.c -o test_msg_bin $(COMMONOBJS) ../store/file.o ../store/dummy.o ../io/std.o ../crypto/gcrypt.o ../lq/msg.o $(LDFLAGS) - $(CC) $(CFLAGS) test_cert.c -o test_cert_bin $(COMMONOBJS) ../store/file.o ../io/std.o ../crypto/gcrypt.o ../store/dummy.o ../lq/msg.o ../lq/cert.o $(LDFLAGS) - $(CC) $(CFLAGS) test_trust.c -o test_trust_bin $(COMMONOBJS) ../store/file.o ../io/std.c ../crypto/gcrypt.o ../lq/trust.o $(LDFLAGS) - $(CC) $(CFLAGS) test_store.c -o test_store_bin $(COMMONOBJS) ../store/file.o ../io/std.o ../crypto/gcrypt.o $(LDFLAGS) + #$(CC) $(CFLAGS) test_crypto.c -o test_crypto_bin $(COMMONOBJS) ../store/file.o ../io/std.o ../crypto/gcrypt.o $(LDFLAGS) -lgcrypt + $(CC) $(CFLAGS) test_crypto.c -o test_crypto_bin $(COMMONOBJS) $(LDFLAGS) -lgcrypt + $(CC) $(CFLAGS) test_msg.c -o test_msg_bin $(COMMONOBJS) ../store/dummy.o $(LDFLAGS) -lgcrypt + $(CC) $(CFLAGS) test_cert.c -o test_cert_bin $(COMMONOBJS) ../store/dummy.o $(LDFLAGS) -lgcrypt + $(CC) $(CFLAGS) test_trust.c -o test_trust_bin $(COMMONOBJS) $(LDFLAGS) + $(CC) $(CFLAGS) test_store.c -o test_store_bin $(COMMONOBJS) $(LDFLAGS) -lgcrypt clean: rm -vf test_*_bin