commit 8af665c5171e1483342a8873bed864aaf9cd7f09
parent 81b2eb86981bf751d0519e6fb5a359ca5bf773ea
Author: lash <dev@holbrook.no>
Date: Thu, 27 Mar 2025 17:00:45 +0000
WIP add load key from file capability
Diffstat:
10 files changed, 502 insertions(+), 90 deletions(-)
diff --git a/src/Makefile b/src/Makefile
@@ -7,7 +7,7 @@ all-gpg: asn1 aux core gpg
lib: all
lib:
- ar rcs lq.a lq/config.o crypto/gcrypt.o store/file.o mem/std.o io/std.o debug.o aux/lib/libhashmap.a
+ 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:
$(CC) $(CFLAGS) -c debug.c
diff --git a/src/crypto/gcrypt.c b/src/crypto/gcrypt.c
@@ -6,14 +6,20 @@
#include <gcrypt.h>
#include <rerr.h>
#include <llog.h>
+#include <hex.h>
#include "lq/crypto.h"
#include "lq/io.h"
#include "lq/mem.h"
#include "lq/config.h"
#include "lq/err.h"
+#include "lq/store.h"
#include "debug.h"
+#define GPG_PK_FILENAME "lq.gpg"
+#define CHACHA20_KEY_LENGTH_BYTES 32
+#define CHACHA20_NONCE_LENGTH_BYTES 12
+
#ifdef RERR
char *_rerr[7] = {
"",
@@ -26,18 +32,41 @@ char *_rerr[7] = {
};
#endif
+enum gpg_find_mode_e {
+ GPG_FIND_MAIN,
+ GPG_FIND_FINGERPRINT,
+};
+
+/**
+ * gcrypt implementation of the crypto interface.
+ *
+ * The same structure is used in both LQPrivKey and LQPubKey.
+ *
+ */
struct gpg_store {
- gcry_sexp_t k;
- char fingerprint[LQ_FP_LEN];
- char public_key[LQ_PUBKEY_LEN];
- char last_signature[LQ_SIGN_LEN];
- char last_data[LQ_DIGEST_LEN];
+ gcry_sexp_t k; ///< S-expression representing the current object type.
+ char fingerprint[LQ_FP_LEN]; ///< Fingerprint, used for LQPubKey.
+ char public_key[LQ_PUBKEY_LEN]; ///< Literal, uncompressed public key bytes. Used in LQPubKey.
+ char last_signature[LQ_SIGN_LEN]; ///< Stores the latest signature data generated by lq_privatekey_sign.
+ char last_data[LQ_DIGEST_LEN]; ///< Stores the last digest data that was signed using lq_privatekey_sign.
};
+/// store gpg library version.
static const char *gpg_version = NULL;
+
+/// directory holding crypto keys.
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;
+/**
+ * Verifies that installed gpg version is supported.
+ * Sets up crypto keys dir and sets passphrase digest length.
+ */
int lq_crypto_init() {
#ifdef RERR
rerr_register(RERR_PFX_GPG, "crypto", _rerr);
@@ -69,7 +98,8 @@ int lq_crypto_init() {
// DIGEST SECTION
-int calculate_digest_algo(const char *in, size_t in_len, char *out, enum gcry_md_algos algo) {
+/// Calculate a digest according to the specified algo.
+static int calculate_digest_algo(const char *in, size_t in_len, char *out, enum gcry_md_algos algo) {
gcry_error_t e;
gcry_md_hd_t h;
unsigned char *v;
@@ -92,15 +122,14 @@ int calculate_digest_algo(const char *in, size_t in_len, char *out, enum gcry_md
return ERR_OK;
}
-//int calculate_digest(const char *in, size_t in_len, char *out) {
-// return calculate_digest_algo(in, in_len, out, GCRY_MD_NONE);
-//}
-
+/// Calculate digest using the default hashing algorithm (SHA256)
+/// using the gcrypt library.
int lq_digest(const char *in, size_t in_len, char *out) {
return calculate_digest_algo(in, in_len, out, GCRY_MD_NONE);
}
+/// Apply public key to the gpg_store struct.
static int key_apply_public(struct gpg_store *gpg, gcry_sexp_t key) {
char *p;
size_t c;
@@ -123,11 +152,11 @@ static int key_apply_public(struct gpg_store *gpg, gcry_sexp_t key) {
return ERR_OK;
}
+/// Create a new gcrypt keypair.
static int key_create(struct gpg_store *gpg) {
int r;
const char *p;
const char *sexp_quick = "(genkey(ecc(flags eddsa)(curve Ed25519)))";
- //char *pv;
gcry_sexp_t in;
gcry_error_t e;
@@ -156,6 +185,7 @@ static int key_create(struct gpg_store *gpg) {
}
+/// 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) {
int r;
LQPrivKey *o;
@@ -189,6 +219,7 @@ static LQPrivKey* privatekey_alloc(const char *seed, size_t seed_len, const char
return o;
}
+/// 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) {
int r;
LQPrivKey *o;
@@ -204,7 +235,278 @@ LQPrivKey* lq_privatekey_new(const char *seed, size_t seed_len, const char *pass
return o;
}
+size_t get_padsize(size_t insize, size_t blocksize) {
+ size_t c;
+ size_t l;
+ size_t m;
+
+ c = insize + 1;
+ l = c / blocksize;
+ m = c % blocksize;
+ if (m) {
+ l++;
+ }
+ return l * blocksize;
+}
+
+static void padb(char *data, size_t outsize, size_t insize) {
+ gcry_randomize(data + insize, outsize - insize, GCRY_STRONG_RANDOM);
+}
+
+static void pad(char *indata_raw, size_t outsize, const char *indata) { //std::string indata) {
+ int l;
+
+ //strcpy(indata_raw, indata.c_str());
+ strcpy(indata_raw, indata);
+ //l = indata.length() + 1;
+ l = strlen(indata) + 1;
+ padb(indata_raw, outsize, l);
+}
+
+static int create_handle(gcry_cipher_hd_t *h, const char *key, const char *nonce) {
+ gcry_error_t e;
+
+ e = gcry_cipher_open(h, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_POLY1305, GCRY_CIPHER_SECURE);
+ if (e) {
+ return 1;
+ }
+ e = gcry_cipher_setkey(*h, key, CHACHA20_KEY_LENGTH_BYTES);
+ if (e) {
+ return 1;
+ }
+ e = gcry_cipher_setiv(*h, nonce, CHACHA20_NONCE_LENGTH_BYTES);
+ if (e) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static void free_handle(gcry_cipher_hd_t *h) {
+ gcry_cipher_close(*h);
+}
+
+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;
+ gcry_cipher_hd_t h;
+ gcry_error_t e;
+ char indata_raw[ciphertext_len];
+
+ r = create_handle(&h, key, nonce);
+ if (r) {
+ return debug_logerr(LLOG_ERROR, ERR_NOCRYPTO, NULL);
+ }
+ memcpy(indata_raw, indata, indata_len);
+ padb(indata_raw, ciphertext_len, indata_len);
+ e = gcry_cipher_encrypt(h, (unsigned char*)ciphertext, ciphertext_len, (const unsigned char*)indata_raw, ciphertext_len);
+ if (e) {
+ p = gcry_strerror(e);
+ return debug_logerr(LLOG_ERROR, ERR_NOCRYPTO, (char*)p);
+ }
+
+ free_handle(&h);
+
+ return ERR_OK;
+}
+
+int encrypt(char *ciphertext, size_t ciphertext_len, const char *indata, const char *key, const char *nonce) {
+ char *p;
+ int r;
+ gcry_cipher_hd_t h;
+ gcry_error_t e;
+ char indata_raw[ciphertext_len];
+
+ r = create_handle(&h, key, nonce);
+ if (r) {
+ return debug_logerr(LLOG_ERROR, ERR_NOCRYPTO, NULL);
+ }
+
+ pad(indata_raw, ciphertext_len, indata);
+ e = gcry_cipher_encrypt(h, (unsigned char*)ciphertext, ciphertext_len, (const unsigned char*)indata_raw, ciphertext_len);
+ if (e) {
+ p = (char*)gcry_strerror(e);
+ return debug_logerr(LLOG_ERROR, ERR_NOCRYPTO, p);
+ }
+
+ free_handle(&h);
+
+ return ERR_OK;
+}
+
+int decryptb(char *outdata, const char *ciphertext, size_t ciphertext_len, const char *key, const char *nonce) {
+ char *p;
+ int r;
+ gcry_cipher_hd_t h;
+ gcry_error_t e;
+
+ r = create_handle(&h, key, nonce);
+ if (r) {
+ return debug_logerr(LLOG_ERROR, ERR_NOCRYPTO, NULL);
+ }
+
+ e = gcry_cipher_decrypt(h, outdata, ciphertext_len, ciphertext, ciphertext_len);
+ if (e) {
+ p = (char*)gcry_strerror(e);
+ return debug_logerr(LLOG_ERROR, ERR_NOCRYPTO, p);
+ }
+
+ free_handle(&h);
+
+ return ERR_OK;
+}
+
+int decrypt(char *outdata, const char *ciphertext, size_t ciphertext_len, const char *key, const char *nonce) {
+ char *p;
+ int r;
+ gcry_cipher_hd_t h;
+ gcry_error_t e;
+ char outdata_raw[ciphertext_len];
+
+ memset(outdata_raw, 0, sizeof(outdata_raw));
+
+ outdata_raw[0] = 0;
+ r = create_handle(&h, key, nonce);
+ if (r) {
+ return debug_logerr(LLOG_ERROR, ERR_NOCRYPTO, NULL);
+ }
+
+ e = gcry_cipher_decrypt(h, outdata_raw, ciphertext_len, ciphertext, ciphertext_len);
+ if (e) {
+ p = (char*)gcry_strerror(e);
+ return debug_logerr(LLOG_ERROR, ERR_NOCRYPTO, p);
+ }
+ //outdata->assign(outdata_raw);
+ strcpy(outdata, outdata_raw);
+
+ free_handle(&h);
+
+ return ERR_OK;
+}
+static int key_from_data(gcry_sexp_t *key, const char *indata, size_t indata_len) {
+ gcry_error_t e;
+
+ e = gcry_sexp_new(key, indata, indata_len, 0);
+ if (e != GPG_ERR_NO_ERROR) {
+ return debug_logerr(LLOG_ERROR, ERR_COMPAT, NULL);
+ }
+ return ERR_OK;
+}
+
+static int key_from_file(gcry_sexp_t *key, const char *path, const char *passphrase) {
+ char *p;
+ int r;
+ char v[LQ_CRYPTO_BUFLEN];
+ size_t c;
+ size_t i;
+ FILE *f;
+ char nonce[CHACHA20_NONCE_LENGTH_BYTES];
+ void *outdata;
+
+ f = fopen(path, "r");
+ if (f == NULL) {
+ return debug_logerr(LLOG_ERROR, ERR_NOENT, NULL);
+ }
+
+ /// \todo length must be in the ciphertext
+ //c = fread(&l, sizeof(int), 1, f);
+ c = fread(nonce, CHACHA20_NONCE_LENGTH_BYTES, 1, f);
+ i = 0;
+ c = 1;
+ while (c != 0 && i < LQ_CRYPTO_BUFLEN) {
+ c = fread(v+i, 1024, 1, f);
+ c *= 1024;
+ i += c;
+ }
+ if (i == 0) {
+ return debug_logerr(LLOG_ERROR, ERR_CRYPTO, (char*)path);
+ }
+ fclose(f);
+
+ outdata = malloc(i);
+ r = decryptb((char*)outdata, v, i, passphrase, nonce);
+ if (r) {
+ return r;
+ }
+ //r = key_from_data(key, (char*)outdata, l);
+ c = (size_t)(*((int*)outdata));
+ p = (char*)(outdata+sizeof(int));
+ r = key_from_data(key, p, c);
+ free(outdata);
+ return ERR_OK;
+}
+static int gpg_key_load(LQStore *store, struct gpg_store *gpg, const char *passphrase, enum gpg_find_mode_e mode, const void *criteria) {
+ int r;
+ char *p;
+ char path[LQ_PATH_MAX];
+
+ switch(mode) {
+ case GPG_FIND_MAIN:
+ strcpy(path, store->userdata);
+ p = path + strlen(path);
+ strcpy(p, GPG_PK_FILENAME);
+ r = key_from_file(&gpg->k, path, passphrase);
+ if (r) {
+ return debug_logerr(LLOG_WARNING, ERR_KEYFAIL, NULL);
+ }
+ break;
+ case GPG_FIND_FINGERPRINT:
+ strcpy(path, store->userdata);
+ p = path + strlen(path);
+ b2h((const unsigned char*)criteria, LQ_FP_LEN, (unsigned char*)p);
+ r = key_from_file(&gpg->k, path, passphrase);
+ if (r) {
+ return debug_logerr(LLOG_WARNING, ERR_KEYFAIL, NULL);
+ }
+ break;
+ default:
+ return debug_logerr(LLOG_WARNING, ERR_FAIL, NULL);
+ }
+
+ p = (char*)gcry_pk_get_keygrip(gpg->k, (unsigned char*)gpg->fingerprint);
+ if (p == NULL) {
+ return debug_logerr(LLOG_ERROR, ERR_KEYFAIL, NULL);
+ }
+
+ r = key_apply_public(gpg, gpg->k);
+ if (r) {
+ return debug_logerr(LLOG_ERROR, ERR_FAIL, NULL);
+ }
+
+ return ERR_OK;
+
+}
+
+/// Implements the interface to load a private key from storage.
LQPrivKey* lq_privatekey_load(const char *passphrase, size_t passphrase_len) {
+ LQStore *store;
+ LQPrivKey *pk;
+ char *p;
+
+ struct gpg_store *gpg;
+ int r;
+
+ char passphrase_hash[gpg_passphrase_digest_len];
+ r = calculate_digest_algo(passphrase, passphrase_len, passphrase_hash, gpg_passphrase_digest);
+ if (r) {
+ return NULL;
+ }
+
+ r = lq_config_get(LQ_TYP_STR, (void**)&p);
+ if (r) {
+ return NULL;
+ }
+ gpg = lq_alloc(sizeof(struct gpg_store));
+ store = lq_store_new(p);
+ if (store == NULL) {
+ return NULL;
+ }
+
+ r = gpg_key_load(store, gpg, passphrase_hash, GPG_FIND_MAIN, NULL);
+ if (r) {
+ return NULL;
+ }
+
return NULL;
}
diff --git a/src/debug.h b/src/debug.h
@@ -1,14 +1,48 @@
#ifndef MORGEL_H_
#define MORGEL_H_
+/**
+ * \brief Data type indicator for the structured log.
+ *
+ * \see debug_dbg_x
+ */
enum debug_typ_e {
- MORGEL_TYP_BIN,
- MORGEL_TYP_NUM,
+ MORGEL_TYP_BIN, ///< Binary content type.
+ MORGEL_TYP_NUM, ///< Numeric content type.
MORGEL_TYP_STR,
};
+/**
+ * \brief Log a literal message with the given namespace.
+ *
+ * \param[in] Namespace string. If NULL, will use the default namespace.
+ * \param[in] Literal message to log.
+ */
void debug_dbg(const char *ns, const char *msg);
+
+/**
+ * \brief Log a structured message with the given namespace.
+ *
+ * Each structured argument consist of three parameters:
+ * 1. An enum debug_typ_e specifying the type of value (and thus how to format it)
+ * 2. An int value specifying the length of the value behind the pointer, in bytes. Currently only used with MORGEL_TYPE_BIN
+ * 3. Pointer to value.
+ *
+ * \param[in] Namespace string. If NULL, will use the default namespace.
+ * \param[in] Main message to log.
+ * \param[in] Number of structured key/value arguments.
+ * \param[in] Key/value list (see above)
+ */
void debug_dbg_x(const char *ns, const char *msg, int argc, ...);
+
+/**
+ * \brief Convenience function to log a single error, using rerr for error code to string resolution.
+ *
+ * \param[in] Log level to use for the log line.
+ * \param[in] Error code to log.
+ * \param[in] Supporting message to include in log line.
+ * \return The error code.
+ */
int debug_logerr(enum lloglvl_e lvl, int err, char *msg);
-#endif // MOREGELLONS_H_
+#endif // MORGEL_H_
diff --git a/src/lq/config.h b/src/lq/config.h
@@ -11,20 +11,59 @@
#include "lq/mem.h"
+/**
+ * Core configuration keys.
+ */
enum lq_config_core_e {
- LQ_CFG_DIR_BASE,
- LQ_CFG_DIR_CONFIG,
- LQ_CFG_DIR_DATA,
- LQ_CFG_DIR_CACHE,
- LQ_CFG_LAST,
+ LQ_CFG_DIR_BASE, ///< Base working directory.
+ LQ_CFG_DIR_CONFIG, ///< Configurations directory.
+ LQ_CFG_DIR_DATA, ///< Data directory.
+ LQ_CFG_DIR_CACHE, ///< Cache directory.
+ LQ_CFG_LAST, ///< Start of subsystem defined configuration keys.
};
+/**
+ * \brief Initialize the instance-wide config singleton.
+ *
+ * @return ERR_OK on success.
+ */
int lq_config_init();
+
+/**
+ * \brief Register a configuration key/value pair.
+ *
+ * \param[in] Type of value to be stored under key.
+ * \param[in] Configuration key.
+ * \return ERR_OK on success.
+ */
int lq_config_register(enum lq_typ_e typ, const char *name);
-int lq_config_key(const char *name);
+
+/**
+ * \brief Set value for a configuration key.
+ *
+ * \param[in] Configuration key.
+ * \param[in] Value to set. Must correspond to the previously registered value type.
+ * \return ERR_OK on success.
+ *
+ * \see lq_config_register
+ */
int lq_config_set(int k, void *v);
+
+/**
+ * \brief Retrieve a value stored under a configuration key.
+ *
+ * \param[in] Configuration key.
+ * \param[out] Pointer to value write location. Must be sufficient to hold the registered value type.
+ * \return ERR_OK on success.
+ *
+ * \see lq_config_register
+ */
int lq_config_get(int k, void **r);
+
+/**
+ * \brief Release configuration resources.
+ */
void lq_config_free();
#endif
diff --git a/src/lq/crypto.h b/src/lq/crypto.h
@@ -99,147 +99,148 @@ struct lq_signature_t {
typedef struct lq_signature_t LQSig;
/**
- * @brief Perform necessary initializations of crypto component.
+ * \brief Perform necessary initializations of crypto component.
*
- * @return ERR_OK on success.
+ * \return ERR_OK on success.
*/
int lq_crypto_init();
/**
- * @brief Perform necessary resource release of crypto component.
+ * \brief Perform necessary resource release of crypto component.
*/
void lq_crypto_free();
/**
- * @brief Create a new private key
+ * \brief Create a new private key
*
* If passphrase is not null the passphrase will be encrypted using that passphrase by default.
*
- * @param[in] Key material. If NULL, a new random private key will be generated.
- * @param[in] Length of key material. Ignored if seed parameter is NULL.
- * @param[in] Encryption passphrase for key.
- * @return Pointer to new private key. Freeing the object is the caller's responsibility.
- * @see lq_privatekey_free
+ * \param[in] Key material. If NULL, a new random private key will be generated.
+ * \param[in] Length of key material. Ignored if seed parameter is NULL.
+ * \param[in] Passphrase to encrypt key with. If NULL, key will be encrypted with a single 0-byte as passphrase.
+ * \param[in] Passphrase length. Ignored if passphrase is NULL.
+ * \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);
/**
- * @brief Get raw private key bytes
+ * \brief Get raw private key bytes
*
- * @param[in] Private key object.
- * @param[out] Pointer to start of data.
- * @return Length of key. If 0, no key could be found.
+ * \param[in] Private key object.
+ * \param[out] Pointer to start of data.
+ * \return Length of key. If 0, no key could be found.
*/
size_t lq_privatekey_bytes(LQPrivKey *pk, char **out);
/**
- * @brief Create a new public key object.
+ * \brief Create a new public key object.
*
- * @param[in] Uncompressed public key data.
- * @param[out] Pointer to new public key. Freeing the object is the caller's responsibility.
- * @see lq_publickey_free
+ * \param[in] Uncompressed public key data.
+ * \param[out] Pointer to new public key. Freeing the object is the caller's responsibility.
+ * \see lq_publickey_free
*/
LQPubKey* lq_publickey_new(const char *full);
/**
- * @brief Create a new public key object from a private key.
+ * \brief Create a new public key object from a private key.
*
- * @param[in] Private key to generate public key from.
- * @return Pointer to new public key. Freeing the object is the caller's responsibility.
- * @see lq_publickey_free
+ * \param[in] Private key to generate public key from.
+ * \return Pointer to new public key. Freeing the object is the caller's responsibility.
+ * \see lq_publickey_free
*/
LQPubKey* lq_publickey_from_privatekey(LQPrivKey *pk);
/**
- * @brief Get raw public key bytes
+ * \brief Get raw public key bytes
*
- * @param[in] Public key object.
- * @param[out] Pointer to start of data.
- * @return Length of key. If 0, no key could be found.
+ * \param[in] Public key object.
+ * \param[out] Pointer to start of data.
+ * \return Length of key. If 0, no key could be found.
*/
size_t lq_publickey_bytes(LQPubKey *pubk, char **out);
/**
- * @brief Encrypt private key in place.
+ * \brief Encrypt private key in place.
*
* Must clear sensistive memory.
*
- * @param[in] Private Key object
- * @return ERR_OK if encrypted, ERR_NOOP if already encrypted, or ERR_INIT if encryption fails.
+ * \param[in] Private Key object
+ * \return ERR_OK if encrypted, ERR_NOOP if already encrypted, or ERR_INIT if encryption fails.
*/
int lq_privatekey_lock(LQPrivKey *pk, const char *passphrase, size_t passphrase_len);
/**
- * @brief Decrypt private key in place.
+ * \brief Decrypt private key in place.
*
- * @param[in] Private Key object
- * @return ERR_OK if decrypted, ERR_NOOP if not encrypted, or ERR_INIT if decryption fails.
+ * \param[in] Private Key object
+ * \return ERR_OK if decrypted, ERR_NOOP if not encrypted, or ERR_INIT if decryption fails.
*/
int lq_privatekey_unlock(LQPrivKey *pk, const char *passphrase, size_t passphrase_len);
/**
- * @brief Sign digest data using a private key.
+ * \brief Sign digest data using a private key.
*
- * @param[in] Unencrypted private key to use for the signature.
- * @param[in] Message digest to sign.
- * @param[in] Length of message to sign.
- * @param[in] Salt data to use for the signature. Set to NULL if salt is not to be used. If not null, must be LQ_SALT_LEN long.
- * @return Signature object if signing was successful. Returns NULL if signature failed. It is the caller's responsiblity to free the signature.
- * @see lq_signature_free
+ * \param[in] Unencrypted private key to use for the signature.
+ * \param[in] Message digest to sign.
+ * \param[in] Length of message to sign.
+ * \param[in] Salt data to use for the signature. Set to NULL if salt is not to be used. If not null, must be LQ_SALT_LEN long.
+ * \return Signature object if signing was successful. Returns NULL if signature failed. It is the caller's responsiblity to free the signature.
+ * \see lq_signature_free
*/
LQSig* lq_privatekey_sign(LQPrivKey *pk, const char *msg, size_t msg_len, const char *salt);
/**
- * @brief Create a signature object from byte data.
+ * \brief Create a signature object from byte data.
*
- * @param[in] Signature byte data.
- * @param[in] Length of data.
- * @param[in] Public key used in signature. Can be NULL for recoverable signatures.
- * @return Signature object if parse was successful. Returns NULL if parsing failed. It is the caller's responsiblity to free the signature.
+ * \param[in] Signature byte data.
+ * \param[in] Length of data.
+ * \param[in] Public key used in signature. Can be NULL for recoverable signatures.
+ * \return Signature object if parse was successful. Returns NULL if parsing failed. It is the caller's responsiblity to free the signature.
*/
LQSig* lq_signature_from_bytes(const char *sig_data, size_t sig_len, LQPubKey *pubkey);
/**
- * @brief Get raw signature bytes
+ * \brief Get raw signature bytes
*
- * @param[in] Signature object.
- * @param[out] Pointer to start of data.
- * @return Length of signature. If 0, no signature data could be found.
+ * \param[in] Signature object.
+ * \param[out] Pointer to start of data.
+ * \return Length of signature. If 0, no signature data could be found.
*/
size_t lq_signature_bytes(LQSig *sig, char **out);
/**
- * @brief Verify a signature against a private key and message.
+ * \brief Verify a signature against a private key and message.
*
*/
int lq_signature_verify(LQSig *sig, const char *msg, size_t msg_len);
/**
- * @brief Free an allocated public key.
- * @param[in] Public key to free.
+ * \brief Free an allocated public key.
+ * \param[in] Public key to free.
*/
void lq_publickey_free(LQPubKey *pubk);
/**
- * @brief Free an allocated private key.
- * @param[in] Private key to free.
+ * \brief Free an allocated private key.
+ * \param[in] Private key to free.
*/
void lq_privatekey_free(LQPrivKey *pk);
/**
- * @brief Free an allocated signature object.
- * @param[in] Private key to free.
+ * \brief Free an allocated signature object.
+ * \param[in] Private key to free.
*/
void lq_signature_free(LQSig *sig);
/**
- * @brief Calculate digest over arbitrary data.
- * @param[in] Data to calculate digest over.
- * @param[in] Length of data.
- * @param[out] Output buffer. Must be allocated to at least LQ_DIGEST_LENGTH
- * @return ERR_OK on success.
+ * \brief Calculate digest over arbitrary data.
+ * \param[in] Data to calculate digest over.
+ * \param[in] Length of data.
+ * \param[out] Output buffer. Must be allocated to at least LQ_DIGEST_LENGTH
+ * \return ERR_OK on success.
*/
int lq_digest(const char *in, size_t in_len, char *out);
diff --git a/src/lq/store.h b/src/lq/store.h
@@ -45,4 +45,8 @@ 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.
};
+LQStore* lq_store_new(const char *spec);
+void lq_store_free(LQStore *store);
+
+
#endif // LIBQAEDA_STORE_H_
diff --git a/src/store/file.c b/src/store/file.c
@@ -133,6 +133,23 @@ struct lq_store_t LQFileContent = {
.free = lq_file_content_free,
};
+LQStore* lq_store_new(const char *spec) {
+ int l;
+ LQStore *store;
+
+ l = strlen(spec) + 1;
+ store = lq_alloc(sizeof(LQStore));
+ lq_cpy(store, &LQFileContent, sizeof(LQFileContent));
+ store->userdata = lq_alloc(l);
+ lq_cpy(store->userdata, spec, l);
+ return store;
+}
+
+void lq_store_free(LQStore *store) {
+ lq_free(store->userdata);
+ lq_free(store);
+}
+
//LQStore* lq_file_content_new(const char *dir) {
// char path[1024];
// LQStore *store;
diff --git a/src/store/mem.c b/src/store/mem.c
@@ -104,3 +104,15 @@ struct lq_store_t LQMemContent = {
.put = lq_mem_content_put,
.free = lq_mem_content_free,
};
+
+LQStore* lq_store_new(const char *spec) {
+ LQStore *store;
+
+ store = lq_alloc(sizeof(LQStore));
+ lq_cpy(store, &LQMemContent, sizeof(LQMemContent));
+ return store;
+}
+
+void lq_store_free(LQStore *store) {
+ lq_free(store);
+}
diff --git a/src/test/Makefile b/src/test/Makefile
@@ -23,11 +23,11 @@ build:
# $(CC) $(CFLAGS) test_msg.c -o test_msg_bin ../crypto/dummy.o ../mem/std.o ../store/dummy.o ../store/file.o ../io/std.o ../lq/msg.o $(LDFLAGS)
#$(CC) $(CFLAGS) test_cert.c -o test_cert_bin ../crypto/dummy.o ../mem/std.o ../store/dummy.o ../store/file.o ../io/std.o ../lq/msg.o ../lq/cert.o $(LDFLAGS)
#$(CC) $(CFLAGS) test_trust.c -o test_trust_bin ../crypto/dummy.o ../mem/std.o ../store/mem.o ../lq/trust.o -lhashmap $(LDFLAGS)
- $(CC) $(CFLAGS) test_crypto.c -o test_crypto_bin ../crypto/gcrypt.o ../debug.o ../mem/std.o ../lq/config.o $(LDFLAGS) -lgcrypt
- $(CC) $(CFLAGS) test_msg.c -o test_msg_bin ../crypto/gcrypt.o ../debug.o ../mem/std.o ../lq/config.o ../store/dummy.o ../store/file.o ../io/std.o ../lq/msg.o $(LDFLAGS)
- $(CC) $(CFLAGS) test_cert.c -o test_cert_bin ../crypto/gcrypt.o ../debug.o ../lq/config.o ../mem/std.o ../store/dummy.o ../store/file.o ../io/std.o ../lq/msg.o ../lq/cert.o $(LDFLAGS)
- $(CC) $(CFLAGS) test_trust.c -o test_trust_bin ../crypto/gcrypt.o ../debug.o ../lq/config.o ../mem/std.o ../store/mem.o ../lq/trust.o -lhashmap $(LDFLAGS)
- $(CC) $(CFLAGS) test_store.c -o test_store_bin ../crypto/gcrypt.o ../debug.o ../lq/config.o ../mem/std.o ../store/file.o ../io/std.o -lhashmap $(LDFLAGS)
+ $(CC) $(CFLAGS) test_crypto.c -o test_crypto_bin ../store/file.o ../io/std.o ../crypto/gcrypt.o ../debug.o ../mem/std.o ../lq/config.o $(LDFLAGS) -lgcrypt
+ $(CC) $(CFLAGS) test_msg.c -o test_msg_bin ../store/file.o ../io/std.o ../crypto/gcrypt.o ../debug.o ../mem/std.o ../lq/config.o ../store/dummy.o ../lq/msg.o $(LDFLAGS)
+ $(CC) $(CFLAGS) test_cert.c -o test_cert_bin ../store/file.o ../io/std.o ../crypto/gcrypt.o ../debug.o ../lq/config.o ../mem/std.o ../store/dummy.o ../lq/msg.o ../lq/cert.o $(LDFLAGS)
+ $(CC) $(CFLAGS) test_trust.c -o test_trust_bin ../mem/std.o ../store/mem.o ../crypto/gcrypt.o ../debug.o ../lq/config.o ../lq/trust.o -lhashmap $(LDFLAGS)
+ $(CC) $(CFLAGS) test_store.c -o test_store_bin ../store/file.o ../io/std.o ../crypto/gcrypt.o ../debug.o ../lq/config.o ../mem/std.o -lhashmap $(LDFLAGS)
clean:
rm -vf test_*_bin
diff --git a/src/test/test_msg.c b/src/test/test_msg.c
@@ -20,16 +20,17 @@ START_TEST(check_msg_symmetric) {
LQMsg *msg;
LQResolve resolve;
LQResolve resolve_dummy;
- LQStore store;
+ LQStore *store;
- lq_cpy(&store, &LQFileContent, sizeof(LQStore));
+ //lq_cpy(&store, &LQFileContent, sizeof(LQStore));
lq_cpy(path, "/tmp/lqstore_file_XXXXXX", 25);
- store.userdata = (void*)mktempdir(path);
- ck_assert_ptr_nonnull(store.userdata);
+ //store.userdata = (void*)mktempdir(path);
+ store = lq_store_new(mktempdir(path));
+ ck_assert_ptr_nonnull(store->userdata);
resolve_dummy.store = &LQDummyContent;
resolve_dummy.next = NULL;
- resolve.store = &store;
+ resolve.store = store;
resolve.next = &resolve_dummy;
msg = lq_msg_new(data, strlen(data) + 1);
msg->pubkey = lq_publickey_new(data);
@@ -45,6 +46,8 @@ START_TEST(check_msg_symmetric) {
lq_msg_free(msg);
resolve.store->free(resolve.store);
resolve_dummy.store->free(resolve_dummy.store);
+
+ lq_store_free(store);
}
END_TEST