diff --git a/src/include/taler_util.h b/src/include/taler_util.h index db6f22e68..19e6bacf1 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -240,6 +240,30 @@ TALER_data_to_string_alloc (const void *buf, /* ****************** Refresh crypto primitives ************* */ +/** + * Secret used to decrypt refresh links. + */ +struct TALER_LinkSecret +{ + /** + * Secret used to decrypt the refresh link data. + */ + char key[sizeof (struct GNUNET_HashCode)]; +}; + + +/** + * Encrypted secret used to decrypt refresh links. + */ +struct TALER_EncryptedLinkSecret +{ + /** + * Encrypted secret, must be the given size! + */ + char enc[sizeof (struct TALER_LinkSecret)]; +}; + + /** * Representation of an encrypted refresh link. */ @@ -295,9 +319,24 @@ struct TALER_RefreshLinkDecrypted * @return #GNUNET_OK on success */ int -TALER_transfer_decrypt (const struct GNUNET_HashCode *secret_enc, +TALER_transfer_decrypt (const struct TALER_EncryptedLinkSecret *secret_enc, const struct GNUNET_HashCode *trans_sec, - struct GNUNET_HashCode *secret); + struct TALER_LinkSecret *secret); + + +/** + * Use the @a trans_sec (from ECDHE) to encrypt the @a secret + * to obtain the @a secret_enc. + * + * @param secret shared secret for refresh link decryption + * @param trans_sec transfer secret (FIXME: use different type?) + * @param secret_enc[out] encrypted secret + * @return #GNUNET_OK on success + */ +int +TALER_transfer_encrypt (const struct TALER_LinkSecret *secret, + const struct GNUNET_HashCode *trans_sec, + struct TALER_EncryptedLinkSecret *secret_enc); /** @@ -309,7 +348,7 @@ TALER_transfer_decrypt (const struct GNUNET_HashCode *secret_enc, */ struct TALER_RefreshLinkDecrypted * TALER_refresh_decrypt (const struct TALER_RefreshLinkEncrypted *input, - const struct GNUNET_HashCode *secret); + const struct TALER_LinkSecret *secret); /** @@ -321,7 +360,7 @@ TALER_refresh_decrypt (const struct TALER_RefreshLinkEncrypted *input, */ struct TALER_RefreshLinkEncrypted * TALER_refresh_encrypt (const struct TALER_RefreshLinkDecrypted *input, - const struct GNUNET_HashCode *secret); + const struct TALER_LinkSecret *secret); #endif diff --git a/src/mint/mint.h b/src/mint/mint.h index bf8dfcfd3..046b9c17e 100644 --- a/src/mint/mint.h +++ b/src/mint/mint.h @@ -179,10 +179,9 @@ struct RefreshCommitLink struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; /** - * FIXME: this is the encrypted shared secret, should use - * a different type... + * Encrypted shared secret to decrypt the link. */ - struct GNUNET_HashCode shared_secret_enc; + struct TALER_EncryptedLinkSecret shared_secret_enc; }; diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 9ddce104d..8f7553896 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -908,7 +908,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, off = 0; for (i = 0; i < refresh_session.kappa - 1; i++) { - struct GNUNET_HashCode last_shared_secret; + struct TALER_LinkSecret last_shared_secret; int secret_initialized = GNUNET_NO; if (i == refresh_session.noreveal_index) @@ -919,7 +919,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, struct RefreshCommitLink commit_link; struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; struct GNUNET_HashCode transfer_secret; - struct GNUNET_HashCode shared_secret; + struct TALER_LinkSecret shared_secret; res = TALER_MINT_DB_get_refresh_commit_link (db_conn, refresh_session_pub, diff --git a/src/util/crypto.c b/src/util/crypto.c index 930c43a7f..65c586d75 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -30,24 +30,34 @@ #define CURVE "Ed25519" - +/** + * Function called by libgcrypt on serious errors. + * Prints an error message and aborts the process. + * + * @param cls NULL + * @param wtf unknown + * @param msg error message + */ static void -fatal_error_handler (void *cls, int wtf, const char *msg) +fatal_error_handler (void *cls, + int wtf, + const char *msg) { - LOG_ERROR("Fatal error in Gcrypt: %s\n", msg); + LOG_ERROR ("Fatal error in libgcrypt: %s\n", + msg); abort(); } /** - * Initialize Gcrypt library. + * Initialize libgcrypt. */ void -TALER_gcrypt_init() +TALER_gcrypt_init () { gcry_set_fatalerror_handler (&fatal_error_handler, NULL); - TALER_assert_as(gcry_check_version(NEED_LIBGCRYPT_VERSION), - "libgcrypt version mismatch"); + 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); @@ -56,19 +66,48 @@ TALER_gcrypt_init() /** * Derive symmetric key material for refresh operations from - * a given shared secret. + * a given shared secret for link decryption. * * @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, +derive_refresh_key (const struct TALER_LinkSecret *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"; + static const char ctx_key[] = "taler-link-skey"; + static const char ctx_iv[] = "taler-link-iv"; + + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), + ctx_key, strlen (ctx_key), + secret, sizeof (struct TALER_LinkSecret), + NULL, 0)); + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), + ctx_iv, strlen (ctx_iv), + secret, sizeof (struct TALER_LinkSecret), + NULL, 0)); +} + + +/** + * Derive symmetric key material for refresh operations from + * a given shared secret for key decryption. + * + * @param secret the shared secret + * @param[out] iv set to initialization vector + * @param[out] skey set to session key + */ +static void +derive_transfer_key (const struct GNUNET_HashCode *secret, + struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, + struct GNUNET_CRYPTO_SymmetricSessionKey *skey) +{ + static const char ctx_key[] = "taler-transfer-skey"; + static const char ctx_iv[] = "taler-transfer-iv"; GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), @@ -87,29 +126,58 @@ derive_refresh_key (const struct GNUNET_HashCode *secret, * Use the @a trans_sec (from ECDHE) to decrypt the @a secret_enc * to obtain the @a secret to decrypt the linkage data. * - * @param secret_enc encrypted secret (FIXME: use different type!) + * @param secret_enc encrypted secret * @param trans_sec transfer secret (FIXME: use different type?) * @param secret shared secret for refresh link decryption - * (FIXME: use different type?) * @return #GNUNET_OK on success */ int -TALER_transfer_decrypt (const struct GNUNET_HashCode *secret_enc, +TALER_transfer_decrypt (const struct TALER_EncryptedLinkSecret *secret_enc, const struct GNUNET_HashCode *trans_sec, - struct GNUNET_HashCode *secret) + struct TALER_LinkSecret *secret) { struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_SymmetricSessionKey skey; - derive_refresh_key (trans_sec, &iv, &skey); + GNUNET_assert (sizeof (struct TALER_EncryptedLinkSecret) == + sizeof (struct TALER_LinkSecret)); + derive_transfer_key (trans_sec, &iv, &skey); return GNUNET_CRYPTO_symmetric_decrypt (secret_enc, - sizeof (struct GNUNET_HashCode), + sizeof (struct TALER_LinkSecret), &skey, &iv, secret); } +/** + * Use the @a trans_sec (from ECDHE) to encrypt the @a secret + * to obtain the @a secret_enc. + * + * @param secret shared secret for refresh link decryption + * @param trans_sec transfer secret (FIXME: use different type?) + * @param secret_enc[out] encrypted secret + * @return #GNUNET_OK on success + */ +int +TALER_transfer_encrypt (const struct TALER_LinkSecret *secret, + const struct GNUNET_HashCode *trans_sec, + struct TALER_EncryptedLinkSecret *secret_enc) +{ + struct GNUNET_CRYPTO_SymmetricInitializationVector iv; + struct GNUNET_CRYPTO_SymmetricSessionKey skey; + + GNUNET_assert (sizeof (struct TALER_EncryptedLinkSecret) == + sizeof (struct TALER_LinkSecret)); + derive_transfer_key (trans_sec, &iv, &skey); + return GNUNET_CRYPTO_symmetric_encrypt (secret, + sizeof (struct TALER_LinkSecret), + &skey, + &iv, + secret_enc); +} + + /** * Decrypt refresh link information. * @@ -119,7 +187,7 @@ TALER_transfer_decrypt (const struct GNUNET_HashCode *secret_enc, */ struct TALER_RefreshLinkDecrypted * TALER_refresh_decrypt (const struct TALER_RefreshLinkEncrypted *input, - const struct GNUNET_HashCode *secret) + const struct TALER_LinkSecret *secret) { struct TALER_RefreshLinkDecrypted *ret; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; @@ -162,7 +230,7 @@ TALER_refresh_decrypt (const struct TALER_RefreshLinkEncrypted *input, */ struct TALER_RefreshLinkEncrypted * TALER_refresh_encrypt (const struct TALER_RefreshLinkDecrypted *input, - const struct GNUNET_HashCode *secret) + const struct TALER_LinkSecret *secret) { char *b_buf; size_t b_buf_size;