From da9ab66d2ea379a6fbb5e38c7206070b44d571fa Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 6 May 2015 17:05:24 +0200 Subject: simplify PG logic by having libtalerpq handle RSA signature/key encoding --- src/include/taler_crypto_lib.h | 10 ++-- src/include/taler_pq_lib.h | 54 ++++++++++++++++++++- src/mintdb/plugin_mintdb_postgres.c | 74 ++++------------------------- src/pq/db_pq.c | 94 ++++++++++++++++++++++++++++++++----- 4 files changed, 147 insertions(+), 85 deletions(-) (limited to 'src') diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 9ba13a6eb..0ab05f5d0 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -244,8 +244,6 @@ struct TALER_CoinSpendSignatureP GNUNET_NETWORK_STRUCT_END - - /** * @brief Type of blinding keys for Taler. */ @@ -427,7 +425,7 @@ struct TALER_RefreshLinkEncrypted * Decrypt the shared @a secret from the information in the * encrypted link secret @e secret_enc using the transfer * private key and the coin's public key. - * + * * @param secret_enc encrypted link secret * @param transfer_priv transfer private key * @param coin_pub coin public key @@ -445,7 +443,7 @@ TALER_link_decrypt_secret (const struct TALER_EncryptedLinkSecretP *secret_enc, * Decrypt the shared @a secret from the information in the * encrypted link secret @e secret_enc using the transfer * public key and the coin's private key. - * + * * @param secret_enc encrypted link secret * @param transfer_pub transfer public key * @param coin_priv coin private key @@ -462,8 +460,8 @@ TALER_link_decrypt_secret2 (const struct TALER_EncryptedLinkSecretP *secret_enc, /** * Encrypt the shared @a secret to generate the encrypted link secret. * Also creates the transfer key. - * - * @param secret link secret to encrypt + * + * @param secret link secret to encrypt * @param coin_pub coin public key * @param transfer_priv[out] set to transfer private key * @param transfer_pub[out] set to transfer public key diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index 6bf5c0c82..e32dea54a 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -49,9 +49,28 @@ enum TALER_PQ_QueryFormat /** * We have a currency amount (with endianess conversion). - * Data points to a `struct TALER_AmountNBO`, size is not used. + * Data points to a `struct TALER_AmountNBO`, size is only used to check. */ - TALER_PQ_QF_AMOUNT_NBO + TALER_PQ_QF_AMOUNT_NBO, + + /** + * We have a currency amount (with endianess conversion). + * Data points to a `struct TALER_Amount`, size is only used to check. + */ + TALER_PQ_QF_AMOUNT, + + /** + * We have an RSA public key. + * Data points to a `struct GNUNET_CRYPTO_rsa_PublicKey`, size is not used. + */ + TALER_PQ_QF_RSA_PUBLIC_KEY, + + /** + * We have an RSA signature. + * Data points to a `struct GNUNET_CRYPTO_rsa_Signature`, size is not used. + */ + TALER_PQ_QF_RSA_SIGNATURE + }; @@ -113,6 +132,37 @@ struct TALER_PQ_QueryParam #define TALER_PQ_QUERY_PARAM_AMOUNT_NBO(x) { TALER_PQ_QF_AMOUNT_NBO, &(x), sizeof (x) } +/** + * Generate query parameter for a currency, consisting of the three + * components "value", "fraction" and "currency" in this order. The + * types must be a 64-bit integer, 32-bit integer and a + * TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively. + * + * @param x pointer to the query parameter to pass, must be + * a variable of type `struct TALER_Amount`. + */ +#define TALER_PQ_QUERY_PARAM_AMOUNT(x) { TALER_PQ_QF_AMOUNT, &(x), sizeof (x) } + + +/** + * Generate query parameter for an RSA public key. The + * database must contain a BLOB type in the respective position. + * + * @param x the query parameter to pass, must be + * a variable of type `struct GNUNET_CRYPTO_rsa_PublicKey *`. + */ +#define TALER_PQ_QUERY_PARAM_RSA_PUBLIC_KEY(x) { TALER_PQ_QF_RSA_PUBLIC_KEY, (x),0 } + +/** + * Generate query parameter for an RSA signature. The + * database must contain a BLOB type in the respective position. + * + * @param x the query parameter to pass, must be + * a variable of type `struct GNUNET_CRYPTO_rsa_Signature *`. + */ +#define TALER_PQ_QUERY_PARAM_RSA_SIGNATURE(x) { TALER_PQ_QF_RSA_SIGNATURE, (x),0 } + + /** * Different formats of results that can be extracted. */ diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index d5d18542a..9daa945de 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -825,23 +825,13 @@ postgres_insert_denomination (void *cls, const struct TALER_MINTDB_DenominationKeyIssueInformation *dki) { PGresult *result; - char *pub_enc; const struct TALER_DenominationKeyValidityPS *issue; - size_t pub_enc_size; int ret; ret = GNUNET_SYSERR; - pub_enc = NULL; issue = &dki->issue; - pub_enc_size = GNUNET_CRYPTO_rsa_public_key_encode (dki->denom_pub.rsa_public_key, - &pub_enc); - if (NULL == pub_enc) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR_SIZED (pub_enc, pub_enc_size - 1), + TALER_PQ_QUERY_PARAM_RSA_PUBLIC_KEY (dki->denom_pub.rsa_public_key), TALER_PQ_QUERY_PARAM_PTR (&issue->start.abs_value_us__), TALER_PQ_QUERY_PARAM_PTR (&issue->expire_withdraw.abs_value_us__), TALER_PQ_QUERY_PARAM_PTR (&issue->expire_spend.abs_value_us__), @@ -854,7 +844,6 @@ postgres_insert_denomination (void *cls, result = TALER_PQ_exec_prepared (session->conn, "insert_denomination", params); - GNUNET_free (pub_enc); if (PGRES_COMMAND_OK != PQresultStatus (result)) { BREAK_DB_ERR (result); @@ -1212,32 +1201,19 @@ postgres_insert_collectable_blindcoin (void *cls, { PGresult *result; struct TALER_MINTDB_Reserve reserve; - char *denom_pub_enc = NULL; - char *denom_sig_enc = NULL; - size_t denom_pub_enc_size; - size_t denom_sig_enc_size; - int ret; - - ret = GNUNET_SYSERR; - denom_pub_enc_size = - GNUNET_CRYPTO_rsa_public_key_encode (collectable->denom_pub.rsa_public_key, - &denom_pub_enc); - denom_sig_enc_size = - GNUNET_CRYPTO_rsa_signature_encode (collectable->sig.rsa_signature, - &denom_sig_enc); + int ret = GNUNET_SYSERR; struct TALER_PQ_QueryParam params[] = { TALER_PQ_QUERY_PARAM_PTR (h_blind), - TALER_PQ_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size - 1), - TALER_PQ_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size - 1), /* DB doesn't like the trailing \0 */ + TALER_PQ_QUERY_PARAM_RSA_PUBLIC_KEY (collectable->denom_pub.rsa_public_key), + TALER_PQ_QUERY_PARAM_RSA_SIGNATURE (collectable->sig.rsa_signature), TALER_PQ_QUERY_PARAM_PTR (&collectable->reserve_pub), TALER_PQ_QUERY_PARAM_PTR (&collectable->reserve_sig), TALER_PQ_QUERY_PARAM_END }; + if (GNUNET_OK != postgres_start (cls, session)) { - GNUNET_free_non_null (denom_pub_enc); - GNUNET_free_non_null (denom_sig_enc); return GNUNET_SYSERR; } result = TALER_PQ_exec_prepared (session->conn, @@ -1274,8 +1250,6 @@ postgres_insert_collectable_blindcoin (void *cls, session); cleanup: PQclear (result); - GNUNET_free_non_null (denom_pub_enc); - GNUNET_free_non_null (denom_sig_enc); return ret; } @@ -1506,29 +1480,19 @@ postgres_insert_deposit (void *cls, struct TALER_MINTDB_Session *session, const struct TALER_MINTDB_Deposit *deposit) { - char *denom_pub_enc; - char *denom_sig_enc; char *json_wire_enc; PGresult *result; struct TALER_AmountNBO amount_nbo; - size_t denom_pub_enc_size; - size_t denom_sig_enc_size; int ret; ret = GNUNET_SYSERR; - denom_pub_enc_size = - GNUNET_CRYPTO_rsa_public_key_encode (deposit->coin.denom_pub.rsa_public_key, - &denom_pub_enc); - denom_sig_enc_size = - GNUNET_CRYPTO_rsa_signature_encode (deposit->coin.denom_sig.rsa_signature, - &denom_sig_enc); json_wire_enc = json_dumps (deposit->wire, JSON_COMPACT); TALER_amount_hton (&amount_nbo, &deposit->amount_with_fee); struct TALER_PQ_QueryParam params[]= { TALER_PQ_QUERY_PARAM_PTR (&deposit->coin.coin_pub), - TALER_PQ_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size -1), - TALER_PQ_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size -1), + TALER_PQ_QUERY_PARAM_RSA_PUBLIC_KEY (deposit->coin.denom_pub.rsa_public_key), + TALER_PQ_QUERY_PARAM_RSA_SIGNATURE (deposit->coin.denom_sig.rsa_signature), TALER_PQ_QUERY_PARAM_PTR (&deposit->transaction_id), TALER_PQ_QUERY_PARAM_AMOUNT_NBO (amount_nbo), TALER_PQ_QUERY_PARAM_PTR (&deposit->merchant_pub), @@ -1549,8 +1513,6 @@ postgres_insert_deposit (void *cls, cleanup: PQclear (result); - GNUNET_free_non_null (denom_pub_enc); - GNUNET_free_non_null (denom_sig_enc); GNUNET_free_non_null (json_wire_enc); return ret; } @@ -1692,25 +1654,20 @@ postgres_insert_refresh_melt (void *cls, { // FIXME: check logic! uint16_t oldcoin_index_nbo = htons (oldcoin_index); - char *buf; - size_t buf_size; PGresult *result; - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (melt->coin.denom_pub.rsa_public_key, - &buf); { struct TALER_PQ_QueryParam params[] = { TALER_PQ_QUERY_PARAM_PTR(&melt->session_hash), TALER_PQ_QUERY_PARAM_PTR(&oldcoin_index_nbo), TALER_PQ_QUERY_PARAM_PTR(&melt->coin.coin_pub), - TALER_PQ_QUERY_PARAM_PTR_SIZED(buf, buf_size), + TALER_PQ_QUERY_PARAM_RSA_PUBLIC_KEY(melt->coin.denom_pub.rsa_public_key), TALER_PQ_QUERY_PARAM_END }; result = TALER_PQ_exec_prepared (session->conn, "insert_refresh_melt", params); } - GNUNET_free (buf); if (PGRES_COMMAND_OK != PQresultStatus (result)) { BREAK_DB_ERR (result); @@ -1801,25 +1758,19 @@ postgres_insert_refresh_order (void *cls, { // FIXME: check logic: was written for just one COIN! uint16_t newcoin_index_nbo = htons (num_newcoins); - char *buf; - size_t buf_size; PGresult *result; - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pubs->rsa_public_key, - &buf); - { struct TALER_PQ_QueryParam params[] = { TALER_PQ_QUERY_PARAM_PTR (&newcoin_index_nbo), TALER_PQ_QUERY_PARAM_PTR (session_hash), - TALER_PQ_QUERY_PARAM_PTR_SIZED (buf, buf_size), + TALER_PQ_QUERY_PARAM_RSA_PUBLIC_KEY (denom_pubs->rsa_public_key), TALER_PQ_QUERY_PARAM_END }; result = TALER_PQ_exec_prepared (session->conn, "insert_refresh_order", params); } - GNUNET_free (buf); if (PGRES_COMMAND_OK != PQresultStatus (result)) { BREAK_DB_ERR (result); @@ -2228,24 +2179,19 @@ postgres_insert_refresh_collectable (void *cls, { // FIXME: check logic! uint16_t newcoin_index_nbo = htons (newcoin_index); - char *buf; - size_t buf_size; PGresult *result; - buf_size = GNUNET_CRYPTO_rsa_signature_encode (ev_sig->rsa_signature, - &buf); { struct TALER_PQ_QueryParam params[] = { TALER_PQ_QUERY_PARAM_PTR(session_hash), TALER_PQ_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_PQ_QUERY_PARAM_PTR_SIZED(buf, buf_size), + TALER_PQ_QUERY_PARAM_RSA_SIGNATURE(ev_sig->rsa_signature), TALER_PQ_QUERY_PARAM_END }; result = TALER_PQ_exec_prepared (session->conn, "insert_refresh_collectable", params); } - GNUNET_free (buf); if (PGRES_COMMAND_OK != PQresultStatus (result)) { BREAK_DB_ERR (result); diff --git a/src/pq/db_pq.c b/src/pq/db_pq.c index 320cf9fdf..f0afe697b 100644 --- a/src/pq/db_pq.c +++ b/src/pq/db_pq.c @@ -50,13 +50,18 @@ TALER_PQ_exec_prepared (PGconn *db_conn, switch (x->format) { - case TALER_PQ_RF_FIXED_BLOB: - case TALER_PQ_RF_VARSIZE_BLOB: + case TALER_PQ_QF_FIXED_BLOB: + case TALER_PQ_QF_VARSIZE_BLOB: len++; break; - case TALER_PQ_RF_AMOUNT_NBO: + case TALER_PQ_QF_AMOUNT_NBO: + case TALER_PQ_QF_AMOUNT: len += 3; break; + case TALER_PQ_QF_RSA_PUBLIC_KEY: + case TALER_PQ_QF_RSA_SIGNATURE: + len++; + break; default: /* format not supported */ GNUNET_assert (0); @@ -66,27 +71,34 @@ TALER_PQ_exec_prepared (PGconn *db_conn, /* new scope to allow stack allocation without alloca */ { + /* Scratch buffer for temporary storage */ + void *scratch[len]; + /* Parameter array we are building for the query */ void *param_values[len]; int param_lengths[len]; int param_formats[len]; unsigned int off; + /* How many entries in the scratch buffer are in use? */ + unsigned int soff; + PGresult *res; i = 0; off = 0; + soff = 0; while (TALER_PQ_QF_END != params[i].format) { const struct TALER_PQ_QueryParam *x = ¶ms[i]; switch (x->format) { - case TALER_PQ_RF_FIXED_BLOB: - case TALER_PQ_RF_VARSIZE_BLOB: + case TALER_PQ_QF_FIXED_BLOB: + case TALER_PQ_QF_VARSIZE_BLOB: param_values[off] = (void *) x->data; param_lengths[off] = x->size; param_formats[off] = 1; off++; break; - case TALER_PQ_RF_AMOUNT_NBO: + case TALER_PQ_QF_AMOUNT_NBO: { const struct TALER_Amount *amount = x->data; @@ -104,6 +116,59 @@ TALER_PQ_exec_prepared (PGconn *db_conn, off++; } break; + case TALER_PQ_QF_AMOUNT: + { + const struct TALER_Amount *amount_hbo = x->data; + struct TALER_AmountNBO *amount; + + amount = GNUNET_new (struct TALER_AmountNBO); + scratch[soff++] = amount; + TALER_amount_hton (amount, + amount_hbo); + param_values[off] = (void *) &amount->value; + param_lengths[off] = sizeof (amount->value); + param_formats[off] = 1; + off++; + param_values[off] = (void *) &amount->fraction; + param_lengths[off] = sizeof (amount->fraction); + param_formats[off] = 1; + off++; + param_values[off] = (void *) amount->currency; + param_lengths[off] = strlen (amount->currency) + 1; + param_formats[off] = 1; + off++; + } + break; + case TALER_PQ_QF_RSA_PUBLIC_KEY: + { + const struct GNUNET_CRYPTO_rsa_PublicKey *rsa = x->data; + char *buf; + size_t buf_size; + + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rsa, + &buf); + scratch[soff++] = buf; + param_values[off] = (void *) buf; + param_lengths[off] = buf_size - 1; /* DB doesn't like the trailing \0 */ + param_formats[off] = 1; + off++; + } + break; + case TALER_PQ_QF_RSA_SIGNATURE: + { + const struct GNUNET_CRYPTO_rsa_Signature *sig = x->data; + char *buf; + size_t buf_size; + + buf_size = GNUNET_CRYPTO_rsa_signature_encode (sig, + &buf); + scratch[soff++] = buf; + param_values[off] = (void *) buf; + param_lengths[off] = buf_size - 1; /* DB doesn't like the trailing \0 */ + param_formats[off] = 1; + off++; + } + break; default: /* format not supported */ GNUNET_assert (0); @@ -111,13 +176,16 @@ TALER_PQ_exec_prepared (PGconn *db_conn, } } GNUNET_assert (off == len); - return PQexecPrepared (db_conn, - name, - len, - (const char **) param_values, - param_lengths, - param_formats, - 1); + res = PQexecPrepared (db_conn, + name, + len, + (const char **) param_values, + param_lengths, + param_formats, + 1); + for (off = 0; off < soff; off++) + GNUNET_free (scratch[soff]); + return res; } } -- cgit v1.2.3