aboutsummaryrefslogtreecommitdiff
path: root/src/mint/taler-mint-httpd_db.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mint/taler-mint-httpd_db.c')
-rw-r--r--src/mint/taler-mint-httpd_db.c343
1 files changed, 340 insertions, 3 deletions
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c
index bcdda621a..a581d486b 100644
--- a/src/mint/taler-mint-httpd_db.c
+++ b/src/mint/taler-mint-httpd_db.c
@@ -794,8 +794,6 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection,
794 return MHD_NO; 794 return MHD_NO;
795 } 795 }
796 796
797
798
799 if (GNUNET_OK != TALER_MINT_DB_commit (db_conn)) 797 if (GNUNET_OK != TALER_MINT_DB_commit (db_conn))
800 { 798 {
801 // FIXME: return 'internal error'? 799 // FIXME: return 'internal error'?
@@ -804,7 +802,346 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection,
804 } 802 }
805 803
806 return TALER_MINT_reply_refresh_commit_success (connection, &refresh_session); 804 return TALER_MINT_reply_refresh_commit_success (connection, &refresh_session);
807 } 805}
806
807
808/**
809 * Send response for "/refresh/reveal".
810 *
811 * @param connection the MHD connection
812 * @param db_conn the connection to the mint's db
813 * @param refresh_session_pub the refresh session's public key
814 * @return a MHD result code
815 */
816static int
817helper_refresh_reveal_send_response (struct MHD_Connection *connection,
818 PGconn *db_conn,
819 const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub)
820{
821 int res;
822 int newcoin_index;
823 struct RefreshSession refresh_session;
824 struct TALER_RSA_Signature *sigs;
825
826 res = TALER_MINT_DB_get_refresh_session (db_conn,
827 refresh_session_pub,
828 &refresh_session);
829 if (GNUNET_OK != res)
830 {
831 // FIXME: return 'internal error'
832 GNUNET_break (0);
833 return MHD_NO;
834 }
835
836 GNUNET_assert (0 != refresh_session.reveal_ok);
837 sigs = GNUNET_malloc (refresh_session.num_newcoins *
838 sizeof (struct TALER_RSA_Signature));
839 for (newcoin_index = 0; newcoin_index < refresh_session.num_newcoins; newcoin_index++)
840 {
841 res = TALER_MINT_DB_get_refresh_collectable (db_conn,
842 newcoin_index,
843 refresh_session_pub,
844 &sigs[newcoin_index]);
845 if (GNUNET_OK != res)
846 {
847 // FIXME: return 'internal error'
848 GNUNET_break (0);
849 GNUNET_free (sigs);
850 return MHD_NO;
851 }
852 }
853 res = TALER_MINT_reply_refresh_reveal_success (connection,
854 refresh_session.num_newcoins,
855 sigs);
856 GNUNET_free (sigs);
857 return res;
858}
859
860
861/**
862 * Execute a /refresh/reveal.
863 *
864 * @param connection the MHD connection to handle
865 * @param refresh_session_pub public key of the refresh session
866 * @param kappa size of x-dimension of @transfer_privs array plus one (!)
867 * @param num_oldcoins size of y-dimension of @transfer_privs array
868 * @param transfer_pubs array with the revealed transfer keys
869 * @return MHD result code
870 */
871int
872TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection,
873 const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub,
874 unsigned int kappa,
875 unsigned int num_oldcoins,
876 struct GNUNET_CRYPTO_EcdsaPrivateKey *const*transfer_privs)
877{
878 int res;
879 PGconn *db_conn;
880 struct RefreshSession refresh_session;
881 struct MintKeyState *key_state;
882 unsigned int i;
883 unsigned int j;
884 unsigned int off;
885
886 if (NULL == (db_conn = TALER_MINT_DB_get_connection ()))
887 {
888 GNUNET_break (0);
889 // FIXME: return 'internal error'?
890 return MHD_NO;
891 }
892
893 /* Send response immediately if we already know the session,
894 * and the session commited already.
895 * Do _not_ care about fields other than session_pub in this case. */
896
897 res = TALER_MINT_DB_get_refresh_session (db_conn,
898 refresh_session_pub,
899 &refresh_session);
900 if (GNUNET_YES == res && 0 != refresh_session.reveal_ok)
901 return helper_refresh_reveal_send_response (connection,
902 db_conn,
903 refresh_session_pub);
904 if (GNUNET_SYSERR == res)
905 {
906 GNUNET_break (0);
907 // FIXME: return 'internal error'?
908 return MHD_NO;
909 }
910
911 /* Check that the transfer private keys match their commitments.
912 * Then derive the shared secret for each kappa, and check that they match. */
913
914 off = 0;
915 for (i = 0; i < refresh_session.kappa - 1; i++)
916 {
917 struct GNUNET_HashCode last_shared_secret;
918 int secret_initialized = GNUNET_NO;
919
920 if (i == refresh_session.noreveal_index)
921 off = 1;
922
923 for (j = 0; j < refresh_session.num_oldcoins; j++)
924 {
925 struct RefreshCommitLink commit_link;
926 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
927 struct GNUNET_HashCode transfer_secret;
928 struct GNUNET_HashCode shared_secret;
929
930 res = TALER_MINT_DB_get_refresh_commit_link (db_conn,
931 refresh_session_pub,
932 i + off, j,
933 &commit_link);
934 if (GNUNET_OK != res)
935 {
936 GNUNET_break (0);
937 // FIXME: return 'internal error'?
938 return MHD_NO;
939 }
940
941 res = TALER_MINT_DB_get_refresh_melt (db_conn, refresh_session_pub, j, &coin_pub);
942 if (GNUNET_OK != res)
943 {
944 GNUNET_break (0);
945 // FIXME: return 'internal error'?
946 return MHD_NO;
947 }
948
949 /* We're converting key types here, which is not very nice
950 * but necessary and harmless (keys will be thrown away later). */
951 if (GNUNET_OK != GNUNET_CRYPTO_ecc_ecdh ((struct GNUNET_CRYPTO_EcdhePrivateKey *) &transfer_privs[i+off][j],
952 (struct GNUNET_CRYPTO_EcdhePublicKey *) &coin_pub,
953 &transfer_secret))
954 {
955 GNUNET_break (0);
956 // FIXME: return 'internal error'?
957 return MHD_NO;
958 }
959
960 if (0 >= TALER_refresh_decrypt (commit_link.shared_secret_enc, TALER_REFRESH_SHARED_SECRET_LENGTH,
961 &transfer_secret, &shared_secret))
962 {
963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
964 // FIXME: return 'internal error'?
965 return MHD_NO;
966 }
967
968 if (GNUNET_NO == secret_initialized)
969 {
970 secret_initialized = GNUNET_YES;
971 last_shared_secret = shared_secret;
972 }
973 else if (0 != memcmp (&shared_secret, &last_shared_secret, sizeof (struct GNUNET_HashCode)))
974 {
975 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "shared secrets do not match\n");
976 // FIXME: return error code!
977 return MHD_NO;
978 }
979
980 {
981 struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub_check;
982 GNUNET_CRYPTO_ecdsa_key_get_public (&transfer_privs[i+off][j], &transfer_pub_check);
983 if (0 != memcmp (&transfer_pub_check, &commit_link.transfer_pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
984 {
985 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "transfer keys do not match\n");
986 // FIXME: return error code!
987 return MHD_NO;
988 }
989 }
990 }
991
992 /* Check that the commitments for all new coins were correct */
993
994 for (j = 0; j < refresh_session.num_newcoins; j++)
995 {
996 struct RefreshCommitCoin commit_coin;
997 struct LinkData link_data;
998 struct TALER_RSA_BlindedSignaturePurpose *coin_ev_check;
999 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
1000 struct TALER_RSA_BlindingKey *bkey;
1001 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
1002
1003 bkey = NULL;
1004 res = TALER_MINT_DB_get_refresh_commit_coin (db_conn,
1005 refresh_session_pub,
1006 i+off, j,
1007 &commit_coin);
1008 if (GNUNET_OK != res)
1009 {
1010 GNUNET_break (0);
1011 // FIXME: return error code!
1012 return MHD_NO;
1013 }
1014
1015
1016 if (0 >= TALER_refresh_decrypt (commit_coin.link_enc, sizeof (struct LinkData),
1017 &last_shared_secret, &link_data))
1018 {
1019 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1020 // FIXME: return error code!
1021 return MHD_NO;
1022 }
1023
1024 GNUNET_CRYPTO_ecdsa_key_get_public (&link_data.coin_priv, &coin_pub);
1025 if (NULL == (bkey = TALER_RSA_blinding_key_decode (&link_data.bkey_enc)))
1026 {
1027 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid blinding key\n");
1028 // FIXME: return error code!
1029 return MHD_NO;
1030 }
1031 res = TALER_MINT_DB_get_refresh_order (db_conn, j, refresh_session_pub, &denom_pub);
1032 if (GNUNET_OK != res)
1033 {
1034 GNUNET_break (0);
1035 // FIXME: return error code!
1036 return MHD_NO;
1037 }
1038 if (NULL == (coin_ev_check =
1039 TALER_RSA_message_blind (&coin_pub,
1040 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
1041 bkey,
1042 &denom_pub)))
1043 {
1044 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind failed\n");
1045 // FIXME: return error code!
1046 return MHD_NO;
1047 }
1048
1049 if (0 != memcmp (&coin_ev_check,
1050 &commit_coin.coin_ev,
1051 sizeof (struct TALER_RSA_BlindedSignaturePurpose)))
1052 {
1053 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind envelope does not match for kappa=%d, old=%d\n",
1054 (int) (i+off), (int) j);
1055 // FIXME: return error code!
1056 return MHD_NO;
1057 }
1058 }
1059 }
1060
1061
1062 if (GNUNET_OK != TALER_MINT_DB_transaction (db_conn))
1063 {
1064 GNUNET_break (0);
1065 // FIXME: return error code!
1066 return MHD_NO;
1067 }
1068
1069 for (j = 0; j < refresh_session.num_newcoins; j++)
1070 {
1071 struct RefreshCommitCoin commit_coin;
1072 struct TALER_RSA_PublicKeyBinaryEncoded denom_pub;
1073 struct TALER_MINT_DenomKeyIssuePriv *dki;
1074 struct TALER_RSA_Signature ev_sig;
1075
1076 res = TALER_MINT_DB_get_refresh_commit_coin (db_conn,
1077 refresh_session_pub,
1078 refresh_session.noreveal_index % refresh_session.kappa,
1079 j,
1080 &commit_coin);
1081 if (GNUNET_OK != res)
1082 {
1083 GNUNET_break (0);
1084 // FIXME: return error code!
1085 return MHD_NO;
1086 }
1087 res = TALER_MINT_DB_get_refresh_order (db_conn, j, refresh_session_pub, &denom_pub);
1088 if (GNUNET_OK != res)
1089 {
1090 GNUNET_break (0);
1091 // FIXME: return error code!
1092 return MHD_NO;
1093 }
1094
1095
1096 key_state = TALER_MINT_key_state_acquire ();
1097 dki = TALER_MINT_get_denom_key (key_state, &denom_pub);
1098 TALER_MINT_key_state_release (key_state);
1099 if (NULL == dki)
1100 {
1101 GNUNET_break (0);
1102 // FIXME: return error code!
1103 return MHD_NO;
1104 }
1105 if (GNUNET_OK !=
1106 TALER_RSA_sign (dki->denom_priv,
1107 &commit_coin.coin_ev,
1108 sizeof (struct TALER_RSA_BlindedSignaturePurpose),
1109 &ev_sig))
1110 {
1111 GNUNET_break (0);
1112 // FIXME: return error code!
1113 return MHD_NO;
1114 }
1115
1116 res = TALER_MINT_DB_insert_refresh_collectable (db_conn,
1117 j,
1118 refresh_session_pub,
1119 &ev_sig);
1120 if (GNUNET_OK != res)
1121 {
1122 GNUNET_break (0);
1123 // FIXME: return error code!
1124 return MHD_NO;
1125 }
1126 }
1127 /* mark that reveal was successful */
1128
1129 res = TALER_MINT_DB_set_reveal_ok (db_conn, refresh_session_pub);
1130 if (GNUNET_OK != res)
1131 {
1132 GNUNET_break (0);
1133 // FIXME: return error code!
1134 return MHD_NO;
1135 }
1136
1137 if (GNUNET_OK != TALER_MINT_DB_commit (db_conn))
1138 {
1139 GNUNET_break (0);
1140 return MHD_NO;
1141 }
1142
1143 return helper_refresh_reveal_send_response (connection, db_conn, refresh_session_pub);
1144}
808 1145
809 1146
810 1147