diff options
-rw-r--r-- | src/include/Makefile.am | 1 | ||||
-rw-r--r-- | src/include/taler_rsa.h | 360 | ||||
-rw-r--r-- | src/include/taler_signatures.h | 31 | ||||
-rw-r--r-- | src/mint/mint.h | 58 | ||||
-rw-r--r-- | src/mint/mint_common.c | 18 | ||||
-rw-r--r-- | src/mint/mint_db.c | 114 | ||||
-rw-r--r-- | src/mint/mint_db.h | 56 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd.c | 1 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 191 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.h | 15 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_deposit.c | 1 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_keys.c | 31 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_keys.h | 10 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_parsing.c | 68 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_parsing.h | 27 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_refresh.c | 99 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.c | 22 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.h | 2 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_withdraw.c | 62 | ||||
-rw-r--r-- | src/mint/taler-mint-keyup.c | 27 | ||||
-rw-r--r-- | src/mint/test_mint_common.c | 26 | ||||
-rw-r--r-- | src/util/Makefile.am | 3 | ||||
-rw-r--r-- | src/util/rsa.c | 928 |
23 files changed, 568 insertions, 1583 deletions
diff --git a/src/include/Makefile.am b/src/include/Makefile.am index ebdf8561d..70dee2186 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -5,6 +5,5 @@ talerinclude_HEADERS = \ taler_db_lib.h \ taler_json_lib.h \ taler_mint_service.h \ - taler_rsa.h \ taler_signatures.h \ taler_util.h diff --git a/src/include/taler_rsa.h b/src/include/taler_rsa.h deleted file mode 100644 index 1d263ae09..000000000 --- a/src/include/taler_rsa.h +++ /dev/null @@ -1,360 +0,0 @@ -/* NOTE: this is obsolete logic, we should migrate to the - GNUNET_CRYPTO_rsa-API as soon as possible */ - -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> -*/ - -/** - * @file include/taler_rsa.h - * @brief RSA key management utilities. Some code is taken from gnunet-0.9.5a - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - * - * Authors of the gnunet code: - * Christian Grothoff - * Krista Bennett - * Gerd Knorr <kraxel@bytesex.org> - * Ioana Patrascu - * Tzvetan Horozov - */ - -#ifndef TALER_RSA_H -#define TALER_RSA_H - -#include <gnunet/gnunet_common.h> -#include <gnunet/gnunet_crypto_lib.h> - -/** - * Length of an RSA KEY (n,e,len), 2048 bit (=256 octests) key n, 2 byte e - */ -#define TALER_RSA_KEY_LENGTH 258 - -/** - * @brief Length of RSA encrypted data (2048 bit) - * - * We currently do not handle encryption of data - * that can not be done in a single call to the - * RSA methods (read: large chunks of data). - * We should never need that, as we can use - * the GNUNET_CRYPTO_hash for larger pieces of data for signing, - * and for encryption, we only need to encode sessionkeys! - */ -#define TALER_RSA_DATA_ENCODING_LENGTH 256 - -/** - * The private information of an RSA key pair. - */ -struct TALER_RSA_PrivateKey; - - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * GNUnet mandates a certain format for the encoding - * of private RSA key information that is provided - * by the RSA implementations. This format is used - * to serialize a private RSA key (typically when - * writing it to disk). - */ -struct TALER_RSA_PrivateKeyBinaryEncoded -{ - /** - * Total size of the structure, in bytes, in big-endian! - */ - uint16_t len GNUNET_PACKED; - uint16_t sizen GNUNET_PACKED; /* in big-endian! */ - uint16_t sizee GNUNET_PACKED; /* in big-endian! */ - uint16_t sized GNUNET_PACKED; /* in big-endian! */ - uint16_t sizep GNUNET_PACKED; /* in big-endian! */ - uint16_t sizeq GNUNET_PACKED; /* in big-endian! */ - uint16_t sizedmp1 GNUNET_PACKED; /* in big-endian! */ - uint16_t sizedmq1 GNUNET_PACKED; /* in big-endian! */ - /* followed by the actual values */ -}; -GNUNET_NETWORK_STRUCT_END - - -/** - * @brief an RSA signature - */ -struct TALER_RSA_Signature -{ - unsigned char sig[TALER_RSA_DATA_ENCODING_LENGTH]; -}; - -GNUNET_NETWORK_STRUCT_BEGIN -/** - * @brief header of what an RSA signature signs - * this must be followed by "size - 8" bytes of - * the actual signed data - */ -struct TALER_RSA_SignaturePurpose -{ - /** - * How many bytes does this signature sign? - * (including this purpose header); in network - * byte order (!). - */ - uint32_t size GNUNET_PACKED; - - /** - * What does this signature vouch for? This - * must contain a GNUNET_SIGNATURE_PURPOSE_XXX - * constant (from gnunet_signatures.h). In - * network byte order! - */ - uint32_t purpose GNUNET_PACKED; - -}; - - -struct TALER_RSA_BlindedSignaturePurpose -{ - unsigned char data[TALER_RSA_DATA_ENCODING_LENGTH]; -}; - - -/** - * @brief A public key. - */ -struct TALER_RSA_PublicKeyBinaryEncoded -{ - /** - * In big-endian, must be GNUNET_CRYPTO_RSA_KEY_LENGTH+4 - */ - uint16_t len GNUNET_PACKED; - - /** - * Size of n in key; in big-endian! - */ - uint16_t sizen GNUNET_PACKED; - - /** - * The key itself, contains n followed by e. - */ - unsigned char key[TALER_RSA_KEY_LENGTH]; - - /** - * Padding (must be 0) - */ - uint16_t padding GNUNET_PACKED; -}; - -GNUNET_NETWORK_STRUCT_END - -/** - * Create a new private key. Caller must free return value. - * - * @return fresh private key - */ -struct TALER_RSA_PrivateKey * -TALER_RSA_key_create (); - - -/** - * Free memory occupied by the private key. - * - * @param key pointer to the memory to free - */ -void -TALER_RSA_key_free (struct TALER_RSA_PrivateKey *key); - - -/** - * Encode the private key in a format suitable for - * storing it into a file. - * @return encoding of the private key - */ -struct TALER_RSA_PrivateKeyBinaryEncoded * -TALER_RSA_encode_key (const struct TALER_RSA_PrivateKey *hostkey); - - -/** - * Extract the public key of the given private key. - * - * @param priv the private key - * @param pub where to write the public key - */ -void -TALER_RSA_key_get_public (const struct TALER_RSA_PrivateKey *priv, - struct TALER_RSA_PublicKeyBinaryEncoded *pub); - - -/** - * Decode the private key from the data-format back - * to the "normal", internal format. - * - * @param buf the buffer where the private key data is stored - * @param len the length of the data in 'buffer' - * @return NULL on error - */ -struct TALER_RSA_PrivateKey * -TALER_RSA_decode_key (const char *buf, uint16_t len); - - -/** - * Convert a public key to a string. - * - * @param pub key to convert - * @return string representing 'pub' - */ -char * -TALER_RSA_public_key_to_string (const struct TALER_RSA_PublicKeyBinaryEncoded *pub); - - -/** - * Convert a string representing a public key to a public key. - * - * @param enc encoded public key - * @param enclen number of bytes in enc (without 0-terminator) - * @param pub where to store the public key - * @return GNUNET_OK on success - */ -int -TALER_RSA_public_key_from_string (const char *enc, - size_t enclen, - struct TALER_RSA_PublicKeyBinaryEncoded *pub); - - -/** - * Sign a given block.h - * - * @param key private key to use for the signing - * @param msg the message - * @param size the size of the message - * @param sig where to write the signature - * @return GNUNET_SYSERR on error, GNUNET_OK on success - */ -int -TALER_RSA_sign (const struct TALER_RSA_PrivateKey *key, - const void *msg, - size_t size, - struct TALER_RSA_Signature *sig); - - -/** - * Verify signature with the given hash. - * - * @param hash the hash code to verify against the signature - * @param sig signature that is being validated - * @param publicKey public key of the signer - * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid - */ -int -TALER_RSA_hash_verify (const struct GNUNET_HashCode *hash, - const struct TALER_RSA_Signature *sig, - const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey); - - -/** - * Verify signature on the given message - * - * @param msg the message - * @param size the size of the message - * @param sig signature that is being validated - * @param publicKey public key of the signer - * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid - */ -int -TALER_RSA_verify (const void *msg, size_t size, - const struct TALER_RSA_Signature *sig, - const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey); - -/** - * Key used to blind a message - */ -struct TALER_RSA_BlindingKey; - -/** - * Create a blinding key - * - * @return the newly created blinding key - */ -struct TALER_RSA_BlindingKey * -TALER_RSA_blinding_key_create (); - - -/** - * Destroy a blinding key - * - * @param bkey the blinding key to destroy - */ -void -TALER_RSA_blinding_key_destroy (struct TALER_RSA_BlindingKey *bkey); - - -/** - * Binary encoding for TALER_RSA_BlindingKey - */ -struct TALER_RSA_BlindingKeyBinaryEncoded -{ - unsigned char data[TALER_RSA_DATA_ENCODING_LENGTH]; -}; - - -/** - * Encode a blinding key - * - * @param bkey the blinding key to encode - * @param bkey_enc where to store the encoded binary key - * @return #GNUNET_OK upon successful encoding; #GNUNET_SYSERR upon failure - */ -int -TALER_RSA_blinding_key_encode (struct TALER_RSA_BlindingKey *bkey, - struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc); - - -/** - * Decode a blinding key from its encoded form - * - * @param bkey_enc the encoded blinding key - * @return the decoded blinding key; NULL upon error - */ -struct TALER_RSA_BlindingKey * -TALER_RSA_blinding_key_decode (struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc); - - -/** - * Blinds the given message with the given blinding key - * - * @param msg the message - * @param size the size of the message - * @param bkey the blinding key - * @param pkey the public key of the signer - * @return the blinding signature purpose; NULL upon any error - */ -struct TALER_RSA_BlindedSignaturePurpose * -TALER_RSA_message_blind (const void *msg, size_t size, - struct TALER_RSA_BlindingKey *bkey, - struct TALER_RSA_PublicKeyBinaryEncoded *pkey); - - -/** - * Unblind a signature made on blinding signature purpose. The signature - * purpose should have been generated with TALER_RSA_message_blind() function. - * - * @param sig the signature made on the blinded signature purpose - * @param bkey the blinding key used to blind the signature purpose - * @param pkey the public key of the signer - * @return GNUNET_SYSERR upon error; GNUNET_OK upon success. - */ -int -TALER_RSA_unblind (struct TALER_RSA_Signature *sig, - struct TALER_RSA_BlindingKey *bkey, - struct TALER_RSA_PublicKeyBinaryEncoded *pkey); - -#endif /* TALER_RSA_H */ - -/* end of include/taler_rsa.h */ diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 238a915c1..90fa421c3 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -29,8 +29,6 @@ #define TALER_SIGNATURES_H #include <gnunet/gnunet_util_lib.h> -#include "taler_rsa.h" - /** * Purpose for signing public keys signed @@ -113,17 +111,12 @@ GNUNET_NETWORK_STRUCT_BEGIN - /** - * Request to withdraw coins from a reserve. + * Format used for to generate the signature on a request to withdraw + * coins from a reserve. */ struct TALER_WithdrawRequest { - /** - * Signature over the rest of the message - * by the withdraw public key. - */ - struct GNUNET_CRYPTO_EddsaSignature sig; /** * Purpose must be #TALER_SIGNATURE_WITHDRAW. @@ -131,24 +124,20 @@ struct TALER_WithdrawRequest struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** - * Reserve public key. + * Reserve public key (which reserve to withdraw from). This is + * the public key which must match the signature. */ struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; /** - * Denomination public key for the coin that is withdrawn. - * FIXME: change to the hash of the public key (so this - * is fixed-size). + * Hash of the denomination public key for the coin that is withdrawn. */ - struct TALER_RSA_PublicKeyBinaryEncoded denomination_pub; + struct GNUNET_HashCode h_denomination_pub; /** - * Purpose containing coin's blinded public key. - * - * FIXME: this should be explicitly a variable-size field with the - * (blinded) message to be signed by the Mint. + * Hash of the (blinded) message to be signed by the Mint. */ - struct TALER_RSA_BlindedSignaturePurpose coin_envelope; + struct GNUNET_HashCode h_coin_envelope; }; @@ -178,7 +167,8 @@ struct TALER_MINT_DenomKeyIssue struct GNUNET_TIME_AbsoluteNBO start; struct GNUNET_TIME_AbsoluteNBO expire_withdraw; struct GNUNET_TIME_AbsoluteNBO expire_spend; - struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; + // FIXME: does not work like this: + struct GNUNET_CRYPTO_rsa_PublicKey * denom_pub; struct TALER_AmountNBO value; struct TALER_AmountNBO fee_withdraw; struct TALER_AmountNBO fee_deposit; @@ -238,4 +228,3 @@ struct RefreshMeltConfirmSignRequestBody GNUNET_NETWORK_STRUCT_END #endif - diff --git a/src/mint/mint.h b/src/mint/mint.h index 39dda7d5f..1dc179340 100644 --- a/src/mint/mint.h +++ b/src/mint/mint.h @@ -29,7 +29,6 @@ #include <gnunet/gnunet_common.h> #include <libpq-fe.h> #include "taler_util.h" -#include "taler_rsa.h" #include "taler_signatures.h" #define DIR_SIGNKEYS "signkeys" @@ -55,7 +54,7 @@ struct TALER_MINT_DenomKeyIssuePriv * The private key of the denomination. Will be NULL if the private key is * not available. */ - struct TALER_RSA_PrivateKey *denom_priv; + struct GNUNET_CRYPTO_rsa_PrivateKey *denom_priv; struct TALER_MINT_DenomKeyIssue issue; }; @@ -75,26 +74,43 @@ struct TALER_CoinPublicInfo /* * The public key signifying the coin's denomination. */ - struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; /** * Signature over coin_pub by denom_pub. */ - struct TALER_RSA_Signature denom_sig; + struct GNUNET_CRYPTO_rsa_Signature *denom_sig; }; +/** + * Information we keep for a withdrawn coin to reproduce + * the /withdraw operation if needed, and to have proof + * that a reserve was drained by this amount. + */ +struct CollectableBlindcoin +{ + /** + * Our signature over the (blinded) coin. + */ + struct GNUNET_CRYPTO_rsa_Signature *sig; + /** + * Denomination key (which coin was generated). + */ + struct GNUNET_CRYPOT_rsa_PublicKey *denom_pub; - -struct CollectableBlindcoin -{ - struct TALER_RSA_BlindedSignaturePurpose ev; - struct TALER_RSA_Signature ev_sig; - struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; + /** + * Public key of the reserve that was drained. + */ struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + + /** + * Signature confirming the withdrawl, matching @e reserve_pub, + * @e denom_pub and @e h_blind. + */ struct GNUNET_CRYPTO_EddsaSignature reserve_sig; }; @@ -127,7 +143,7 @@ struct RefreshCommitLink struct LinkData { struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv; - struct TALER_RSA_BlindingKeyBinaryEncoded bkey_enc; + struct GNUNET_CRYPTO_rsa_BlindingKey *bkey_enc; }; @@ -149,7 +165,17 @@ GNUNET_NETWORK_STRUCT_END struct RefreshCommitCoin { struct GNUNET_CRYPTO_EddsaPublicKey session_pub; - struct TALER_RSA_BlindedSignaturePurpose coin_ev; + + /** + * Blinded message to be signed (in envelope). + */ + char *coin_ev; + + /** + * Number of bytes in @e coin_ev. + */ + size_t coin_ev_size; + uint16_t cnc_index; uint16_t newcoin_index; char link_enc[sizeof (struct LinkData)]; @@ -177,17 +203,17 @@ struct Deposit /* FIXME: should be TALER_CoinPublicInfo */ struct GNUNET_CRYPTO_EddsaPublicKey coin_pub; - struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - struct TALER_RSA_Signature coin_sig; + struct GNUNET_CRYPTO_rsa_Signature *coin_sig; - struct TALER_RSA_Signature ubsig; + struct GNUNET_CRYPTO_rsa_Signature *ubsig; // ??? /** * Type of the deposit (also purpose of the signature). Either * #TALER_SIGNATURE_DEPOSIT or #TALER_SIGNATURE_INCREMENTAL_DEPOSIT. */ - struct TALER_RSA_SignaturePurpose purpose; + // struct TALER_RSA_SignaturePurpose purpose; // FIXME: bad type! uint64_t transaction_id; diff --git a/src/mint/mint_common.c b/src/mint/mint_common.c index 734085e7b..bb55f30c4 100644 --- a/src/mint/mint_common.c +++ b/src/mint/mint_common.c @@ -93,7 +93,7 @@ TALER_MINT_read_denom_key (const char *filename, uint64_t size; size_t offset; void *data; - struct TALER_RSA_PrivateKey *priv; + struct GNUNET_CRYPTO_rsa_PrivateKey *priv; int ret; ret = GNUNET_SYSERR; @@ -115,7 +115,8 @@ TALER_MINT_read_denom_key (const char *filename, data, size)) goto cleanup; - if (NULL == (priv = TALER_RSA_decode_key (data + offset, size - offset))) + if (NULL == (priv = GNUNET_CRYPTO_rsa_private_key_decode (data + offset, + size - offset))) goto cleanup; dki->denom_priv = priv; memcpy (&dki->issue.signature, data, offset); @@ -138,22 +139,22 @@ int TALER_MINT_write_denom_key (const char *filename, const struct TALER_MINT_DenomKeyIssuePriv *dki) { - struct TALER_RSA_PrivateKeyBinaryEncoded *priv_enc; + char *priv_enc; + size_t priv_enc_size; struct GNUNET_DISK_FileHandle *fh; ssize_t wrote; size_t wsize; int ret; fh = NULL; - priv_enc = NULL; + priv_enc_size = GNUNET_CRYPTO_rsa_private_key_encode (dki->denom_priv, + &priv_enc); ret = GNUNET_SYSERR; if (NULL == (fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_TRUNCATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))) goto cleanup; - if (NULL == (priv_enc = TALER_RSA_encode_key (dki->denom_priv))) - goto cleanup; wsize = sizeof (struct TALER_MINT_DenomKeyIssuePriv) - offsetof (struct TALER_MINT_DenomKeyIssuePriv, issue.signature); if (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh, @@ -162,12 +163,11 @@ TALER_MINT_write_denom_key (const char *filename, goto cleanup; if (wrote != wsize) goto cleanup; - wsize = ntohs (priv_enc->len); if (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh, priv_enc, - wsize))) + priv_enc_size))) goto cleanup; - if (wrote != wsize) + if (wrote != priv_enc_size) goto cleanup; ret = GNUNET_OK; cleanup: diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 6ce60fc45..60ad14493 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -54,25 +54,44 @@ static char *TALER_MINT_db_connection_cfg_str; if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ } while (0) + +/** + * Locate the response for a /withdraw request under the + * key of the hash of the blinded message. + * + * @param db_conn database connection to use + * @param h_blind hash of the blinded message + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return #GNUNET_SYSERR on internal error + * #GNUNET_NO if the collectable was not found + * #GNUNET_YES on success + */ int TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, - struct TALER_RSA_BlindedSignaturePurpose *blind_ev, + const struct GNUNET_HashCode *h_blind, struct CollectableBlindcoin *collectable) { PGresult *result; struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (blind_ev), + TALER_DB_QUERY_PARAM_PTR (h_blind), TALER_DB_QUERY_PARAM_END }; - result = TALER_DB_exec_prepared (db_conn, "get_collectable_blindcoins", params); + char *sig_buf; + size_t sig_buf_size; + + result = TALER_DB_exec_prepared (db_conn, + "get_collectable_blindcoins", + params); if (PGRES_TUPLES_OK != PQresultStatus (result)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed: %s\n", PQresultErrorMessage (result)); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Query failed: %s\n", + PQresultErrorMessage (result)); PQclear (result); return GNUNET_SYSERR; } - if (0 == PQntuples (result)) { PQclear (result); @@ -80,7 +99,7 @@ TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, } struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("blind_ev_sig", &collectable->ev_sig), + TALER_DB_RESULT_SPEC_VAR("blind_sig", &sig_buf, &sig_buf_size), TALER_DB_RESULT_SPEC("denom_pub", &collectable->denom_pub), TALER_DB_RESULT_SPEC("reserve_sig", &collectable->reserve_sig), TALER_DB_RESULT_SPEC("reserve_pub", &collectable->reserve_pub), @@ -93,43 +112,66 @@ TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, PQclear (result); return GNUNET_SYSERR; } - (void) memcpy (&collectable->ev, blind_ev, sizeof (struct TALER_RSA_BlindedSignaturePurpose)); PQclear (result); return GNUNET_OK; } +/** + * Store collectable bit coin under the corresponding + * hash of the blinded message. + * + * @param db_conn database connection to use + * @param h_blind hash of the blinded message + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return #GNUNET_SYSERR on internal error + * #GNUNET_NO if the collectable was not found + * #GNUNET_YES on success + */ int TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, + const struct GNUNET_HashCode *h_blind, const struct CollectableBlindcoin *collectable) { PGresult *result; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (&collectable->ev), - TALER_DB_QUERY_PARAM_PTR (&collectable->ev_sig), - TALER_DB_QUERY_PARAM_PTR (&collectable->denom_pub), - TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_pub), - TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_sig), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db_conn, "insert_collectable_blindcoins", params); + char *sig_buf; + size_t sig_buf_size; + + sig_buf_size = GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, + &sig_buf); + { + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (&h_blind), + TALER_DB_QUERY_PARAM_PTR_SIZED (sig_buf, sig_buf_size), + TALER_DB_QUERY_PARAM_PTR (&collectable->denom_pub), + TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_pub), + TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_sig), + TALER_DB_QUERY_PARAM_END + }; - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed: %s\n", PQresultErrorMessage (result)); - PQclear (result); - return GNUNET_SYSERR; - } + result = TALER_DB_exec_prepared (db_conn, + "insert_collectable_blindcoins", + params); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Query failed: %s\n", + PQresultErrorMessage (result)); + PQclear (result); + return GNUNET_SYSERR; + } - if (0 != strcmp ("1", PQcmdTuples (result))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Insert failed (updated '%s' tupes instead of '1')\n", - PQcmdTuples (result)); + if (0 != strcmp ("1", PQcmdTuples (result))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Insert failed (updated '%s' tupes instead of '1')\n", + PQcmdTuples (result)); + PQclear (result); + return GNUNET_SYSERR; + } PQclear (result); - return GNUNET_SYSERR; } - - PQclear (result); return GNUNET_OK; } @@ -730,7 +772,7 @@ int TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, uint16_t newcoin_index, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub) + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) { uint16_t newcoin_index_nbo = htons (newcoin_index); struct TALER_DB_QueryParam params[] = { @@ -1267,7 +1309,7 @@ int TALER_MINT_DB_get_refresh_order (PGconn *db_conn, uint16_t newcoin_index, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub) + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) { uint16_t newcoin_index_nbo = htons (newcoin_index); @@ -1315,7 +1357,7 @@ int TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn, uint16_t newcoin_index, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct TALER_RSA_Signature *ev_sig) + const struct GNUNET_CRYPTO_rsa_Signature *ev_sig) { uint16_t newcoin_index_nbo = htons (newcoin_index); struct TALER_DB_QueryParam params[] = { @@ -1343,7 +1385,7 @@ int TALER_MINT_DB_get_refresh_collectable (PGconn *db_conn, uint16_t newcoin_index, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - struct TALER_RSA_Signature *ev_sig) + struct GNUNET_CRYPTO_rsa_Signature *ev_sig) { uint16_t newcoin_index_nbo = htons (newcoin_index); @@ -1394,7 +1436,7 @@ TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, uint16_t oldcoin_index, const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub) + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) { uint16_t oldcoin_index_nbo = htons (oldcoin_index); struct TALER_DB_QueryParam params[] = { @@ -1499,8 +1541,8 @@ TALER_db_get_link (PGconn *db_conn, for (i = 0; i < PQntuples (result); i++) { struct LinkDataEnc link_data_enc; - struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; - struct TALER_RSA_Signature ev_sig; + struct GNUNET_CRYPTO_rsa__PublicKey *denom_pub; + struct GNUNET_CRYPTO_rsa_Signature *sig; struct TALER_DB_ResultSpec rs[] = { TALER_DB_RESULT_SPEC("link_vector_enc", &link_data_enc), TALER_DB_RESULT_SPEC("denom_pub", &denom_pub), diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 7998a01cf..01ad1a6ed 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -27,7 +27,6 @@ #include <microhttpd.h> #include <gnunet/gnunet_util_lib.h> #include "taler_util.h" -#include "taler_rsa.h" #include "taler-mint-httpd_db.h" #include "mint.h" @@ -35,13 +34,40 @@ int TALER_MINT_DB_prepare (PGconn *db_conn); + +/** + * Locate the response for a /withdraw request under the + * key of the hash of the blinded message. + * + * @param db_conn database connection to use + * @param h_blind hash of the blinded message + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return #GNUNET_SYSERR on internal error + * #GNUNET_NO if the collectable was not found + * #GNUNET_YES on success + */ int TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, - struct TALER_RSA_BlindedSignaturePurpose *blind_ev, + const struct GNUNET_HashCode *h_blind, struct CollectableBlindcoin *collectable); + +/** + * Store collectable bit coin under the corresponding + * hash of the blinded message. + * + * @param db_conn database connection to use + * @param h_blind hash of the blinded message + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return #GNUNET_SYSERR on internal error + * #GNUNET_NO if the collectable was not found + * #GNUNET_YES on success + */ int TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, + const struct GNUNET_HashCode *h_blind, const struct CollectableBlindcoin *collectable); @@ -62,6 +88,15 @@ TALER_MINT_DB_get_reserve (PGconn *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub, struct Reserve *reserve_res); + +/** + * Update information about a reserve. + * + * @param db_conn + * @param reserve current reserve status + * @param fresh FIXME + * @return #GNUNET_OK on success + */ int TALER_MINT_DB_update_reserve (PGconn *db_conn, const struct Reserve *reserve, @@ -72,7 +107,7 @@ int TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, uint16_t newcoin_index, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub); + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); int TALER_MINT_DB_get_refresh_session (PGconn *db_conn, @@ -123,19 +158,22 @@ int TALER_MINT_DB_get_refresh_order (PGconn *db_conn, uint16_t newcoin_index, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub); + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); int TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn, uint16_t newcoin_index, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct TALER_RSA_Signature *ev_sig); + const struct GNUNET_CRYPTO_rsa_Signature *ev_sig); + int TALER_MINT_DB_get_refresh_collectable (PGconn *db_conn, uint16_t newcoin_index, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - struct TALER_RSA_Signature *ev_sig); + struct GNUNET_CRYPTO_rsa_Signature *ev_sig); + + int TALER_MINT_DB_set_reveal_ok (PGconn *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub); @@ -145,7 +183,7 @@ TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, uint16_t oldcoin_index, const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub); + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); int @@ -158,8 +196,8 @@ TALER_MINT_DB_get_refresh_melt (PGconn *db_conn, typedef int (*LinkIterator) (void *cls, const struct LinkDataEnc *link_data_enc, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub, - const struct TALER_RSA_Signature *ev_sig); + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub, + const struct GNUNET_CRYPTO_rsa_Signature *ev_sig); int TALER_db_get_link (PGconn *db_conn, diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 9dc03cdea..ffd97a1ad 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -29,7 +29,6 @@ #include <pthread.h> #include "mint.h" #include "taler_signatures.h" -#include "taler_rsa.h" #include "taler_json_lib.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_mhd.h" diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 369e88967..78946f50f 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -83,9 +83,9 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, if (GNUNET_SYSERR == res) { - GNUNET_break (0); + GNUNET_break (0); /* FIXME: return error message to client via MHD! */ - return MHD_NO; + return MHD_NO; } { @@ -221,56 +221,65 @@ TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection, * Execute a /withdraw/sign. * * @param connection the MHD connection to handle - * @param wsrd_ro details about the withdraw request + * @param reserve public key of the reserve + * @param denomination_pub public key of the denomination requested + * @param blinded_msg blinded message to be signed + * @param blinded_msg_len number of bytes in @a blinded_msg + * @param signature signature over the withdraw request, to be stored in DB * @return MHD result code */ int TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, - const struct TALER_WithdrawRequest *wsrd_ro) + const struct GNUNET_CRYPTO_EddsaPublicKey *reserve, + const struct GNUNET_CRYPTO_rsa_PublicKey *denomination_pub, + const char *blinded_msg, + size_t blinded_msg_len, + const struct GNUNET_CRYPTO_EddsaSignature *signature) { PGconn *db_conn; - struct Reserve reserve; + struct Reserve db_reserve; struct MintKeyState *key_state; struct CollectableBlindcoin collectable; struct TALER_MINT_DenomKeyIssuePriv *dki; - struct TALER_RSA_Signature ev_sig; + struct GNUNET_CRYPTO_rsa_Signature *sig; struct TALER_Amount amount_required; - /* FIXME: the fact that we do this here is a sign that we - need to have different versions of this struct for - the different places it is used! */ - struct TALER_WithdrawRequest wsrd = *wsrd_ro; + struct GNUNET_HashCode h_blind; int res; + GNUNET_CRYPTO_hash (blinded_msg, + blinded_msg_len, + &h_blind); + if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } - - res = TALER_MINT_DB_get_collectable_blindcoin (db_conn, - &wsrd.coin_envelope, + &h_blind, &collectable); if (GNUNET_SYSERR == res) { - // FIXME: return 'internal error' GNUNET_break (0); - return MHD_NO; + return TALER_MINT_reply_internal_db_error (connection); } /* Don't sign again if we have already signed the coin */ if (GNUNET_YES == res) - return TALER_MINT_reply_withdraw_sign_success (connection, - &collectable); + { + res = TALER_MINT_reply_withdraw_sign_success (connection, + &collectable); + GNUNET_CRYPTO_rsa_signature_free (collectable.sig); + return res; + } GNUNET_assert (GNUNET_NO == res); res = TALER_MINT_DB_get_reserve (db_conn, - &wsrd.reserve_pub, - &reserve); + reserve, + &db_reserve); if (GNUNET_SYSERR == res) { - // FIXME: return 'internal error' GNUNET_break (0); - return MHD_NO; + return TALER_MINT_reply_internal_db_error (connection); } if (GNUNET_NO == res) return TALER_MINT_reply_json_pack (connection, @@ -279,26 +288,9 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, "error", "Reserve not found"); - // fill out all the missing info in the request before - // we can check the signature on the request - - wsrd.purpose.purpose = htonl (TALER_SIGNATURE_WITHDRAW); - wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest) - - offsetof (struct TALER_WithdrawRequest, purpose)); - - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WITHDRAW, - &wsrd.purpose, - &wsrd.sig, - &wsrd.reserve_pub)) - return TALER_MINT_reply_json_pack (connection, - MHD_HTTP_UNAUTHORIZED, - "{s:s}", - "error", "Invalid Signature"); - key_state = TALER_MINT_key_state_acquire (); dki = TALER_MINT_get_denom_key (key_state, - &wsrd.denomination_pub); + denomination_pub); TALER_MINT_key_state_release (key_state); if (NULL == dki) return TALER_MINT_reply_json_pack (connection, @@ -307,52 +299,54 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, "error", "Denomination not found"); - amount_required = TALER_amount_ntoh (dki->issue.value); - amount_required = TALER_amount_add (amount_required, + amount_required = TALER_amount_add (TALER_amount_ntoh (dki->issue.value), TALER_amount_ntoh (dki->issue.fee_withdraw)); - if (0 < TALER_amount_cmp (amount_required, - TALER_amount_ntoh (reserve.balance))) + TALER_amount_ntoh (db_reserve.balance))) return TALER_MINT_reply_json_pack (connection, MHD_HTTP_PAYMENT_REQUIRED, "{s:s}", "error", "Insufficient funds"); - if (GNUNET_OK != - TALER_RSA_sign (dki->denom_priv, - &wsrd.coin_envelope, - sizeof (struct TALER_RSA_BlindedSignaturePurpose), - &ev_sig)) + + db_reserve.balance = TALER_amount_hton + (TALER_amount_subtract (TALER_amount_ntoh (db_reserve.balance), + amount_required)); + + sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv, + blinded_msg, + blinded_msg_len); + if (NULL == sig) { - // FIXME: return 'internal error' GNUNET_break (0); - return MHD_NO; + return TALER_MINT_reply_internal_error (connection, + "Internal error"); } - reserve.balance = TALER_amount_hton (TALER_amount_subtract (TALER_amount_ntoh (reserve.balance), - amount_required)); + /* transaction start */ if (GNUNET_OK != TALER_MINT_DB_update_reserve (db_conn, - &reserve, + &db_reserve, GNUNET_YES)) { - // FIXME: return 'internal error' GNUNET_break (0); - return MHD_NO; + return TALER_MINT_reply_internal_db_error (connection); } - collectable.ev = wsrd.coin_envelope; - collectable.ev_sig = ev_sig; + collectable.sig = sig; collectable.reserve_pub = wsrd.reserve_pub; collectable.reserve_sig = wsrd.sig; if (GNUNET_OK != TALER_MINT_DB_insert_collectable_blindcoin (db_conn, + &h_blind, &collectable)) { - // FIXME: return 'internal error' GNUNET_break (0); - return GNUNET_NO;; + GNUNET_CRYPTO_rsa_signature_free (sig); + return TALER_MINT_reply_internal_db_error (connection); } + /* transaction end */ + GNUNET_CRYPTO_rsa_signature_free (sig); return TALER_MINT_reply_withdraw_sign_success (connection, &collectable); } @@ -378,7 +372,7 @@ refresh_accept_denoms (struct MHD_Connection *connection, const struct MintKeyState *key_state, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, unsigned int denom_pubs_count, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pubs, + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pubs, struct TALER_Amount *r_amount) { unsigned int i; @@ -554,7 +548,7 @@ int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, unsigned int num_new_denoms, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pubs, + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pubs, unsigned int coin_count, const struct TALER_CoinPublicInfo *coin_public_infos) { @@ -821,10 +815,10 @@ helper_refresh_reveal_send_response (struct MHD_Connection *connection, { int res; unsigned int newcoin_index; - struct TALER_RSA_Signature *sigs; + struct GNUNET_CRYPTO_rsa_Signature **sigs; sigs = GNUNET_malloc (refresh_session->num_newcoins * - sizeof (struct TALER_RSA_Signature)); + sizeof (struct GNUNET_CRYPTO_rsa_Signature *)); for (newcoin_index = 0; newcoin_index < refresh_session->num_newcoins; newcoin_index++) { res = TALER_MINT_DB_get_refresh_collectable (db_conn, @@ -984,10 +978,12 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, { struct RefreshCommitCoin commit_coin; struct LinkData link_data; - struct TALER_RSA_BlindedSignaturePurpose *coin_ev_check; + // struct BlindedSignaturePurpose *coin_ev_check; struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; - struct TALER_RSA_BlindingKey *bkey; - struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; + struct GNUNET_CRYPTO_rsa_BlindingKey *bkey; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + char *buf; + size_t buf_len; bkey = NULL; res = TALER_MINT_DB_get_refresh_commit_coin (db_conn, @@ -1011,7 +1007,8 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, } GNUNET_CRYPTO_ecdsa_key_get_public (&link_data.coin_priv, &coin_pub); - if (NULL == (bkey = TALER_RSA_blinding_key_decode (&link_data.bkey_enc))) + if (NULL == (bkey = GNUNET_CRYPTO_rsa_blinding_key_decode (link_data.bkey_enc, + link_data.bkey_enc_size))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid blinding key\n"); // FIXME: return error code! @@ -1024,26 +1021,31 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, // FIXME: return error code! return MHD_NO; } - if (NULL == (coin_ev_check = - TALER_RSA_message_blind (&coin_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + if (NULL == (buf_len = + GNUNET_CRYPTO_rsa_blind (&h_msg, bkey, - &denom_pub))) + denom_pub, + &buf))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind failed\n"); // FIXME: return error code! return MHD_NO; } - if (0 != memcmp (&coin_ev_check, - &commit_coin.coin_ev, - sizeof (struct TALER_RSA_BlindedSignaturePurpose))) + if ( (buf_len != commit_coin.coin_ev_size) || + (0 != memcmp (buf, + commit_coin.coin_ev, + buf_len)) ) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind envelope does not match for kappa=%d, old=%d\n", + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "blind envelope does not match for kappa=%d, old=%d\n", (int) (i+off), (int) j); // FIXME: return error code! + GNUNET_free (buf); return MHD_NO; } + GNUNET_free (buf); + } } @@ -1058,9 +1060,9 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, for (j = 0; j < refresh_session.num_newcoins; j++) { struct RefreshCommitCoin commit_coin; - struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; struct TALER_MINT_DenomKeyIssuePriv *dki; - struct TALER_RSA_Signature ev_sig; + struct GNUNET_CRYPTO_rsa_Signature *ev_sig; res = TALER_MINT_DB_get_refresh_commit_coin (db_conn, refresh_session_pub, @@ -1091,11 +1093,10 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, // FIXME: return error code! return MHD_NO; } - if (GNUNET_OK != - TALER_RSA_sign (dki->denom_priv, - &commit_coin.coin_ev, - sizeof (struct TALER_RSA_BlindedSignaturePurpose), - &ev_sig)) + ev_sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv, + commit_coin.coin_ev, + commit_coin.coin_ev_len); + if (NULL == ev_sig) { GNUNET_break (0); // FIXME: return error code! @@ -1144,25 +1145,33 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, static int link_iter (void *cls, const struct LinkDataEnc *link_data_enc, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub, - const struct TALER_RSA_Signature *ev_sig) + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub, + const struct GNUNET_CRYPTO_rsa_Signature *ev_sig) { json_t *list = cls; json_t *obj = json_object (); + char *buf; + size_t buf_len; + json_array_append_new (list, obj); json_object_set_new (obj, "link_enc", - TALER_JSON_from_data (link_data_enc, - sizeof (struct LinkDataEnc))); + TALER_JSON_from_data (link_data_enc, + sizeof (struct LinkDataEnc))); + buf_len = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, + &buf); json_object_set_new (obj, "denom_pub", - TALER_JSON_from_data (denom_pub, - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded))); - + TALER_JSON_from_data (buf, + buf_len)); + GNUNET_free (buf); + buf_len = GNUNET_CRYPTO_rsa_signature_encode (ev_sig, + &buf); json_object_set_new (obj, "ev_sig", - TALER_JSON_from_data (ev_sig, - sizeof (struct TALER_RSA_Signature))); + TALER_JSON_from_data (buf, + buf_len)); + GNUNET_free (buf_len); return GNUNET_OK; } diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index 2a03812aa..dd82cbcb1 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -25,7 +25,6 @@ #include <microhttpd.h> #include <gnunet/gnunet_util_lib.h> #include "taler_util.h" -#include "taler_rsa.h" #include "taler-mint-httpd_keys.h" #include "mint.h" @@ -62,12 +61,20 @@ TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection, * Execute a /withdraw/sign. * * @param connection the MHD connection to handle - * @param wsrd details about the withdraw request + * @param reserve public key of the reserve + * @param denomination_pub public key of the denomination requested + * @param blinded_msg blinded message to be signed + * @param blinded_msg_len number of bytes in @a blinded_msg + * @param signature signature over the withdraw request, to be stored in DB * @return MHD result code */ int TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, - const struct TALER_WithdrawRequest *wsrd); + const struct GNUNET_CRYPTO_EddsaPublicKey *reserve, + const struct GNUNET_CRYPTO_rsa_PublicKey *denomination_pub, + const char *blinded_msg, + size_t blinded_msg_len, + const struct GNUNET_CRYPTO_EddsaSignature *signature); @@ -86,7 +93,7 @@ int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, unsigned int num_new_denoms, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pubs, + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pubs, unsigned int coin_count, const struct TALER_CoinPublicInfo *coin_public_infos); diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index c4f4718e3..6eeb3bff1 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -36,7 +36,6 @@ #include "mint.h" #include "mint_db.h" #include "taler_signatures.h" -#include "taler_rsa.h" #include "taler_json_lib.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_keys.h" diff --git a/src/mint/taler-mint-httpd_keys.c b/src/mint/taler-mint-httpd_keys.c index aa1e2c6e6..24851575a 100644 --- a/src/mint/taler-mint-httpd_keys.c +++ b/src/mint/taler-mint-httpd_keys.c @@ -32,7 +32,6 @@ #include <pthread.h> #include "mint.h" #include "taler_signatures.h" -#include "taler_rsa.h" #include "taler_json_lib.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_keys.h" @@ -66,14 +65,23 @@ static int reload_pipe[2]; static json_t * denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki) { + char *buf; + size_t buf_len; json_t *dk_json = json_object (); + json_object_set_new (dk_json, "master_sig", TALER_JSON_from_data (&dki->signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature))); json_object_set_new (dk_json, "stamp_start", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->start))); json_object_set_new (dk_json, "stamp_expire_withdraw", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_withdraw))); json_object_set_new (dk_json, "stamp_expire_deposit", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_spend))); + + + buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dki->denom_pub, + &buf); json_object_set_new (dk_json, "denom_pub", - TALER_JSON_from_data (&dki->denom_pub, sizeof (struct TALER_RSA_PublicKeyBinaryEncoded))); + TALER_JSON_from_data (buf, + buf_len)); + GNUNET_free (buf); json_object_set_new (dk_json, "value", TALER_JSON_from_amount (TALER_amount_ntoh (dki->value))); json_object_set_new (dk_json, @@ -341,14 +349,19 @@ TALER_MINT_key_state_acquire (void) */ struct TALER_MINT_DenomKeyIssuePriv * TALER_MINT_get_denom_key (const struct MintKeyState *key_state, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub) + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) { struct TALER_MINT_DenomKeyIssuePriv *issue; struct GNUNET_HashCode hash; + char *buf; + size_t buf_len; - GNUNET_CRYPTO_hash (denom_pub, - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded), + buf_len = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, + *buf); + GNUNET_CRYPTO_hash (buf, + buf_len, &hash); + GNUNET_free (buf); issue = GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map, &hash); return issue; } @@ -373,10 +386,10 @@ TALER_MINT_test_coin_valid (const struct MintKeyState *key_state, dki = TALER_MINT_get_denom_key (key_state, &coin_public_info->denom_pub); if (NULL == dki) return GNUNET_NO; - if (GNUNET_OK != TALER_RSA_verify (&coin_public_info->coin_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), - &coin_public_info->denom_sig, - &dki->issue.denom_pub)) + if (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (&c_hash, + coin_public_info->denom_sig, + dki->issue.denom_pub)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "coin signature is invalid\n"); diff --git a/src/mint/taler-mint-httpd_keys.h b/src/mint/taler-mint-httpd_keys.h index cef0ac950..596350345 100644 --- a/src/mint/taler-mint-httpd_keys.h +++ b/src/mint/taler-mint-httpd_keys.h @@ -107,7 +107,7 @@ TALER_MINT_key_state_acquire (void); */ struct TALER_MINT_DenomKeyIssuePriv * TALER_MINT_get_denom_key (const struct MintKeyState *key_state, - const struct TALER_RSA_PublicKeyBinaryEncoded *denom_pub); + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); /** @@ -116,9 +116,9 @@ TALER_MINT_get_denom_key (const struct MintKeyState *key_state, * * @param key_state the key state to use for checking the coin's validity * @param coin_public_info the coin public info to check for validity - * @return GNUNET_YES if the coin is valid, - * GNUNET_NO if it is invalid - * GNUNET_SYSERROR if an internal error occured + * @return #GNUNET_YES if the coin is valid, + * #GNUNET_NO if it is invalid + * #GNUNET_SYSERROR if an internal error occured */ int TALER_MINT_test_coin_valid (const struct MintKeyState *key_state, @@ -129,7 +129,7 @@ TALER_MINT_test_coin_valid (const struct MintKeyState *key_state, * Read signals from a pipe in a loop, and reload keys from disk if * SIGUSR1 is read from the pipe. * - * @return GNUNET_OK if we terminated normally, GNUNET_SYSERR on error + * @return #GNUNET_OK if we terminated normally, #GNUNET_SYSERR on error */ int TALER_MINT_key_reload_loop (void); diff --git a/src/mint/taler-mint-httpd_parsing.c b/src/mint/taler-mint-httpd_parsing.c index 56744c6b0..c4e28bba7 100644 --- a/src/mint/taler-mint-httpd_parsing.c +++ b/src/mint/taler-mint-httpd_parsing.c @@ -553,22 +553,29 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection, { unsigned int i; int ret; + void *ptr; ret = GNUNET_YES; for (i=0; NULL != spec[i].field_name; i++) { if (0 == spec[i].destination_size_in) + { + ptr = NULL; parse_variable_json_data (connection, root, spec[i].field_name, - (void **) spec[i].destination, + &ptr, &spec[i].destination_size_out, &ret); + spec[i].destination = ptr; + } else + { parse_fixed_json_data (connection, root, spec[i].field_name, spec[i].destination, spec[i].destination_size_in, &ret); + } } if (GNUNET_YES != ret) TALER_MINT_release_parsed_data (spec); @@ -641,4 +648,63 @@ TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection, return GNUNET_OK; } + +/** + * Extraxt variable-size base32crockford encoded data from request. + * + * Queues an error response to the connection if the parameter is missing + * or the encoding is invalid. + * + * @param connection the MHD connection + * @param param_name the name of the parameter with the key + * @param[out] out_data pointer to allocate buffer and store the result + * @param[out] out_size set to the size of the buffer allocated in @a out_data + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +int +TALER_MINT_mhd_request_var_arg_data (struct MHD_Connection *connection, + const char *param_name, + void **out_data, + size_t *out_size) +{ + const char *str; + size_t slen; + size_t olen; + void *out; + + str = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + param_name); + if (NULL == str) + { + return (MHD_NO == + TALER_MINT_reply_arg_missing (connection, param_name)) + ? GNUNET_SYSERR : GNUNET_NO; + } + slen = strlen (str); + olen = (slen * 5) / 8; + out = GNUNET_malloc (olen); + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (str, + strlen (str), + out, + olen)) + { + GNUNET_free (out); + *out_size = 0; + return (MHD_NO == + TALER_MINT_reply_arg_invalid (connection, param_name)) + ? GNUNET_SYSERR : GNUNET_NO; + } + *out_data = out; + *out_size = olen; + return GNUNET_OK; + +} + + + /* end of taler-mint-httpd_parsing.c */ diff --git a/src/mint/taler-mint-httpd_parsing.h b/src/mint/taler-mint-httpd_parsing.h index 59c31f595..5f5f35dfc 100644 --- a/src/mint/taler-mint-httpd_parsing.h +++ b/src/mint/taler-mint-httpd_parsing.h @@ -209,9 +209,8 @@ TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec); * Generate line in parser specification for variable-size value. * * @param field name of the field - * @param value where to store the value */ -#define TALER_MINT_PARSE_VARIABLE(field,value) { field, &value, 0, 0 } +#define TALER_MINT_PARSE_VARIABLE(field) { field, NULL, 0, 0 } /** * Generate line in parser specification indicating the end of the spec. @@ -220,7 +219,7 @@ TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec); /** - * Extraxt base32crockford encoded data from request. + * Extraxt fixed-size base32crockford encoded data from request. * * Queues an error response to the connection if the parameter is missing or * invalid. @@ -241,6 +240,28 @@ TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection, size_t out_size); +/** + * Extraxt variable-size base32crockford encoded data from request. + * + * Queues an error response to the connection if the parameter is missing + * or the encoding is invalid. + * + * @param connection the MHD connection + * @param param_name the name of the parameter with the key + * @param[out] out_data pointer to allocate buffer and store the result + * @param[out] out_size set to the size of the buffer allocated in @a out_data + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +int +TALER_MINT_mhd_request_var_arg_data (struct MHD_Connection *connection, + const char *param_name, + void **out_data, + size_t *out_size); + + #endif /* TALER_MICROHTTPD_LIB_H_ */ diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 69ba87c29..40737ae31 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -34,7 +34,6 @@ #include "mint.h" #include "mint_db.h" #include "taler_signatures.h" -#include "taler_rsa.h" #include "taler_json_lib.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_keys.h" @@ -94,7 +93,7 @@ check_confirm_signature (struct MHD_Connection *connection, * @param connection the connection to send error responses to * @param root the JSON object to extract the coin info from * @return #GNUNET_YES if coin public info in JSON was valid - * #GNUNET_NO otherwise + * #GNUNET_NO JSON was invalid, response was generated * #GNUNET_SYSERR on internal error */ static int @@ -103,33 +102,38 @@ request_json_require_coin_public_info (struct MHD_Connection *connection, struct TALER_CoinPublicInfo *r_public_info) { int ret; - - GNUNET_assert (NULL != root); - - ret = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "coin_pub", - JNAV_RET_DATA, - &r_public_info->coin_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - if (GNUNET_OK != ret) - return ret; - - ret = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "denom_sig", - JNAV_RET_DATA, - &r_public_info->denom_sig, - sizeof (struct TALER_RSA_Signature)); - if (GNUNET_OK != ret) - return ret; - - ret = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "denom_pub", - JNAV_RET_DATA, - &r_public_info->denom_pub, - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)); + struct GNUNET_CRYPTO_rsa_Signature *sig; + struct GNUNET_CRYPTO_rsa_PublicKey *pk; + struct GNUNET_MINT_ParseFieldSpec spec[] = + { + TALER_MINT_PARSE_FIXED("coin_pub", &r_public_info->coin_pub), + TALER_MINT_PARSE_VARIABLE("denom_sig"), + TALER_MINT_PARSE_VARIABLE("denom_pub"), + TALER_MINT_PARSE_END + }; + + ret = TALER_MINT_parse_json_data (connection, + root, + spec); if (GNUNET_OK != ret) return ret; - + sig = GNUNET_CRYPTO_rsa_signature_decode (spec[1].destination, + spec[1].destination_size_out); + pk = GNUNET_CRYPTO_rsa_public_key_decode (spec[2].destination, + spec[2].destination_size_out); + TALER_MINT_release_parsed_data (spec); + if ( (NULL == pk) || + (NULL == sig) ) + { + if (NULL != sig) + GNUNET_CRYPTO_rsa_signature_free (sig); + if (NULL != pk) + GNUNET_CRYPTO_rsa_public_key_free (pk); + // FIXME: send error reply... + return GNUNET_NO; + } + r_public_info->denom_sig = sig; + r_public_info->denom_pub = pk; return GNUNET_OK; } @@ -247,7 +251,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, json_t *new_denoms; unsigned int num_new_denoms; unsigned int i; - struct TALER_RSA_PublicKeyBinaryEncoded *denom_pubs; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pubs; json_t *melt_coins; struct TALER_CoinPublicInfo *coin_public_infos; unsigned int coin_count; @@ -256,6 +260,8 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, struct MintKeyState *key_state; struct RefreshMeltSignatureBody body; json_t *melt_sig_json; + char *buf; + size_t buf_size; res = TALER_MINT_parse_post_json (connection, connection_cls, @@ -291,23 +297,31 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, return res; num_new_denoms = json_array_size (new_denoms); denom_pubs = GNUNET_malloc (num_new_denoms * - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)); + sizeof (struct GNUNET_CRYPTO_rsa_PublicKey *)); for (i=0;i<num_new_denoms;i++) { res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "new_denoms", JNAV_INDEX, (int) i, - JNAV_RET_DATA, - &denom_pubs[i], - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)); - + JNAV_RET_DATA_VAR, + &buf, + &buf_size); if (GNUNET_OK != res) { GNUNET_free (denom_pubs); /* FIXME: proper cleanup! */ return res; } + denom_pubs[i] = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); + GNUNET_free (buf); + if (NULL == denom_pubs[i]) + { + GNUNET_free (denom_pubs); + /* FIXME: proper cleanup! */ + /* FIXME: generate error reply */ + return GNUNET_SYSERR; + } } res = GNUNET_MINT_parse_navigate_json (connection, root, @@ -377,9 +391,14 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, /* check that signature from the session public key is ok */ hash_context = GNUNET_CRYPTO_hash_context_start (); for (i = 0; i < num_new_denoms; i++) + { + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pubs[i], + &buf); GNUNET_CRYPTO_hash_context_read (hash_context, - &denom_pubs[i], - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)); + buf, + buf_size); + GNUNET_free (buf); + } for (i = 0; i < coin_count; i++) GNUNET_CRYPTO_hash_context_read (hash_context, &coin_public_infos[i].coin_pub, @@ -526,9 +545,9 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, JNAV_FIELD, "coin_evs", JNAV_INDEX, (int) i, JNAV_INDEX, (int) j, - JNAV_RET_DATA, - commit_coin[i][j].coin_ev, - sizeof (struct TALER_RSA_BlindedSignaturePurpose)); + JNAV_RET_DATA_VAR, + &commit_coin[i][j].coin_ev, + &commit_coin[i][j].coin_ev_size); if (GNUNET_OK != res) { @@ -539,8 +558,8 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, } GNUNET_CRYPTO_hash_context_read (hash_context, - &commit_coin[i][j].coin_ev, - sizeof (struct TALER_RSA_BlindedSignaturePurpose)); + commit_coin[i][j].coin_ev, + commit_coin[i][j].coin_ev_size); res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "link_encs", diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 75342cd2d..92bde3c70 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -295,10 +295,15 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, const struct CollectableBlindcoin *collectable) { json_t *root = json_object (); + size_t sig_buf_size; + char *sig_buf; + sig_buf_size = GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, + &sig_buf); json_object_set_new (root, "ev_sig", - TALER_JSON_from_data (&collectable->ev_sig, - sizeof (struct TALER_RSA_Signature))); + TALER_JSON_from_data (sig_buf, + sig_buf_size)); + GNUNET_free (sig_buf); return TALER_MINT_reply_json (connection, root, MHD_HTTP_OK); @@ -388,19 +393,26 @@ TALER_MINT_reply_refresh_commit_success (struct MHD_Connection *connection, int TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, unsigned int num_newcoins, - const struct TALER_RSA_Signature *sigs) + const struct GNUNET_CRYPTO_rsa_Signature *sigs) { int newcoin_index; json_t *root; json_t *list; + char *buf; + size_t buf_size; root = json_object (); list = json_array (); json_object_set_new (root, "ev_sigs", list); for (newcoin_index = 0; newcoin_index < num_newcoins; newcoin_index++) + { + buf_size = GNUNET_CRYPTO_rsa_signature_encode (&sigs[newcoin_index], + &buf); json_array_append_new (list, - TALER_JSON_from_data (&sigs[newcoin_index], - sizeof (struct TALER_RSA_Signature))); + TALER_JSON_from_data (buf, + buf_size)); + GNUNET_free (buf); + } return TALER_MINT_reply_json (connection, root, MHD_HTTP_OK); diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index 11e916f16..f92101ff7 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -209,7 +209,7 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, int TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, unsigned int num_newcoins, - const struct TALER_RSA_Signature *sigs); + const struct GNUNET_CRYPTO_rsa_Signature *sigs); diff --git a/src/mint/taler-mint-httpd_withdraw.c b/src/mint/taler-mint-httpd_withdraw.c index 5259c7fbf..1cf410910 100644 --- a/src/mint/taler-mint-httpd_withdraw.c +++ b/src/mint/taler-mint-httpd_withdraw.c @@ -32,7 +32,6 @@ #include "mint.h" #include "mint_db.h" #include "taler_signatures.h" -#include "taler_rsa.h" #include "taler_json_lib.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_keys.h" @@ -94,6 +93,12 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh, { struct TALER_WithdrawRequest wsrd; int res; + const struct GNUNET_CRYPTO_rsa_PublicKey *denomination_pub; + char *denomination_pub_data; + size_t denomination_pub_data_size; + char *blinded_msg; + size_t blinded_msg_len; + const struct GNUNET_CRYPTO_EddsaSignature signature; res = TALER_MINT_mhd_request_arg_data (connection, "reserve_pub", @@ -105,33 +110,66 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh, return MHD_YES; /* invalid request */ /* FIXME: handle variable-size signing keys! */ - res = TALER_MINT_mhd_request_arg_data (connection, - "denom_pub", - &wsrd.denomination_pub, - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)); + res = TALER_MINT_mhd_request_var_arg_data (connection, + "denom_pub", + &denomination_pub_data, + &denomination_pub_data_size); if (GNUNET_SYSERR == res) return MHD_NO; /* internal error */ if (GNUNET_NO == res) return MHD_YES; /* invalid request */ - res = TALER_MINT_mhd_request_arg_data (connection, - "coin_ev", - &wsrd.coin_envelope, - sizeof (struct TALER_RSA_Signature)); + res = TALER_MINT_mhd_request_var_arg_data (connection, + "coin_ev", + &blinded_msg, + &blinded_msg_len); if (GNUNET_SYSERR == res) return MHD_NO; /* internal error */ if (GNUNET_NO == res) return MHD_YES; /* invalid request */ res = TALER_MINT_mhd_request_arg_data (connection, "reserve_sig", - &wsrd.sig, + &signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature)); if (GNUNET_SYSERR == res) return MHD_NO; /* internal error */ if (GNUNET_NO == res) return MHD_YES; /* invalid request */ - return TALER_MINT_db_execute_withdraw_sign (connection, - &wsrd); + /* verify signature! */ + wsrd.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest)); + wsrd.purpose.type = htonl (TALER_SIGNATURE_WITHDRAW); + GNUNET_CRYPTO_hash (denomination_pub_data, + denomination_pub_data_size, + &wsrd.h_denomination_pub); + GNUNET_CRYPTO_hash (blinded_msg, + blinded_msg_len, + &wsrd.h_coin_envelope); + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WITHDRAW, + &wsrd.purpose, + &signature, + &wsrd.reserve_pub)) + { + return 42; // FIXME: generate error reply + } + denomination_pub = GNUNET_CRYPTO_rsa_private_key_decode (denomination_pub_data, + denomination_pub_data_size); + if (NULL == denomination_pub) + { + GNUNET_free (denomination_pub_data); + GNUNET_free (blinded_msg); + return 42; // FIXME: generate error reply + } + res = TALER_MINT_db_execute_withdraw_sign (connection, + &wsrd.reserve_pub, + denomination_pub, + blinded_msg, + blinded_msg_len, + &signature); + GNUNET_free (denomination_pub_data); + GNUNET_free (blinded_msg); + GNUNET_CRYPTO_rsa_public_key_free (denomination_pub); + return res; } /* end of taler-mint-httpd_withdraw.c */ diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 263618ade..c2a326566 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -105,7 +105,7 @@ static struct GNUNET_CRYPTO_EddsaPublicKey *master_pub; static struct GNUNET_TIME_Absolute lookahead_sign_stamp; -int +static int config_get_denom (const char *section, const char *option, struct TALER_Amount *denom) { char *str; @@ -117,7 +117,7 @@ config_get_denom (const char *section, const char *option, struct TALER_Amount * } -char * +static char * get_signkey_dir () { char *dir; @@ -128,7 +128,7 @@ get_signkey_dir () } -char * +static char * get_signkey_file (struct GNUNET_TIME_Absolute start) { char *dir; @@ -140,13 +140,12 @@ get_signkey_file (struct GNUNET_TIME_Absolute start) } - /** * Hash the data defining the coin type. * Exclude information that may not be the same for all * instances of the coin type (i.e. the anchor, overlap). */ -void +static void hash_coin_type (const struct CoinTypeParams *p, struct GNUNET_HashCode *hash) { struct CoinTypeNBO p_nbo; @@ -254,7 +253,7 @@ get_anchor_iter (void *cls, * @param overlap what's the overlap between the keys validity period? * @param[out] anchor the timestamp where the first new key should be generated */ -void +static void get_anchor (const char *dir, struct GNUNET_TIME_Relative duration, struct GNUNET_TIME_Relative overlap, @@ -291,6 +290,7 @@ get_anchor (const char *dir, // anchor is now the stamp where we need to create a new key } + static void create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration, @@ -327,7 +327,7 @@ check_signkey_valid (const char *signkey_filename) } -int +static int mint_keys_update_signkeys () { struct GNUNET_TIME_Relative signkey_duration; @@ -377,7 +377,7 @@ mint_keys_update_signkeys () } -int +static int get_cointype_params (const char *ct, struct CoinTypeParams *params) { const char *dir; @@ -434,8 +434,8 @@ static void create_denomkey_issue (struct CoinTypeParams *params, struct TALER_MINT_DenomKeyIssuePriv *dki) { - GNUNET_assert (NULL != (dki->denom_priv = TALER_RSA_key_create ())); - TALER_RSA_key_get_public (dki->denom_priv, &dki->issue.denom_pub); + GNUNET_assert (NULL != (dki->denom_priv = GNUNET_CRYPTO_rsa_private_key_create ())); + dki->issue.denom_pub = GNUNET_CRYPTO_rsa_private_key_get_get_public (dki->denom_priv); dki->issue.master = *master_pub; dki->issue.start = GNUNET_TIME_absolute_hton (params->anchor); dki->issue.expire_withdraw = @@ -470,7 +470,7 @@ check_cointype_valid (const char *filename, struct CoinTypeParams *params) } -int +static int mint_keys_update_cointype (const char *coin_alias) { struct CoinTypeParams p; @@ -496,7 +496,7 @@ mint_keys_update_cointype (const char *coin_alias) printf ("Target path: %s\n", dkf); create_denomkey_issue (&p, &denomkey_issue); ret = TALER_MINT_write_denom_key (dkf, &denomkey_issue); - TALER_RSA_key_free (denomkey_issue.denom_priv); + GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv); if (GNUNET_OK != ret) { fprintf (stderr, "Can't write to file '%s'\n", dkf); @@ -514,7 +514,7 @@ mint_keys_update_cointype (const char *coin_alias) } -int +static int mint_keys_update_denomkeys () { char *coin_types; @@ -659,4 +659,3 @@ main (int argc, char *const *argv) return 1; return 0; } - diff --git a/src/mint/test_mint_common.c b/src/mint/test_mint_common.c index d4bbb6c46..7946f4f1a 100644 --- a/src/mint/test_mint_common.c +++ b/src/mint/test_mint_common.c @@ -22,7 +22,6 @@ #include "platform.h" #include "gnunet/gnunet_util_lib.h" -#include "taler_rsa.h" #include "mint.h" #define EXITIF(cond) \ @@ -34,9 +33,11 @@ int main (int argc, const char *const argv[]) { struct TALER_MINT_DenomKeyIssuePriv dki; - struct TALER_RSA_PrivateKeyBinaryEncoded *enc; + char *enc; + size_t enc_size; struct TALER_MINT_DenomKeyIssuePriv dki_read; - struct TALER_RSA_PrivateKeyBinaryEncoded *enc_read; + char *enc_read; + size_t enc_read_size; char *tmpfile; int ret; @@ -51,20 +52,17 @@ main (int argc, const char *const argv[]) &dki.issue.signature, sizeof (dki) - offsetof (struct TALER_MINT_DenomKeyIssue, signature)); - dki.denom_priv = TALER_RSA_key_create (); - EXITIF (NULL == (enc = TALER_RSA_encode_key (dki.denom_priv))); + dki.denom_priv = GNUNET_CRYPTO_rsa_private_key_create (); + enc_size = GNUNET_CRYPTO_rsa_private_key_encode (dki.denom_priv, &enc); EXITIF (NULL == (tmpfile = GNUNET_DISK_mktemp ("test_mint_common"))); EXITIF (GNUNET_OK != TALER_MINT_write_denom_key (tmpfile, &dki)); EXITIF (GNUNET_OK != TALER_MINT_read_denom_key (tmpfile, &dki_read)); - EXITIF (NULL == (enc_read = TALER_RSA_encode_key (dki_read.denom_priv))); - EXITIF (enc->len != enc_read->len); + enc_read_size = GNUNET_CRYPTO_rsa_privae_key_encode (dki_read.denom_priv, + &enc_read); + EXITIF (enc_size != enc_read_size); EXITIF (0 != memcmp (enc, enc_read, - ntohs(enc->len))); - EXITIF (0 != memcmp (&dki.issue.signature, - &dki_read.issue.signature, - sizeof (dki) - offsetof (struct TALER_MINT_DenomKeyIssue, - signature))); + enc_size)); ret = 0; EXITIF_exit: @@ -76,8 +74,8 @@ main (int argc, const char *const argv[]) } GNUNET_free_non_null (enc_read); if (NULL != dki.denom_priv) - TALER_RSA_key_free (dki.denom_priv); + GNUNET_CRYPTO_rsa_private_key_free (dki.denom_priv); if (NULL != dki_read.denom_priv) - TALER_RSA_key_free (dki_read.denom_priv); + GNUNET_CRYPOT_rsa_private_key_free (dki_read.denom_priv); return ret; } diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 480b07a70..d280cfd04 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -6,8 +6,7 @@ lib_LTLIBRARIES = \ libtalerutil_la_SOURCES = \ util.c \ json.c \ - db.c \ - rsa.c + db.c libtalerutil_la_LIBADD = \ -lgnunetutil \ diff --git a/src/util/rsa.c b/src/util/rsa.c deleted file mode 100644 index c34ab1661..000000000 --- a/src/util/rsa.c +++ /dev/null @@ -1,928 +0,0 @@ -/* NOTE: this is obsolete logic, we should migrate to the - GNUNET_CRYPTO_rsa-API as soon as possible */ - -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> -*/ - -/** - * @file util/rsa.c - * @brief RSA key management utilities. Most of the code here is taken from - * gnunet-0.9.5a - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - * - * Authors of the gnunet code: - * Christian Grothoff - * Krista Bennett - * Gerd Knorr <kraxel@bytesex.org> - * Ioana Patrascu - * Tzvetan Horozov - */ - -#include "platform.h" -#include "gcrypt.h" -#include "gnunet/gnunet_util_lib.h" -#include "taler_rsa.h" - - - -#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) - -#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) - -#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) - -/** - * Log an error message at log-level 'level' that indicates - * a failure of the command 'cmd' with the message given - * by gcry_strerror(rc). - */ -#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0) - -/** - * Shorthand to cleanup non null mpi data types - */ -#define mpi_release_non_null(mpi) \ - if (NULL != mpi) gcry_mpi_release (mpi); - -/** - * The private information of an RSA key pair. - * NOTE: this must match the definition in crypto_ksk.c and gnunet-rsa.c! - */ -struct TALER_RSA_PrivateKey -{ - /** - * Libgcrypt S-expression for the ECC key. - */ - gcry_sexp_t sexp; -}; - - -/** - * Extract values from an S-expression. - * - * @param array where to store the result(s) - * @param sexp S-expression to parse - * @param topname top-level name in the S-expression that is of interest - * @param elems names of the elements to extract - * @return 0 on success - */ -static int -key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, - const char *elems) -{ - gcry_sexp_t list; - gcry_sexp_t l2; - const char *s; - unsigned int i; - unsigned int idx; - - if (! (list = gcry_sexp_find_token (sexp, topname, 0))) - return 1; - l2 = gcry_sexp_cadr (list); - gcry_sexp_release (list); - list = l2; - if (! list) - return 2; - idx = 0; - for (s = elems; *s; s++, idx++) - { - if (! (l2 = gcry_sexp_find_token (list, s, 1))) - { - for (i = 0; i < idx; i++) - { - gcry_free (array[i]); - array[i] = NULL; - } - gcry_sexp_release (list); - return 3; /* required parameter not found */ - } - array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); - gcry_sexp_release (l2); - if (! array[idx]) - { - for (i = 0; i < idx; i++) - { - gcry_free (array[i]); - array[i] = NULL; - } - gcry_sexp_release (list); - return 4; /* required parameter is invalid */ - } - } - gcry_sexp_release (list); - return 0; -} - -/** - * If target != size, move target bytes to the - * end of the size-sized buffer and zero out the - * first target-size bytes. - * - * @param buf original buffer - * @param size number of bytes in the buffer - * @param target target size of the buffer - */ -static void -adjust (unsigned char *buf, size_t size, size_t target) -{ - if (size < target) - { - memmove (&buf[target - size], buf, size); - memset (buf, 0, target - size); - } -} - - -/** - * Create a new private key. Caller must free return value. - * - * @return fresh private key - */ -struct TALER_RSA_PrivateKey * -TALER_RSA_key_create () -{ - struct TALER_RSA_PrivateKey *ret; - gcry_sexp_t s_key; - gcry_sexp_t s_keyparam; - - GNUNET_assert (0 == - gcry_sexp_build (&s_keyparam, NULL, - "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))", - 2048)); - GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam)); - gcry_sexp_release (s_keyparam); -#if EXTRA_CHECKS - GNUNET_assert (0 == gcry_pk_testkey (s_key)); -#endif - ret = GNUNET_malloc (sizeof (struct TALER_RSA_PrivateKey)); - ret->sexp = s_key; - return ret; -} - - -/** - * Free memory occupied by the private key. - * - * @param key pointer to the memory to free - */ -void -TALER_RSA_key_free (struct TALER_RSA_PrivateKey *key) -{ - gcry_sexp_release (key->sexp); - GNUNET_free (key); -} - - -/** - * Encode the private key in a format suitable for - * storing it into a file. - * @return encoding of the private key - */ -struct TALER_RSA_PrivateKeyBinaryEncoded * -TALER_RSA_encode_key (const struct TALER_RSA_PrivateKey *hostkey) -{ - struct TALER_RSA_PrivateKeyBinaryEncoded *retval; - gcry_mpi_t pkv[6]; - void *pbu[6]; - size_t sizes[6]; - int rc; - int i; - int size; - -#if EXTRA_CHECKS - if (gcry_pk_testkey (hostkey->sexp)) - { - GNUNET_break (0); - return NULL; - } -#endif - - memset (pkv, 0, sizeof (gcry_mpi_t) * 6); - rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpqu"); - if (rc) - rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpqu"); - if (rc) - rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpq"); - if (rc) - rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpq"); - if (rc) - rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "ned"); - if (rc) - rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "ned"); - GNUNET_assert (0 == rc); - size = sizeof (struct TALER_RSA_PrivateKeyBinaryEncoded); - for (i = 0; i < 6; i++) - { - if (NULL != pkv[i]) - { - GNUNET_assert (0 == - gcry_mpi_aprint (GCRYMPI_FMT_USG, - (unsigned char **) &pbu[i], &sizes[i], - pkv[i])); - size += sizes[i]; - } - else - { - pbu[i] = NULL; - sizes[i] = 0; - } - } - GNUNET_assert (size < 65536); - retval = GNUNET_malloc (size); - retval->len = htons (size); - i = 0; - retval->sizen = htons (sizes[0]); - memcpy (&((char *) (&retval[1]))[i], pbu[0], sizes[0]); - i += sizes[0]; - retval->sizee = htons (sizes[1]); - memcpy (&((char *) (&retval[1]))[i], pbu[1], sizes[1]); - i += sizes[1]; - retval->sized = htons (sizes[2]); - memcpy (&((char *) (&retval[1]))[i], pbu[2], sizes[2]); - i += sizes[2]; - /* swap p and q! */ - retval->sizep = htons (sizes[4]); - memcpy (&((char *) (&retval[1]))[i], pbu[4], sizes[4]); - i += sizes[4]; - retval->sizeq = htons (sizes[3]); - memcpy (&((char *) (&retval[1]))[i], pbu[3], sizes[3]); - i += sizes[3]; - retval->sizedmp1 = htons (0); - retval->sizedmq1 = htons (0); - memcpy (&((char *) (&retval[1]))[i], pbu[5], sizes[5]); - for (i = 0; i < 6; i++) - { - if (pkv[i] != NULL) - gcry_mpi_release (pkv[i]); - if (pbu[i] != NULL) - free (pbu[i]); - } - return retval; -} - - -/** - * Extract the public key of the given private key. - * - * @param priv the private key - * @param pub where to write the public key - */ -void -TALER_RSA_key_get_public (const struct TALER_RSA_PrivateKey *priv, - struct TALER_RSA_PublicKeyBinaryEncoded *pub) -{ - gcry_mpi_t skey[2]; - size_t size; - int rc; - - rc = key_from_sexp (skey, priv->sexp, "public-key", "ne"); - if (0 != rc) - rc = key_from_sexp (skey, priv->sexp, "private-key", "ne"); - if (0 != rc) - rc = key_from_sexp (skey, priv->sexp, "rsa", "ne"); - GNUNET_assert (0 == rc); - pub->len = - htons (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded) - - sizeof (pub->padding)); - pub->sizen = htons (TALER_RSA_DATA_ENCODING_LENGTH); - pub->padding = 0; - size = TALER_RSA_DATA_ENCODING_LENGTH; - GNUNET_assert (0 == - gcry_mpi_print (GCRYMPI_FMT_USG, &pub->key[0], size, &size, - skey[0])); - adjust (&pub->key[0], size, TALER_RSA_DATA_ENCODING_LENGTH); - size = TALER_RSA_KEY_LENGTH - TALER_RSA_DATA_ENCODING_LENGTH; - GNUNET_assert (0 == - gcry_mpi_print (GCRYMPI_FMT_USG, - &pub->key - [TALER_RSA_DATA_ENCODING_LENGTH], size, - &size, skey[1])); - adjust (&pub->key[TALER_RSA_DATA_ENCODING_LENGTH], size, - TALER_RSA_KEY_LENGTH - - TALER_RSA_DATA_ENCODING_LENGTH); - gcry_mpi_release (skey[0]); - gcry_mpi_release (skey[1]); -} - - -/** - * Decode the private key from the data-format back - * to the "normal", internal format. - * - * @param buf the buffer where the private key data is stored - * @param len the length of the data in 'buffer' - * @return NULL on error - */ -struct TALER_RSA_PrivateKey * -TALER_RSA_decode_key (const char *buf, uint16_t len) -{ - struct TALER_RSA_PrivateKey *ret; - const struct TALER_RSA_PrivateKeyBinaryEncoded *encoding = - (const struct TALER_RSA_PrivateKeyBinaryEncoded *) buf; - gcry_sexp_t res; - gcry_mpi_t n; - gcry_mpi_t e; - gcry_mpi_t d; - gcry_mpi_t p; - gcry_mpi_t q; - gcry_mpi_t u; - int rc; - size_t size; - size_t pos; - uint16_t enc_len; - size_t erroff; - - enc_len = ntohs (encoding->len); - if (len != enc_len) - return NULL; - - pos = 0; - size = ntohs (encoding->sizen); - rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG, - &((const unsigned char *) (&encoding[1]))[pos], size, - &size); - pos += ntohs (encoding->sizen); - if (0 != rc) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - return NULL; - } - size = ntohs (encoding->sizee); - rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG, - &((const unsigned char *) (&encoding[1]))[pos], size, - &size); - pos += ntohs (encoding->sizee); - if (0 != rc) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (n); - return NULL; - } - size = ntohs (encoding->sized); - rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG, - &((const unsigned char *) (&encoding[1]))[pos], size, - &size); - pos += ntohs (encoding->sized); - if (0 != rc) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (n); - gcry_mpi_release (e); - return NULL; - } - /* swap p and q! */ - size = ntohs (encoding->sizep); - if (size > 0) - { - rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG, - &((const unsigned char *) (&encoding[1]))[pos], size, - &size); - pos += ntohs (encoding->sizep); - if (0 != rc) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (n); - gcry_mpi_release (e); - gcry_mpi_release (d); - return NULL; - } - } - else - q = NULL; - size = ntohs (encoding->sizeq); - if (size > 0) - { - rc = gcry_mpi_scan (&p, GCRYMPI_FMT_USG, - &((const unsigned char *) (&encoding[1]))[pos], size, - &size); - pos += ntohs (encoding->sizeq); - if (0 != rc) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (n); - gcry_mpi_release (e); - gcry_mpi_release (d); - if (NULL != q) - gcry_mpi_release (q); - return NULL; - } - } - else - p = NULL; - pos += ntohs (encoding->sizedmp1); - pos += ntohs (encoding->sizedmq1); - size = - ntohs (encoding->len) - sizeof (struct TALER_RSA_PrivateKeyBinaryEncoded) - pos; - if (size > 0) - { - rc = gcry_mpi_scan (&u, GCRYMPI_FMT_USG, - &((const unsigned char *) (&encoding[1]))[pos], size, - &size); - if (0 != rc) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (n); - gcry_mpi_release (e); - gcry_mpi_release (d); - if (NULL != p) - gcry_mpi_release (p); - if (NULL != q) - gcry_mpi_release (q); - return NULL; - } - } - else - u = NULL; - - if ((NULL != p) && (NULL != q) && (NULL != u)) - { - rc = gcry_sexp_build (&res, &erroff, - "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)(u %m)))", - n, e, d, p, q, u); - } - else - { - if ((NULL != p) && (NULL != q)) - { - rc = gcry_sexp_build (&res, &erroff, - "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)))", - n, e, d, p, q); - } - else - { - rc = gcry_sexp_build (&res, &erroff, - "(private-key(rsa(n %m)(e %m)(d %m)))", n, e, d); - } - } - gcry_mpi_release (n); - gcry_mpi_release (e); - gcry_mpi_release (d); - if (NULL != p) - gcry_mpi_release (p); - if (NULL != q) - gcry_mpi_release (q); - if (NULL != u) - gcry_mpi_release (u); - - if (0 != rc) - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); - if (0 != (rc = gcry_pk_testkey (res))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); - return NULL; - } - ret = GNUNET_malloc (sizeof (struct TALER_RSA_PrivateKey)); - ret->sexp = res; - return ret; -} - - -/** - * Convert a public key to a string. - * - * @param pub key to convert - * @return string representing 'pub' - */ -char * -TALER_RSA_public_key_to_string (const struct TALER_RSA_PublicKeyBinaryEncoded *pub) -{ - char *pubkeybuf; - size_t keylen = (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) * 8; - char *end; - - if (keylen % 5 > 0) - keylen += 5 - keylen % 5; - keylen /= 5; - pubkeybuf = GNUNET_malloc (keylen + 1); - end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub, - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded), - pubkeybuf, - keylen); - if (NULL == end) - { - GNUNET_free (pubkeybuf); - return NULL; - } - *end = '\0'; - return pubkeybuf; -} - - -/** - * Convert a string representing a public key to a public key. - * - * @param enc encoded public key - * @param enclen number of bytes in enc (without 0-terminator) - * @param pub where to store the public key - * @return GNUNET_OK on success - */ -int -TALER_RSA_public_key_from_string (const char *enc, - size_t enclen, - struct TALER_RSA_PublicKeyBinaryEncoded *pub) -{ - size_t keylen = (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) * 8; - - if (keylen % 5 > 0) - keylen += 5 - keylen % 5; - keylen /= 5; - if (enclen != keylen) - return GNUNET_SYSERR; - - if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen, - (unsigned char*) pub, - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded))) - return GNUNET_SYSERR; - if ( (ntohs (pub->len) != sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) || - (ntohs (pub->padding) != 0) || - (ntohs (pub->sizen) != TALER_RSA_DATA_ENCODING_LENGTH) ) - return GNUNET_SYSERR; - return GNUNET_OK; -} - - -/** - * Convert the data specified in the given purpose argument to an - * S-expression suitable for signature operations. - * - * @param ptr pointer to the data to convert - * @param size the size of the data - * @return converted s-expression - */ -static gcry_sexp_t -data_to_sexp (const void *ptr, size_t size) -{ - gcry_mpi_t value; - gcry_sexp_t data; - - value = NULL; - data = NULL; - GNUNET_assert (0 == gcry_mpi_scan (&value, GCRYMPI_FMT_USG, ptr, size, NULL)); - GNUNET_assert (0 == gcry_sexp_build (&data, NULL, "(data (flags raw) (value %M))", value)); - gcry_mpi_release (value); - return data; -} - - -/** - * Sign the given hash block. - * - * @param key private key to use for the signing - * @param hash the block containing the hash of the message to sign - * @param hash_size the size of the hash block - * @param sig where to write the signature - * @return GNUNET_SYSERR on error, GNUNET_OK on success - */ -int -TALER_RSA_sign (const struct TALER_RSA_PrivateKey *key, - const void *hash, - size_t hash_size, - struct TALER_RSA_Signature *sig) -{ - gcry_sexp_t result; - gcry_sexp_t data; - size_t ssize; - gcry_mpi_t rval; - - data = data_to_sexp (hash, hash_size); - GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp)); - gcry_sexp_release (data); - GNUNET_assert (0 == key_from_sexp (&rval, result, "rsa", "s")); - gcry_sexp_release (result); - ssize = sizeof (struct TALER_RSA_Signature); - GNUNET_assert (0 == - gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) sig, ssize, - &ssize, rval)); - gcry_mpi_release (rval); - adjust (sig->sig, ssize, sizeof (struct TALER_RSA_Signature)); - return GNUNET_OK; -} - - -/** - * Convert the given public key from the network format to the - * S-expression that can be used by libgcrypt. - * - * @param publicKey public key to decode - * @return NULL on error - */ -static gcry_sexp_t -decode_public_key (const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey) -{ - gcry_sexp_t result; - gcry_mpi_t n; - gcry_mpi_t e; - size_t size; - size_t erroff; - int rc; - - if ((ntohs (publicKey->sizen) != TALER_RSA_DATA_ENCODING_LENGTH) || - (ntohs (publicKey->len) != - sizeof (struct TALER_RSA_PublicKeyBinaryEncoded) - - sizeof (publicKey->padding))) - { - GNUNET_break (0); - return NULL; - } - size = TALER_RSA_DATA_ENCODING_LENGTH; - if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG, &publicKey->key[0], size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - return NULL; - } - size = TALER_RSA_KEY_LENGTH - TALER_RSA_DATA_ENCODING_LENGTH; - if (0 != (rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG, - &publicKey->key[TALER_RSA_DATA_ENCODING_LENGTH], - size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (n); - return NULL; - } - rc = gcry_sexp_build (&result, &erroff, "(public-key(rsa(n %m)(e %m)))", n, - e); - gcry_mpi_release (n); - gcry_mpi_release (e); - if (0 != rc) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */ - return NULL; - } - return result; -} - - -/** - * Verify signature with the given hash. - * - * @param hash the hash code to verify against the signature - * @param sig signature that is being validated - * @param publicKey public key of the signer - * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid - */ -int -TALER_RSA_hash_verify (const struct GNUNET_HashCode *hash, - const struct TALER_RSA_Signature *sig, - const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey) -{ - gcry_sexp_t data; - gcry_sexp_t sigdata; - size_t size; - gcry_mpi_t val; - gcry_sexp_t psexp; - size_t erroff; - int rc; - - size = sizeof (struct TALER_RSA_Signature); - GNUNET_assert (0 == - gcry_mpi_scan (&val, GCRYMPI_FMT_USG, - (const unsigned char *) sig, size, &size)); - GNUNET_assert (0 == - gcry_sexp_build (&sigdata, &erroff, "(sig-val(rsa(s %m)))", - val)); - gcry_mpi_release (val); - data = data_to_sexp (hash, sizeof (struct GNUNET_HashCode)); - if (! (psexp = decode_public_key (publicKey))) - { - gcry_sexp_release (data); - gcry_sexp_release (sigdata); - return GNUNET_SYSERR; - } - rc = gcry_pk_verify (sigdata, data, psexp); - gcry_sexp_release (psexp); - gcry_sexp_release (data); - gcry_sexp_release (sigdata); - if (rc) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _("RSA signature verification failed at %s:%d: %s\n"), __FILE__, - __LINE__, gcry_strerror (rc)); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Verify signature on the given message - * - * @param msg the message - * @param size the size of the message - * @param sig signature that is being validated - * @param publicKey public key of the signer - * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid - */ -int -TALER_RSA_verify (const void *msg, size_t size, - const struct TALER_RSA_Signature *sig, - const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey) -{ - struct GNUNET_HashCode hash; - - GNUNET_CRYPTO_hash (msg, size, &hash); - return TALER_RSA_hash_verify (&hash, sig, publicKey); -} - -/** - * The blinding key is equal in length to the RSA modulus - */ -#define TALER_RSA_BLINDING_KEY_LEN TALER_RSA_DATA_ENCODING_LENGTH - -struct TALER_RSA_BlindingKey -{ - /** - * The blinding factor - */ - gcry_mpi_t r; -}; - -struct TALER_RSA_BlindingKey * -TALER_RSA_blinding_key_create () -{ - struct TALER_RSA_BlindingKey *blind; - - blind = GNUNET_new (struct TALER_RSA_BlindingKey); - blind->r = gcry_mpi_new (TALER_RSA_BLINDING_KEY_LEN * 8); - gcry_mpi_randomize (blind->r, TALER_RSA_BLINDING_KEY_LEN * 8, GCRY_STRONG_RANDOM); - return blind; -} - - -void -TALER_RSA_blinding_key_destroy (struct TALER_RSA_BlindingKey *bkey) -{ - gcry_mpi_release (bkey->r); - GNUNET_free (bkey); -} - - -struct TALER_RSA_BlindedSignaturePurpose * -TALER_RSA_message_blind (const void *msg, size_t size, - struct TALER_RSA_BlindingKey *bkey, - struct TALER_RSA_PublicKeyBinaryEncoded *pkey) -{ - struct TALER_RSA_BlindedSignaturePurpose *bsp; - struct GNUNET_HashCode hash; - gcry_sexp_t psexp; - gcry_mpi_t data; - gcry_mpi_t skey[2]; - gcry_mpi_t r_e; - gcry_mpi_t data_r_e; - size_t rsize; - gcry_error_t rc; - int ret; - - bsp = NULL; - psexp = NULL; - data = NULL; - skey[0] = skey[1] = NULL; - r_e = NULL; - data_r_e = NULL; - rsize = 0; - rc = 0; - ret = 0; - if (! (psexp = decode_public_key (pkey))) - return NULL; - ret = key_from_sexp (skey, psexp, "public-key", "ne"); - if (0 != ret) - ret = key_from_sexp (skey, psexp, "rsa", "ne"); - gcry_sexp_release (psexp); - psexp = NULL; - GNUNET_assert (0 == ret); - GNUNET_CRYPTO_hash (msg, size, &hash); - if (0 != (rc=gcry_mpi_scan (&data, GCRYMPI_FMT_USG, - (const unsigned char *) msg, size, &rsize))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_WARNING, "gcry_mpi_scan", rc); - goto cleanup; - } - r_e = gcry_mpi_new (0); - gcry_mpi_powm (r_e, bkey->r, - skey[1], /* e */ - skey[0]); /* n */ - - data_r_e = gcry_mpi_new (0); - gcry_mpi_mulm (data_r_e, data, r_e, skey[0]); - - bsp = GNUNET_new (struct TALER_RSA_BlindedSignaturePurpose); - rc = gcry_mpi_print (GCRYMPI_FMT_USG, - (unsigned char *) bsp, - sizeof (struct TALER_RSA_BlindedSignaturePurpose), - &rsize, - data_r_e); - GNUNET_assert (0 == rc); - adjust ((unsigned char *) bsp, rsize, - sizeof (struct TALER_RSA_BlindedSignaturePurpose)); - - cleanup: - if (NULL != psexp) gcry_sexp_release (psexp); - mpi_release_non_null (skey[0]); - mpi_release_non_null (skey[1]); - mpi_release_non_null (data); - mpi_release_non_null (r_e); - mpi_release_non_null (data_r_e); - return bsp; -} - - -int -TALER_RSA_unblind (struct TALER_RSA_Signature *sig, - struct TALER_RSA_BlindingKey *bkey, - struct TALER_RSA_PublicKeyBinaryEncoded *pkey) -{ - gcry_sexp_t psexp; - gcry_mpi_t skey; - gcry_mpi_t sigval; - gcry_mpi_t r_inv; - gcry_mpi_t ubsig; - size_t rsize; - gcry_error_t rc; - int ret; - - psexp = NULL; - skey = NULL; - sigval = NULL; - r_inv = NULL; - ubsig = NULL; - rsize = 0; - rc = 0; - ret = GNUNET_SYSERR; - if (! (psexp = decode_public_key (pkey))) - return GNUNET_SYSERR; - ret = key_from_sexp (&skey, psexp, "public-key", "n"); - if (0 != ret) - ret = key_from_sexp (&skey, psexp, "rsa", "n"); - gcry_sexp_release (psexp); - psexp = NULL; - if (0 != (rc = gcry_mpi_scan (&sigval, GCRYMPI_FMT_USG, - (const unsigned char *) sig, - sizeof (struct TALER_RSA_Signature), - &rsize))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - goto cleanup; - } - r_inv = gcry_mpi_new (0); - GNUNET_assert (1 == gcry_mpi_invm (r_inv, bkey->r, skey)); /* n: skey */ - ubsig = gcry_mpi_new (0); - gcry_mpi_mulm (ubsig, sigval, r_inv, skey); - rc = gcry_mpi_print (GCRYMPI_FMT_USG, - (unsigned char *) sig, - sizeof (struct TALER_RSA_Signature), - &rsize, - ubsig); - GNUNET_assert (0 == rc); - adjust ((unsigned char *) sig, rsize, sizeof (struct TALER_RSA_Signature)); - ret = GNUNET_OK; - - cleanup: - if (NULL != psexp) gcry_sexp_release (psexp); - mpi_release_non_null (skey); - mpi_release_non_null (sigval); - mpi_release_non_null (r_inv); - mpi_release_non_null (ubsig); - return ret; -} - - -/** - * Encode a blinding key - * - * @param bkey the blinding key to encode - * @param bkey_enc where to store the encoded binary key - * @return #GNUNET_OK upon successful encoding; #GNUNET_SYSERR upon failure - */ -int -TALER_RSA_blinding_key_encode (struct TALER_RSA_BlindingKey *bkey, - struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc) -{ - GNUNET_abort (); /* FIXME: not implemented */ -} - - -/** - * Decode a blinding key from its encoded form - * - * @param bkey_enc the encoded blinding key - * @return the decoded blinding key; NULL upon error - */ -struct TALER_RSA_BlindingKey * -TALER_RSA_blinding_key_decode (struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc) -{ - GNUNET_abort (); /* FIXME: not implemented */ -} - -/* end of util/rsa.c */ |