libqaeda

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

commit 0b0759e1f402682a269c94c928237ee5984206ca
parent 645f54a19044620cd75a93cd454cd62ec24ae49e
Author: lash <dev@holbrook.no>
Date:   Tue, 25 Mar 2025 02:11:13 +0000

Add signature verify, but cert sig verify now fails in tests

Diffstat:
Msrc/crypto/gcrypt.c | 82++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/lq/crypto.h | 8+++++++-
Msrc/test/test_crypto.c | 31+++++++++++++++++++++++++++----
3 files changed, 107 insertions(+), 14 deletions(-)

diff --git a/src/crypto/gcrypt.c b/src/crypto/gcrypt.c @@ -42,9 +42,7 @@ int lq_crypto_init() { #ifdef RERR rerr_register(RERR_PFX_GPG, "crypto", _rerr); #endif - //char *p; - //size_t c; - char *v; + const char *v; if (gpg_version == NULL) { v = gcry_check_version(GPG_MIN_VERSION); @@ -271,7 +269,7 @@ int lq_privatekey_unlock(LQPrivKey *pk, const char *passphrase, size_t passphras // } //} -static int sign(struct gpg_store *gpg, char *data, size_t data_len, const char *salt) { +static int sign(struct gpg_store *gpg, const char *data, size_t data_len, const char *salt) { int r; size_t c; char *p; @@ -327,21 +325,20 @@ static int sign(struct gpg_store *gpg, char *data, size_t data_len, const char * return 0; } -LQSig* lq_privatekey_sign(LQPrivKey *pk, const char *msg, size_t msg_len, const char *salt) { +LQSig* lq_privatekey_sign(LQPrivKey *pk, const char *data, size_t data_len, const char *salt) { int r; struct gpg_store *gpg; LQSig *sig; + char digest[LQ_DIGEST_LEN]; if ((pk->key_state & LQ_KEY_LOCK) > 0) { return NULL; } - if (msg_len != LQ_DIGEST_LEN) { - return NULL; - } + lq_digest(data, strlen(data), (char*)digest); gpg = (struct gpg_store*)pk->impl; - r = sign(gpg, msg, msg_len, salt); + r = sign(gpg, digest, LQ_DIGEST_LEN, salt); if (r != ERR_OK) { return NULL; } @@ -365,6 +362,72 @@ size_t lq_signature_bytes(LQSig *sig, char **out) { return LQ_SIGN_LEN; } +int lq_signature_verify(LQSig *sig, const char *data, size_t data_len) { + int r; + size_t c; + gcry_mpi_t sig_r; + gcry_mpi_t sig_s; + gcry_error_t err; + gcry_sexp_t sigx; + gcry_sexp_t msgx; + gcry_sexp_t pubkey; + struct gpg_store *gpg; + char digest[LQ_DIGEST_LEN]; + + if (sig->pubkey == NULL) { + return ERR_NOENT; + } + + gpg = (struct gpg_store*)sig->pubkey->impl; + c = 0; + err = gcry_sexp_build(&pubkey, &c, "(key-data(public-key(ecc(curve Ed25519)(q %b))))", LQ_PUBKEY_LEN, gpg->public_key); + if (err != GPG_ERR_NO_ERROR) { + return ERR_CRYPTO; + } + + c = 0; + err = gcry_mpi_scan(&sig_r, GCRYMPI_FMT_STD, sig->impl, LQ_POINT_LEN, &c); + if (err != GPG_ERR_NO_ERROR) { + return ERR_CRYPTO; + } + if (c != 32) { + return ERR_CRYPTO; + } + + c = 0; + err = gcry_mpi_scan(&sig_s, GCRYMPI_FMT_STD, sig->impl + LQ_POINT_LEN, LQ_POINT_LEN, &c); + if (err != GPG_ERR_NO_ERROR) { + return ERR_CRYPTO; + } + if (c != 32) { + return ERR_CRYPTO; + } + + c = 0; + err = gcry_sexp_build(&sigx, &c, "(sig-val(eddsa(r %m)(s %m)))", sig_r, sig_s); + if (err != GPG_ERR_NO_ERROR) { + return ERR_CRYPTO; + } + + r = calculate_digest_algo(data, data_len, digest, GCRY_MD_SHA512); + if (r) { + return ERR_CRYPTO; + } + + c = 0; + err = gcry_sexp_build(&msgx, &c, "(data(flags eddsa)(hash-algo sha512)(value %b))", LQ_DIGEST_LEN, digest); + if (err != GPG_ERR_NO_ERROR) { + return ERR_CRYPTO; + } + + err = gcry_pk_verify(sigx, msgx, pubkey); + if (err != GPG_ERR_NO_ERROR) { + return ERR_ENCODING; + } + + return ERR_OK; +} + void lq_privatekey_free(LQPrivKey *pk) { lq_free(pk->impl); lq_free(pk); @@ -413,6 +476,7 @@ LQPubKey* lq_publickey_new(const char *full) { if (e != GPG_ERR_NO_ERROR) { return NULL; } + lq_cpy(gpg->public_key, full, LQ_PUBKEY_LEN); r = (char*)gcry_pk_get_keygrip(gpg->k, (unsigned char*)gpg->fingerprint); if (r == NULL) { diff --git a/src/lq/crypto.h b/src/lq/crypto.h @@ -4,7 +4,7 @@ #include <stddef.h> #ifndef LQ_DIGEST_LEN -#define LQ_DIGEST_LEN 32 +#define LQ_DIGEST_LEN 64 #endif #ifndef LQ_PUBKEY_LEN @@ -209,6 +209,12 @@ LQSig* lq_signature_from_bytes(const char *sig_data, size_t sig_len, LQPubKey *p size_t lq_signature_bytes(LQSig *sig, char **out); /** + * @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. */ diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c @@ -49,7 +49,7 @@ START_TEST(check_privatekey) { r = lq_crypto_init(); ck_assert_int_eq(r, 0); - pk = lq_privatekey_new(privkeydata, 32, NULL, 0); + pk = lq_privatekey_new(privkeydata, LQ_PRIVKEY_LEN, NULL, 0); ck_assert_ptr_nonnull(pk); lq_privatekey_free(pk); } @@ -62,7 +62,7 @@ START_TEST(check_publickey) { char *keydata; char *keydata_manual; - pk = lq_privatekey_new(privkeydata, 32, passphrase, 32); + pk = lq_privatekey_new(privkeydata, LQ_PRIVKEY_LEN, passphrase, 32); pubk = lq_publickey_from_privatekey(pk); lq_publickey_bytes(pubk, &keydata); pubk_manual = lq_publickey_new(keydata); @@ -82,8 +82,7 @@ START_TEST(check_signature) { char *sigdata; pk = lq_privatekey_new(privkeydata, 32, passphrase, 32); - lq_digest(data, strlen(data), (char*)digest); - sig = lq_privatekey_sign(pk, digest, 32, salt); + sig = lq_privatekey_sign(pk, data, strlen(data), salt); ck_assert_ptr_null(sig); r = lq_privatekey_unlock(pk, passphrase, 32); @@ -100,6 +99,29 @@ START_TEST(check_signature) { } END_TEST +START_TEST(check_verify) { + char r; + LQPrivKey *pk; + LQSig *sig; + char *sigdata; + + pk = lq_privatekey_new(privkeydata, LQ_PRIVKEY_LEN, passphrase, 32); + sig = lq_privatekey_sign(pk, data, strlen(data), salt); + ck_assert_ptr_null(sig); + + r = lq_privatekey_unlock(pk, passphrase, 32); + ck_assert_int_eq(r, 0); + + sig = lq_privatekey_sign(pk, data, strlen(data), salt); + ck_assert_ptr_nonnull(sig); + + r = lq_signature_verify(sig, data, strlen(data)); + + lq_signature_free(sig); + lq_privatekey_free(pk); +} +END_TEST + Suite * common_suite(void) { Suite *s; TCase *tc; @@ -110,6 +132,7 @@ Suite * common_suite(void) { tcase_add_test(tc, check_privatekey); tcase_add_test(tc, check_publickey); tcase_add_test(tc, check_signature); + tcase_add_test(tc, check_verify); suite_add_tcase(s, tc); return s;