commit 3791fb3b150c54658d06754f4187f08cd7c3ec98
parent bf39ba1b2f770c01a5b8e198bc076d1b9362d208
Author: lash <dev@holbrook.no>
Date: Sun, 30 Mar 2025 02:43:48 +0100
Remove seed input for private key
Diffstat:
7 files changed, 77 insertions(+), 30 deletions(-)
diff --git a/src/Makefile b/src/Makefile
@@ -9,7 +9,7 @@ lib: all
lib:
ar rcs liblq.a lq/config.o crypto/gcrypt.o store/file.o mem/std.o io/std.o debug.o aux/lib/libhashmap.a
-core:
+core: dummy
$(CC) $(CFLAGS) -c debug.c
make -C lq
diff --git a/src/crypto/dummy.c b/src/crypto/dummy.c
@@ -1,3 +1,5 @@
+#include <stdlib.h>
+
#include "lq/crypto.h"
#include "lq/mem.h"
#include "lq/err.h"
@@ -48,6 +50,14 @@ struct dummycrypto {
size_t len; ///< Length of private key data.
};
+void fill_random(char *buf, size_t len) {
+ int i;
+
+ for (i = 0; i < len; i++) {
+ *(buf+i) = (char)(rand()%255);
+ }
+}
+
void keylock_xor(LQPrivKey *pk, const char *passphrase_digest) {
int i;
struct dummycrypto *o;
@@ -90,15 +100,15 @@ int lq_privatekey_lock(LQPrivKey *pk, const char *passphrase, size_t passphrase_
return ERR_OK;
}
-LQPrivKey* lq_privatekey_new(const char *seed, size_t seed_len, const char *passphrase, size_t passphrase_len) {
+LQPrivKey* lq_privatekey_new(const char *passphrase, size_t passphrase_len) {
LQPrivKey *pk;
struct dummycrypto *o;
o = lq_alloc(sizeof(struct dummycrypto));
pk = lq_alloc(sizeof(LQPrivKey));
- o->data = lq_alloc(seed_len);
- lq_cpy(o->data, seed, seed_len);
- o->len = seed_len;
+ o->data = lq_alloc(LQ_PRIVKEY_LEN);
+ fill_random(o->data, LQ_PRIVKEY_LEN);
+ o->len = LQ_PRIVKEY_LEN;
pk->impl = o;
pk->key_typ = 0;
pk->key_state = 0;
diff --git a/src/crypto/gcrypt.c b/src/crypto/gcrypt.c
@@ -337,22 +337,21 @@ static int key_create(struct gpg_store *gpg) {
gcry_sexp_t in;
gcry_error_t e;
+ // Set up parameters for key creation.
e = gcry_sexp_new(&in, (const void*)sexp_quick, strlen(sexp_quick), 0);
if (e) {
p = gcry_strerror(e);
return debug_logerr(LLOG_ERROR, ERR_CRYPTO, (char*)p);
}
+
+ // Generate a new key with the given parameters.
e = gcry_pk_genkey(&gpg->k, in);
if (e) {
p = gcry_strerror(e);
return debug_logerr(LLOG_ERROR, ERR_CRYPTO, (char*)p);
}
-// p = (char*)gcry_pk_get_keygrip(gpg->k, (unsigned char*)gpg->fingerprint);
-// if (p == NULL) {
-// p = gcry_strerror(e);
-// return debug_logerr(LLOG_ERROR, ERR_CRYPTO, (char*)p);
-// }
-//
+
+ // Apply the public part of the key to the underlying key structure.
r = key_apply_public(gpg, gpg->k);
if (r) {
return debug_logerr(LLOG_ERROR, ERR_CRYPTO, NULL);
@@ -361,6 +360,9 @@ static int key_create(struct gpg_store *gpg) {
return ERR_OK;
}
+// Create a new store instance using the crypto partition path
+// set in the configuration.
+// Caller must free it.
LQStore *key_store_get() {
int r;
char *p;
@@ -371,6 +373,7 @@ LQStore *key_store_get() {
}
return lq_store_new(p);
}
+
//
//static char *key_filename(LQStore *store, struct gpg_store *gpg, char *out, size_t *out_len) {
// int l;
@@ -490,7 +493,7 @@ static int key_create_store(struct gpg_store *gpg, const char *passphrase) {
}
/// Create a new keypair, encrypted with given passphrase.
-static LQPrivKey* privatekey_alloc(const char *seed, size_t seed_len, const char *passphrase, size_t passphrase_len) {
+static LQPrivKey* privatekey_alloc(const char *passphrase, size_t passphrase_len) {
int r;
LQPrivKey *o;
struct gpg_store *gpg;
@@ -527,14 +530,14 @@ static LQPrivKey* privatekey_alloc(const char *seed, size_t seed_len, const char
/// Implements the interface to create a new private key.
-LQPrivKey* lq_privatekey_new(const char *seed, size_t seed_len, const char *passphrase, size_t passphrase_len) {
+LQPrivKey* lq_privatekey_new(const char *passphrase, size_t passphrase_len) {
int r;
LQPrivKey *o;
if (passphrase == NULL) {
return NULL;
}
- o = privatekey_alloc(seed, seed_len, passphrase, passphrase_len);
+ o = privatekey_alloc(passphrase, passphrase_len);
if (o == NULL) {
return NULL;
}
@@ -545,6 +548,7 @@ LQPrivKey* lq_privatekey_new(const char *seed, size_t seed_len, const char *pass
return o;
}
+/// Parse data from buffer as S-expression text representing a key.
static int key_from_data(gcry_sexp_t *key, const char *indata, size_t indata_len) {
gcry_error_t e;
@@ -555,6 +559,7 @@ static int key_from_data(gcry_sexp_t *key, const char *indata, size_t indata_len
return ERR_OK;
}
+/// Load a private key from the store's crypto partition.
static int key_from_store(struct gpg_store *gpg, const char *passphrase) {
char *nonce;
char *p;
@@ -567,32 +572,49 @@ static int key_from_store(struct gpg_store *gpg, const char *passphrase) {
char in[LQ_CRYPTO_BUFLEN];
size_t in_len;
size_t out_len;
-
+
+ // Instantiate the store.
+ store = key_store_get();
+
+ // If a valid fingerprint is found in the gpg structure,
+ // retrieve the key matching that fingerprint.
+ // Otherwise, retrieve the main key.
+ // Or fail if none of them can be found.
inkey_len = LQ_FP_LEN;
in_len = LQ_CRYPTO_BUFLEN;
- store = key_store_get();
if (lq_cmp(gpg->fingerprint, gpg_fingerprint_zero, LQ_FP_LEN)) {
lq_cpy(inkey, gpg->fingerprint, LQ_FP_LEN);
} else {
- *inkey = '_';
+ *inkey = gpg_default_store_key;
inkey_len = 1;
}
r = store->get(LQ_CONTENT_KEY, store, inkey, inkey_len, in, &in_len);
if (r) {
+ lq_free(store);
return ERR_NOENT;
}
+ // The private key in the store is encrypted.
+ // Decrypt it with the provided passphrase.
nonce = in;
p = (char*)in + CHACHA20_NONCE_LENGTH_BYTES;
in_len -= CHACHA20_NONCE_LENGTH_BYTES;
r = decryptb(out, p, in_len, passphrase, nonce);
if (r) {
- return r;
+ lq_free(store);
+ return ERR_CRYPTO;
}
-
+
+ // Attempt to parse and instantiate the key from the decrypted data.
out_len = (size_t)(*((int*)out));
p = (char*)(out+sizeof(int));
r = key_from_data(&gpg->k, p, out_len);
+ if (r) {
+ lq_free(store);
+ return ERR_COMPAT;
+ }
+
+ lq_free(store);
return ERR_OK;
}
diff --git a/src/lq/crypto.h b/src/lq/crypto.h
@@ -130,7 +130,7 @@ void lq_crypto_free();
* \return Pointer to new private key. Freeing the object is the caller's responsibility.
* \see lq_privatekey_free
*/
-LQPrivKey* lq_privatekey_new(const char *seed, size_t seed_len, const char *passphrase, size_t passphrase_len);
+LQPrivKey* lq_privatekey_new(const char *passphrase, size_t passphrase_len);
/**
* \brief Load a private key from store.
diff --git a/src/lq/store.h b/src/lq/store.h
@@ -54,8 +54,23 @@ struct lq_resolve_t {
LQResolve *next; ///< Provides access to next store implementation to store to or retrieve from. Setting to NULL stops any further action.
};
+/**
+ * \brief Instantiate a new store from the given path or connection spec.
+ *
+ * Caller must free the store after use with lq_store_free.
+ *
+ * \param[in] Connection string or path.
+ * \return A new store object, or NULL by failure.
+ *
+ * \see lq_store_free
+ */
LQStore* lq_store_new(const char *spec);
-void lq_store_free(LQStore *store);
+/**
+ * \brief Free resources used by store instance.
+ *
+ * \param[in] Store object.
+ */
+void lq_store_free(LQStore *store);
#endif // LIBQAEDA_STORE_H_
diff --git a/src/test/test_cert.c b/src/test/test_cert.c
@@ -79,7 +79,7 @@ START_TEST(check_cert_symmetric_req_sig) {
LQCtx ctx;
char buf[4096];
- pk = lq_privatekey_new(privkeydata, 32, passphrase, 32);
+ pk = lq_privatekey_new(passphrase, 32);
lq_set(&ctx, 0, sizeof(LQCtx));
req = lq_msg_new(data, strlen(data) + 1);
cert = lq_certificate_new(NULL, &ctx, req, NULL);
@@ -108,7 +108,7 @@ START_TEST(check_cert_symmetric_rsp_onesig) {
LQCtx ctx;
char buf[4096];
- pk = lq_privatekey_new(privkeydata, 32, passphrase, 32);
+ pk = lq_privatekey_new(passphrase, 32);
lq_set(&ctx, 0, sizeof(LQCtx));
req = lq_msg_new(data, strlen(data) + 1);
rsp = lq_msg_new(data_two, strlen(data_two) + 1);
@@ -138,7 +138,7 @@ START_TEST(check_cert_symmetric_rsp_bothsig) {
LQCtx ctx;
char buf[4096];
- pk = lq_privatekey_new(privkeydata, 32, passphrase, 32);
+ pk = lq_privatekey_new(passphrase, 32);
lq_set(&ctx, 0, sizeof(LQCtx));
req = lq_msg_new(data, strlen(data) + 1);
cert = lq_certificate_new(NULL, &ctx, req, NULL);
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
@@ -43,7 +43,7 @@ START_TEST(check_privatekey) {
int r;
LQPrivKey *pk;
- pk = lq_privatekey_new(privkeydata, LQ_PRIVKEY_LEN, passphrase, passphrase_len);
+ pk = lq_privatekey_new(passphrase, passphrase_len);
ck_assert_ptr_nonnull(pk);
lq_privatekey_free(pk);
}
@@ -56,7 +56,7 @@ START_TEST(check_publickey) {
char *keydata;
char *keydata_manual;
- pk = lq_privatekey_new(privkeydata, LQ_PRIVKEY_LEN, passphrase, passphrase_len);
+ pk = lq_privatekey_new(passphrase, passphrase_len);
pubk = lq_publickey_from_privatekey(pk);
lq_publickey_bytes(pubk, &keydata);
pubk_manual = lq_publickey_new(keydata);
@@ -75,7 +75,7 @@ START_TEST(check_signature) {
LQSig *sig;
char *sigdata;
- pk = lq_privatekey_new(privkeydata, 32, passphrase, passphrase_len);
+ pk = lq_privatekey_new(passphrase, passphrase_len);
sig = lq_privatekey_sign(pk, data, strlen(data), salt);
ck_assert_ptr_null(sig);
@@ -99,7 +99,7 @@ START_TEST(check_verify) {
LQSig *sig;
char *sigdata;
- pk = lq_privatekey_new(privkeydata, LQ_PRIVKEY_LEN, passphrase, 32);
+ pk = lq_privatekey_new(passphrase, 32);
sig = lq_privatekey_sign(pk, data, strlen(data), salt);
ck_assert_ptr_null(sig);
@@ -120,7 +120,7 @@ START_TEST(check_create_load) {
LQPrivKey *pk;
LQPrivKey *pk_load;
- pk = lq_privatekey_new(privkeydata, LQ_PRIVKEY_LEN, passphrase, passphrase_len);
+ pk = lq_privatekey_new(passphrase, passphrase_len);
ck_assert_ptr_nonnull(pk);
pk_load = lq_privatekey_load(passphrase, passphrase_len, NULL);
ck_assert_ptr_nonnull(pk_load);
@@ -136,7 +136,7 @@ START_TEST(check_load_specific) {
char *p;
size_t c;
- pk = lq_privatekey_new(privkeydata, LQ_PRIVKEY_LEN, passphrase, passphrase_len);
+ pk = lq_privatekey_new(passphrase, passphrase_len);
ck_assert_ptr_nonnull(pk);
pubk = lq_publickey_from_privatekey(pk);
ck_assert_ptr_nonnull(pubk);