diff --git a/src/include/taler_util.h b/src/include/taler_util.h index d37ac356f..f1264d254 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -65,22 +65,50 @@ do {int rc; rc = cmd; if (!rc) break; LOG_ERROR("A Gcrypt call failed at %s:%d with error: %s\n", __FILE__, __LINE__, gcry_strerror(rc)); abort(); } while (0) + +/** + * Initialize Gcrypt library. + */ +void +TALER_gcrypt_init (void); + + +/* *********************** Amount management ****************** */ + + +/** + * Number of characters (plus 1 for 0-termination) we use to + * represent currency names (i.e. EUR, USD, etc.). + */ #define TALER_CURRENCY_LEN 4 GNUNET_NETWORK_STRUCT_BEGIN +/** + * Amount, encoded for network transmission. + */ struct TALER_AmountNBO { + /** + * Value in the main currency, in NBO. + */ uint32_t value; + + /** + * Additinal fractional value, in NBO. + */ uint32_t fraction; + + /** + * Type of the currency being represented. + */ char currency[TALER_CURRENCY_LEN]; }; GNUNET_NETWORK_STRUCT_END - /** * Representation of monetary value in a given currency. */ @@ -90,10 +118,12 @@ struct TALER_Amount * Value (numerator of fraction) */ uint32_t value; + /** * Fraction (denominator of fraction) */ uint32_t fraction; + /** * Currency string, left adjusted and padded with zeros. */ @@ -101,38 +131,39 @@ struct TALER_Amount }; -/** - * Initialize Gcrypt library. - */ -void -TALER_gcrypt_init (void); - - /** * Parse denomination description, in the format "T : V : F". * * @param str denomination description * @param denom denomination to write the result to - * @return GNUNET_OK if the string is a valid denomination specification, - * GNUNET_SYSERR if it is invalid. + * @return #GNUNET_OK if the string is a valid denomination specification, + * #GNUNET_SYSERR if it is invalid. */ int -TALER_string_to_amount (const char *str, struct TALER_Amount *denom); +TALER_string_to_amount (const char *str, + struct TALER_Amount *denom); /** - * FIXME + * Convert amount from host to network representation. + * + * @param d amount in host representation + * @return amount in network representation */ struct TALER_AmountNBO TALER_amount_hton (struct TALER_Amount d); /** - * FIXME + * Convert amount from network to host representation. + * + * @param d amount in network representation + * @return amount in host representation */ struct TALER_Amount TALER_amount_ntoh (struct TALER_AmountNBO dn); + /** * Compare the value/fraction of two amounts. Does not compare the currency, * i.e. comparing amounts with the same value and fraction but different @@ -143,7 +174,8 @@ TALER_amount_ntoh (struct TALER_AmountNBO dn); * @return result of the comparison */ int -TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2); +TALER_amount_cmp (struct TALER_Amount a1, + struct TALER_Amount a2); /** @@ -154,7 +186,8 @@ TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2); * @return (a1-a2) or 0 if a2>=a1 */ struct TALER_Amount -TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2); +TALER_amount_subtract (struct TALER_Amount a1, + struct TALER_Amount a2); /** @@ -165,7 +198,8 @@ TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2); * @return sum of a1 and a2 */ struct TALER_Amount -TALER_amount_add (struct TALER_Amount a1, struct TALER_Amount a2); +TALER_amount_add (struct TALER_Amount a1, + struct TALER_Amount a2); /** @@ -187,43 +221,89 @@ TALER_amount_normalize (struct TALER_Amount amount); char * TALER_amount_to_string (struct TALER_Amount amount); +/* ****************** FIXME: move to GNUnet? ************** */ /** * Return the base32crockford encoding of the given buffer. * * The returned string will be freshly allocated, and must be free'd - * with GNUNET_free. + * with #GNUNET_free(). * * @param buffer with data * @param size size of the buffer * @return freshly allocated, null-terminated string */ char * -TALER_data_to_string_alloc (const void *buf, size_t size); +TALER_data_to_string_alloc (const void *buf, + size_t size); + + +/* ****************** Refresh crypto primitives ************* */ + +/** + * Representation of an encrypted refresh link. + */ +struct TALER_RefreshLinkEncrypted +{ + + /** + * Encrypted private key of the coin. + */ + char [sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)] coin_priv_enc; + + /** + * Encrypted blinding key with @e blinding_key_enc_size bytes. + */ + char *blinding_key_enc; + + /** + * Number of bytes in @e blinding_key_enc. + */ + size_t blinding_key_enc_size; +}; /** - * Get encoded binary data from a configuration. - * - * @return GNUNET_OK on success - * GNUNET_NO is the value does not exist - * GNUNET_SYSERR on encoding error + * Representation of an refresh link in cleartext. */ -int -TALER_configuration_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *section, const char *option, - void *buf, size_t buf_size); +struct TALER_RefreshLinkDecrypted +{ + + /** + * Private key of the coin. + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv; + + /** + * Blinding key with @e blinding_key_enc_size bytes. + */ + struct GNUNET_CRYPTO_rsa_BlindingKey *blinding_key; + +}; +/** + * Decrypt refresh link information. + * + * @param input encrypted refresh link data + * @param secret shared secret to use for decryption + * @return NULL on error + */ +struct TALER_RefreshLinkDecrypted * +TALER_refresh_decrypt (const struct TALER_RefreshLinkEncrypted *input, + const struct GNUNET_HashCode *secret); -int -TALER_refresh_decrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result); - -int -TALER_refresh_encrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result); - - +/** + * Encrypt refresh link information. + * + * @param input plaintext refresh link data + * @param secret shared secret to use for encryption + * @return NULL on error (should never happen) + */ +struct TALER_RefreshLinkEncrypted * +TALER_refresh_encrypt (const struct TALER_RefreshLinkDecrypted *input, + const struct GNUNET_HashCode *secret); #endif diff --git a/src/mint/mint.h b/src/mint/mint.h index 3f98b368d..b194be687 100644 --- a/src/mint/mint.h +++ b/src/mint/mint.h @@ -117,9 +117,9 @@ struct CollectableBlindcoin struct RefreshSession { - int has_commit_sig; struct GNUNET_CRYPTO_EddsaSignature commit_sig; struct GNUNET_CRYPTO_EddsaPublicKey session_pub; + int has_commit_sig; uint16_t num_oldcoins; uint16_t num_newcoins; uint16_t kappa; @@ -128,46 +128,33 @@ struct RefreshSession }; -#define TALER_REFRESH_SHARED_SECRET_LENGTH (sizeof (struct GNUNET_HashCode)) -#define TALER_REFRESH_LINK_LENGTH (sizeof (struct LinkData)) - +/** + * FIXME + */ struct RefreshCommitLink { struct GNUNET_CRYPTO_EddsaPublicKey session_pub; struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; + struct GNUNET_HashCode shared_secret; uint16_t cnc_index; uint16_t oldcoin_index; - char shared_secret_enc[sizeof (struct GNUNET_HashCode)]; -}; - -struct LinkData -{ - struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv; - struct GNUNET_CRYPTO_rsa_BlindingKey *bkey_enc; }; -GNUNET_NETWORK_STRUCT_BEGIN - -struct SharedSecretEnc -{ - char data[TALER_REFRESH_SHARED_SECRET_LENGTH]; -}; - - -struct LinkDataEnc -{ - char data[sizeof (struct LinkData)]; -}; - -GNUNET_NETWORK_STRUCT_END - +/** + * FIXME + */ struct RefreshCommitCoin { + /** + * Refresh session's public key. + */ struct GNUNET_CRYPTO_EddsaPublicKey session_pub; + struct TALER_RefreshLinkEncrypted refresh_link; + /** - * Blinded message to be signed (in envelope). + * Blinded message to be signed (in envelope), with @e coin_env_size bytes. */ char *coin_ev; @@ -176,22 +163,36 @@ struct RefreshCommitCoin */ size_t coin_ev_size; + /** + * FIXME: needed? + */ uint16_t cnc_index; + + /** + * FIXME: needed? + */ uint16_t newcoin_index; - char link_enc[sizeof (struct LinkData)]; + }; +/** + * FIXME + */ struct KnownCoin { struct TALER_CoinPublicInfo public_info; - struct TALER_Amount expended_balance; - int is_refreshed; + /** * Refreshing session, only valid if * is_refreshed==1. */ struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; + + struct TALER_Amount expended_balance; + + int is_refreshed; + }; @@ -356,11 +357,15 @@ TALER_MINT_config_load (const char *mint_base_dir); int -TALER_TALER_DB_extract_amount (PGresult *result, unsigned int row, - int indices[3], struct TALER_Amount *denom); +TALER_TALER_DB_extract_amount (PGresult *result, + unsigned int row, + int indices[3], + struct TALER_Amount *denom); int -TALER_TALER_DB_extract_amount_nbo (PGresult *result, unsigned int row, - int indices[3], struct TALER_AmountNBO *denom_nbo); +TALER_TALER_DB_extract_amount_nbo (PGresult *result, + unsigned int row, + int indices[3], + struct TALER_AmountNBO *denom_nbo); #endif /* _MINT_H */ diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 2fbcb54b4..bb07e2ca3 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -4,6 +4,8 @@ lib_LTLIBRARIES = \ libtalerutil.la libtalerutil_la_SOURCES = \ + amount.c \ + crypto.c \ util.c \ json.c \ db.c diff --git a/src/util/amount.c b/src/util/amount.c new file mode 100644 index 000000000..8bd899bf5 --- /dev/null +++ b/src/util/amount.c @@ -0,0 +1,329 @@ +/* + 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 +*/ + +/** + * @file amount.c + * @brief Common utility functions to deal with units of currency + * @author Sree Harsha Totakura + * @author Florian Dold + * @author Benedikt Mueller + */ +#include "platform.h" +#include "taler_util.h" +#include +#include +#include + +#define AMOUNT_FRAC_BASE 1000000 + +#define AMOUNT_FRAC_LEN 6 + + +/** + * Parse money amount description, in the format "A:B.C". + * + * @param str amount description + * @param denom amount to write the result to + * @return #GNUNET_OK if the string is a valid amount specification, + * #GNUNET_SYSERR if it is invalid. + */ +int +TALER_string_to_amount (const char *str, + struct TALER_Amount *denom) +{ + unsigned int i; // pos in str + int n; // number tmp + unsigned int c; // currency pos + uint32_t b; // base for suffix + + memset (denom, 0, sizeof (struct TALER_Amount)); + + i = n = c = 0; + + while (isspace(str[i])) + i++; + + if (0 == str[i]) + { + printf("null before currency\n"); + return GNUNET_SYSERR; + } + + while (str[i] != ':') + { + if (0 == str[i]) + { + printf("null before colon"); + return GNUNET_SYSERR; + } + if (c > 3) + { + printf("currency too long\n"); + return GNUNET_SYSERR; + } + denom->currency[c] = str[i]; + c++; + i++; + } + + // skip colon + i++; + + if (0 == str[i]) + { + printf("null before value\n"); + return GNUNET_SYSERR; + } + + while (str[i] != '.') + { + if (0 == str[i]) + { + return GNUNET_OK; + } + n = str[i] - '0'; + if (n < 0 || n > 9) + { + printf("invalid character '%c' before comma at %u\n", (char) n, i); + return GNUNET_SYSERR; + } + denom->value = (denom->value * 10) + n; + i++; + } + + // skip the dot + i++; + + if (0 == str[i]) + { + printf("null after dot"); + return GNUNET_SYSERR; + } + + b = 100000; + + while (0 != str[i]) + { + n = str[i] - '0'; + if (b == 0 || n < 0 || n > 9) + { + printf("error after comma"); + return GNUNET_SYSERR; + } + denom->fraction += n * b; + b /= 10; + i++; + } + + return GNUNET_OK; +} + + +/** + * FIXME + */ +struct TALER_AmountNBO +TALER_amount_hton (struct TALER_Amount d) +{ + struct TALER_AmountNBO dn; + dn.value = htonl (d.value); + dn.fraction = htonl (d.fraction); + memcpy (dn.currency, d.currency, TALER_CURRENCY_LEN); + + return dn; +} + + +/** + * FIXME + */ +struct TALER_Amount +TALER_amount_ntoh (struct TALER_AmountNBO dn) +{ + struct TALER_Amount d; + d.value = ntohl (dn.value); + d.fraction = ntohl (dn.fraction); + memcpy (d.currency, dn.currency, sizeof(dn.currency)); + + return d; +} + + +/** + * Compare the value/fraction of two amounts. Does not compare the currency, + * i.e. comparing amounts with the same value and fraction but different + * currency would return 0. + * + * @param a1 first amount + * @param a2 second amount + * @return result of the comparison + */ +int +TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2) +{ + a1 = TALER_amount_normalize (a1); + a2 = TALER_amount_normalize (a2); + if (a1.value == a2.value) + { + if (a1.fraction < a2.fraction) + return -1; + if (a1.fraction > a2.fraction) + return 1; + return 0; + } + if (a1.value < a2.value) + return -1; + return 1; +} + + +/** + * Perform saturating subtraction of amounts. + * + * @param a1 amount to subtract from + * @param a2 amount to subtract + * @return (a1-a2) or 0 if a2>=a1 + */ +struct TALER_Amount +TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2) +{ + a1 = TALER_amount_normalize (a1); + a2 = TALER_amount_normalize (a2); + + if (a1.value < a2.value) + { + a1.value = 0; + a1.fraction = 0; + return a1; + } + + if (a1.fraction < a2.fraction) + { + if (0 == a1.value) + { + a1.fraction = 0; + return a1; + } + a1.fraction += AMOUNT_FRAC_BASE; + a1.value -= 1; + } + + a1.fraction -= a2.fraction; + a1.value -= a2.value; + + return a1; +} + + +/** + * Perform saturating addition of amounts. + * + * @param a1 first amount to add + * @param a2 second amount to add + * @return sum of a1 and a2 + */ +struct TALER_Amount +TALER_amount_add (struct TALER_Amount a1, struct TALER_Amount a2) +{ + a1 = TALER_amount_normalize (a1); + a2 = TALER_amount_normalize (a2); + + a1.value += a2.value; + a1.fraction += a2.fraction; + + if (0 == a1.currency[0]) + { + memcpy (a2.currency, a1.currency, TALER_CURRENCY_LEN); + } + + if (0 == a2.currency[0]) + { + memcpy (a1.currency, a2.currency, TALER_CURRENCY_LEN); + } + + if (0 != a1.currency[0] && 0 != memcmp (a1.currency, a2.currency, TALER_CURRENCY_LEN)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "adding mismatching currencies\n"); + } + + if (a1.value < a2.value) + { + a1.value = UINT32_MAX; + a2.value = UINT32_MAX; + return a1; + } + + return TALER_amount_normalize (a1); +} + + +/** + * Normalize the given amount. + * + * @param amout amount to normalize + * @return normalized amount + */ +struct TALER_Amount +TALER_amount_normalize (struct TALER_Amount amount) +{ + while (amount.value != UINT32_MAX && amount.fraction >= AMOUNT_FRAC_BASE) + { + amount.fraction -= AMOUNT_FRAC_BASE; + amount.value += 1; + } + return amount; +} + + +/** + * Convert amount to string. + * + * @param amount amount to convert to string + * @return freshly allocated string representation + */ +char * +TALER_amount_to_string (struct TALER_Amount amount) +{ + char tail[AMOUNT_FRAC_LEN + 1] = { 0 }; + char curr[TALER_CURRENCY_LEN + 1] = { 0 }; + char *result = NULL; + int len; + + memcpy (curr, amount.currency, TALER_CURRENCY_LEN); + + amount = TALER_amount_normalize (amount); + if (0 != amount.fraction) + { + unsigned int i; + uint32_t n = amount.fraction; + for (i = 0; (i < AMOUNT_FRAC_LEN) && (n != 0); i++) + { + tail[i] = '0' + (n / (AMOUNT_FRAC_BASE / 10)); + n = (n * 10) % (AMOUNT_FRAC_BASE); + } + tail[i] = 0; + len = GNUNET_asprintf (&result, "%s:%lu.%s", curr, (unsigned long) amount.value, tail); + } + else + { + len = GNUNET_asprintf (&result, "%s:%lu", curr, (unsigned long) amount.value); + } + GNUNET_assert (len > 0); + return result; +} + + +/* end of amount.c */ diff --git a/src/util/crypto.c b/src/util/crypto.c new file mode 100644 index 000000000..7ff741159 --- /dev/null +++ b/src/util/crypto.c @@ -0,0 +1,118 @@ +/* + 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 +*/ + +/** + * @file crypto.c + * @brief Cryptographic utility functions + * @author Sree Harsha Totakura + * @author Florian Dold + * @author Benedikt Mueller + */ + +#include "platform.h" +#include "taler_util.h" +#include +#include +#include + +#define CURVE "Ed25519" + + +static void +fatal_error_handler (void *cls, int wtf, const char *msg) +{ + LOG_ERROR("Fatal error in Gcrypt: %s\n", msg); + abort(); +} + + +/** + * Initialize Gcrypt library. + */ +void +TALER_gcrypt_init() +{ + gcry_set_fatalerror_handler (&fatal_error_handler, NULL); + TALER_assert_as(gcry_check_version(NEED_LIBGCRYPT_VERSION), + "libgcrypt version mismatch"); + /* Disable secure memory. */ + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); +} + + +/** + * Derive symmetric key material for refresh operations from + * a given shared secret. + * + * @param secret the shared secret + * @param[out] iv set to initialization vector + * @param[out] skey set to session key + */ +static void +derive_refresh_key (const struct GNUNET_HashCode *secret, + struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, + struct GNUNET_CRYPTO_SymmetricSessionKey *skey) +{ + static const char ctx_key[] = "taler-key-skey"; + static const char ctx_iv[] = "taler-key-iv"; + + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), + ctx_key, strlen (ctx_key), + secret, sizeof (struct GNUNET_HashCode), + NULL, 0)); + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), + ctx_iv, strlen (ctx_iv), + secret, sizeof (struct GNUNET_HashCode), + NULL, 0)); +} + + +int +TALER_refresh_decrypt (const void *input, + size_t input_size, + const struct GNUNET_HashCode *secret, + void *result) +{ + struct GNUNET_CRYPTO_SymmetricInitializationVector iv; + struct GNUNET_CRYPTO_SymmetricSessionKey skey; + + derive_refresh_key (secret, &iv, &skey); + + return GNUNET_CRYPTO_symmetric_decrypt (input, input_size, &skey, &iv, result); +} + + +int +TALER_refresh_encrypt (const void *input, + size_t input_size, + const struct GNUNET_HashCode *secret, + void *result) +{ + struct GNUNET_CRYPTO_SymmetricInitializationVector iv; + struct GNUNET_CRYPTO_SymmetricSessionKey skey; + + derive_refresh_key (secret, &iv, &skey); + + return GNUNET_CRYPTO_symmetric_encrypt (input, input_size, &skey, &iv, result); +} + + + + +/* end of crypto.c */ diff --git a/src/util/util.c b/src/util/util.c index 80f8fc5f0..440b49fab 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -28,335 +28,11 @@ #include #include -#define CURVE "Ed25519" - -#define AMOUNT_FRAC_BASE 1000000 -#define AMOUNT_FRAC_LEN 6 - - - -static void -fatal_error_handler (void *cls, int wtf, const char *msg) -{ - LOG_ERROR("Fatal error in Gcrypt: %s\n", msg); - abort(); -} - - -/** - * Initialize Gcrypt library. - */ -void -TALER_gcrypt_init() -{ - gcry_set_fatalerror_handler (&fatal_error_handler, NULL); - TALER_assert_as(gcry_check_version(NEED_LIBGCRYPT_VERSION), - "libgcrypt version mismatch"); - /* Disable secure memory. */ - gcry_control (GCRYCTL_DISABLE_SECMEM, 0); - gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); -} - - -/** - * Parse money amount description, in the format "A:B.C". - * - * @param str amount description - * @param denom amount to write the result to - * @return GNUNET_OK if the string is a valid amount specification, - * GNUNET_SYSERR if it is invalid. - */ -int -TALER_string_to_amount (const char *str, struct TALER_Amount *denom) -{ - unsigned int i; // pos in str - int n; // number tmp - unsigned int c; // currency pos - uint32_t b; // base for suffix - - memset (denom, 0, sizeof (struct TALER_Amount)); - - i = n = c = 0; - - while (isspace(str[i])) - i++; - - if (0 == str[i]) - { - printf("null before currency\n"); - return GNUNET_SYSERR; - } - - while (str[i] != ':') - { - if (0 == str[i]) - { - printf("null before colon"); - return GNUNET_SYSERR; - } - if (c > 3) - { - printf("currency too long\n"); - return GNUNET_SYSERR; - } - denom->currency[c] = str[i]; - c++; - i++; - } - - // skip colon - i++; - - if (0 == str[i]) - { - printf("null before value\n"); - return GNUNET_SYSERR; - } - - while (str[i] != '.') - { - if (0 == str[i]) - { - return GNUNET_OK; - } - n = str[i] - '0'; - if (n < 0 || n > 9) - { - printf("invalid character '%c' before comma at %u\n", (char) n, i); - return GNUNET_SYSERR; - } - denom->value = (denom->value * 10) + n; - i++; - } - - // skip the dot - i++; - - if (0 == str[i]) - { - printf("null after dot"); - return GNUNET_SYSERR; - } - - b = 100000; - - while (0 != str[i]) - { - n = str[i] - '0'; - if (b == 0 || n < 0 || n > 9) - { - printf("error after comma"); - return GNUNET_SYSERR; - } - denom->fraction += n * b; - b /= 10; - i++; - } - - return GNUNET_OK; -} - - -/** - * FIXME - */ -struct TALER_AmountNBO -TALER_amount_hton (struct TALER_Amount d) -{ - struct TALER_AmountNBO dn; - dn.value = htonl (d.value); - dn.fraction = htonl (d.fraction); - memcpy (dn.currency, d.currency, TALER_CURRENCY_LEN); - - return dn; -} - - -/** - * FIXME - */ -struct TALER_Amount -TALER_amount_ntoh (struct TALER_AmountNBO dn) -{ - struct TALER_Amount d; - d.value = ntohl (dn.value); - d.fraction = ntohl (dn.fraction); - memcpy (d.currency, dn.currency, sizeof(dn.currency)); - - return d; -} - - -/** - * Compare the value/fraction of two amounts. Does not compare the currency, - * i.e. comparing amounts with the same value and fraction but different - * currency would return 0. - * - * @param a1 first amount - * @param a2 second amount - * @return result of the comparison - */ -int -TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2) -{ - a1 = TALER_amount_normalize (a1); - a2 = TALER_amount_normalize (a2); - if (a1.value == a2.value) - { - if (a1.fraction < a2.fraction) - return -1; - if (a1.fraction > a2.fraction) - return 1; - return 0; - } - if (a1.value < a2.value) - return -1; - return 1; -} - - -/** - * Perform saturating subtraction of amounts. - * - * @param a1 amount to subtract from - * @param a2 amount to subtract - * @return (a1-a2) or 0 if a2>=a1 - */ -struct TALER_Amount -TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2) -{ - a1 = TALER_amount_normalize (a1); - a2 = TALER_amount_normalize (a2); - - if (a1.value < a2.value) - { - a1.value = 0; - a1.fraction = 0; - return a1; - } - - if (a1.fraction < a2.fraction) - { - if (0 == a1.value) - { - a1.fraction = 0; - return a1; - } - a1.fraction += AMOUNT_FRAC_BASE; - a1.value -= 1; - } - - a1.fraction -= a2.fraction; - a1.value -= a2.value; - - return a1; -} - - -/** - * Perform saturating addition of amounts. - * - * @param a1 first amount to add - * @param a2 second amount to add - * @return sum of a1 and a2 - */ -struct TALER_Amount -TALER_amount_add (struct TALER_Amount a1, struct TALER_Amount a2) -{ - a1 = TALER_amount_normalize (a1); - a2 = TALER_amount_normalize (a2); - - a1.value += a2.value; - a1.fraction += a2.fraction; - - if (0 == a1.currency[0]) - { - memcpy (a2.currency, a1.currency, TALER_CURRENCY_LEN); - } - - if (0 == a2.currency[0]) - { - memcpy (a1.currency, a2.currency, TALER_CURRENCY_LEN); - } - - if (0 != a1.currency[0] && 0 != memcmp (a1.currency, a2.currency, TALER_CURRENCY_LEN)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "adding mismatching currencies\n"); - } - - if (a1.value < a2.value) - { - a1.value = UINT32_MAX; - a2.value = UINT32_MAX; - return a1; - } - - return TALER_amount_normalize (a1); -} - - -/** - * Normalize the given amount. - * - * @param amout amount to normalize - * @return normalized amount - */ -struct TALER_Amount -TALER_amount_normalize (struct TALER_Amount amount) -{ - while (amount.value != UINT32_MAX && amount.fraction >= AMOUNT_FRAC_BASE) - { - amount.fraction -= AMOUNT_FRAC_BASE; - amount.value += 1; - } - return amount; -} - - -/** - * Convert amount to string. - * - * @param amount amount to convert to string - * @return freshly allocated string representation - */ -char * -TALER_amount_to_string (struct TALER_Amount amount) -{ - char tail[AMOUNT_FRAC_LEN + 1] = { 0 }; - char curr[TALER_CURRENCY_LEN + 1] = { 0 }; - char *result = NULL; - int len; - - memcpy (curr, amount.currency, TALER_CURRENCY_LEN); - - amount = TALER_amount_normalize (amount); - if (0 != amount.fraction) - { - unsigned int i; - uint32_t n = amount.fraction; - for (i = 0; (i < AMOUNT_FRAC_LEN) && (n != 0); i++) - { - tail[i] = '0' + (n / (AMOUNT_FRAC_BASE / 10)); - n = (n * 10) % (AMOUNT_FRAC_BASE); - } - tail[i] = 0; - len = GNUNET_asprintf (&result, "%s:%lu.%s", curr, (unsigned long) amount.value, tail); - } - else - { - len = GNUNET_asprintf (&result, "%s:%lu", curr, (unsigned long) amount.value); - } - GNUNET_assert (len > 0); - return result; -} - - - /** * Return the base32crockford encoding of the given buffer. * * The returned string will be freshly allocated, and must be free'd - * with GNUNET_free. + * with GNUNET_free(). * * @param buffer with data * @param size size of the buffer @@ -384,84 +60,4 @@ TALER_data_to_string_alloc (const void *buf, size_t size) } -/** - * Get encoded binary data from a configuration. - * - * @return GNUNET_OK on success - * GNUNET_NO is the value does not exist - * GNUNET_SYSERR on encoding error - */ -int -TALER_configuration_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *section, const char *option, - void *buf, size_t buf_size) -{ - char *enc; - int res; - size_t data_size; - if (GNUNET_OK != (res = GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &enc))) - return res; - data_size = (strlen (enc) * 5) / 8; - if (data_size != buf_size) - { - GNUNET_free (enc); - return GNUNET_SYSERR; - } - if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, strlen (enc), - buf, buf_size)) - { - GNUNET_free (enc); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -static void -derive_refresh_key (const struct GNUNET_HashCode *secret, - struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, - struct GNUNET_CRYPTO_SymmetricSessionKey *skey) -{ - static const char ctx_key[] = "taler-key-skey"; - static const char ctx_iv[] = "taler-key-iv"; - - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), - ctx_key, strlen (ctx_key), - secret, sizeof (struct GNUNET_HashCode), - NULL, 0)); - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), - ctx_iv, strlen (ctx_iv), - secret, sizeof (struct GNUNET_HashCode), - NULL, 0)); -} - - -int -TALER_refresh_decrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result) -{ - struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - struct GNUNET_CRYPTO_SymmetricSessionKey skey; - - derive_refresh_key (secret, &iv, &skey); - - return GNUNET_CRYPTO_symmetric_decrypt (input, input_size, &skey, &iv, result); -} - - -int -TALER_refresh_encrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result) -{ - struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - struct GNUNET_CRYPTO_SymmetricSessionKey skey; - - derive_refresh_key (secret, &iv, &skey); - - return GNUNET_CRYPTO_symmetric_encrypt (input, input_size, &skey, &iv, result); -} - - - - /* end of util.c */