diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-01-21 14:46:33 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-01-21 14:46:33 +0100 |
commit | 9c56c91c1f9879352e5be51ccb2447128e0cd735 (patch) | |
tree | 9ec4f90462fb54afa4e782827d1257dacf38fa33 | |
parent | c9a819a5efdc359fd8d7a3c32e497679c92d0741 (diff) | |
download | exchange-9c56c91c1f9879352e5be51ccb2447128e0cd735.tar.gz exchange-9c56c91c1f9879352e5be51ccb2447128e0cd735.zip |
separate DB logic for /refresh/reveal from parsing logic
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 343 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.h | 17 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_refresh.c | 370 |
3 files changed, 408 insertions, 322 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 | */ | ||
816 | static int | ||
817 | helper_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 | */ | ||
871 | int | ||
872 | TALER_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 | ||
diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index 093878674..2a03812aa 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h | |||
@@ -110,6 +110,23 @@ TALER_MINT_db_execute_refresh_commit (struct MHD_Connection *connection, | |||
110 | struct RefreshCommitLink *const* commit_link); | 110 | struct RefreshCommitLink *const* commit_link); |
111 | 111 | ||
112 | 112 | ||
113 | /** | ||
114 | * Execute a /refresh/reveal. | ||
115 | * | ||
116 | * @param connection the MHD connection to handle | ||
117 | * @param refresh_session_pub public key of the refresh session | ||
118 | * @param kappa size of x-dimension of @transfer_privs array plus one (!) | ||
119 | * @param num_oldcoins size of y-dimension of @transfer_privs array | ||
120 | * @param transfer_pubs array with the revealed transfer keys | ||
121 | * @return MHD result code | ||
122 | */ | ||
123 | int | ||
124 | TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, | ||
125 | const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, | ||
126 | unsigned int kappa, | ||
127 | unsigned int num_oldcoins, | ||
128 | struct GNUNET_CRYPTO_EcdsaPrivateKey *const*transfer_privs); | ||
129 | |||
113 | 130 | ||
114 | /** | 131 | /** |
115 | * Execute a /refresh/link. | 132 | * Execute a /refresh/link. |
diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index fc46a1d35..69ba87c29 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c | |||
@@ -483,6 +483,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, | |||
483 | return MHD_NO; | 483 | return MHD_NO; |
484 | } | 484 | } |
485 | res = GNUNET_MINT_parse_navigate_json (connection, root, | 485 | res = GNUNET_MINT_parse_navigate_json (connection, root, |
486 | JNAV_FIELD, "coin_evs", | ||
486 | JNAV_INDEX, (int) 0, | 487 | JNAV_INDEX, (int) 0, |
487 | JNAV_RET_DATA, | 488 | JNAV_RET_DATA, |
488 | JSON_ARRAY, &coin_detail); | 489 | JSON_ARRAY, &coin_detail); |
@@ -502,6 +503,7 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, | |||
502 | return MHD_NO; | 503 | return MHD_NO; |
503 | } | 504 | } |
504 | res = GNUNET_MINT_parse_navigate_json (connection, root, | 505 | res = GNUNET_MINT_parse_navigate_json (connection, root, |
506 | JNAV_FIELD, "transfer_pubs", | ||
505 | JNAV_INDEX, (int) 0, | 507 | JNAV_INDEX, (int) 0, |
506 | JNAV_RET_DATA, | 508 | JNAV_RET_DATA, |
507 | JSON_ARRAY, &coin_detail); | 509 | JSON_ARRAY, &coin_detail); |
@@ -653,59 +655,6 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh, | |||
653 | 655 | ||
654 | 656 | ||
655 | /** | 657 | /** |
656 | * Send response for "/refresh/reveal". | ||
657 | * | ||
658 | * @param connection the MHD connection | ||
659 | * @param db_conn the connection to the mint's db | ||
660 | * @param refresh_session_pub the refresh session's public key | ||
661 | * @return a MHD result code | ||
662 | */ | ||
663 | static int | ||
664 | helper_refresh_reveal_send_response (struct MHD_Connection *connection, | ||
665 | PGconn *db_conn, | ||
666 | struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub) | ||
667 | { | ||
668 | int res; | ||
669 | int newcoin_index; | ||
670 | struct RefreshSession refresh_session; | ||
671 | struct TALER_RSA_Signature *sigs; | ||
672 | |||
673 | res = TALER_MINT_DB_get_refresh_session (db_conn, | ||
674 | refresh_session_pub, | ||
675 | &refresh_session); | ||
676 | if (GNUNET_OK != res) | ||
677 | { | ||
678 | // FIXME: return 'internal error' | ||
679 | GNUNET_break (0); | ||
680 | return MHD_NO; | ||
681 | } | ||
682 | |||
683 | GNUNET_assert (0 != refresh_session.reveal_ok); | ||
684 | sigs = GNUNET_malloc (refresh_session.num_newcoins * | ||
685 | sizeof (struct TALER_RSA_Signature)); | ||
686 | for (newcoin_index = 0; newcoin_index < refresh_session.num_newcoins; newcoin_index++) | ||
687 | { | ||
688 | res = TALER_MINT_DB_get_refresh_collectable (db_conn, | ||
689 | newcoin_index, | ||
690 | refresh_session_pub, | ||
691 | &sigs[newcoin_index]); | ||
692 | if (GNUNET_OK != res) | ||
693 | { | ||
694 | // FIXME: return 'internal error' | ||
695 | GNUNET_break (0); | ||
696 | GNUNET_free (sigs); | ||
697 | return MHD_NO; | ||
698 | } | ||
699 | } | ||
700 | res = TALER_MINT_reply_refresh_reveal_success (connection, | ||
701 | refresh_session.num_newcoins, | ||
702 | sigs); | ||
703 | GNUNET_free (sigs); | ||
704 | return res; | ||
705 | } | ||
706 | |||
707 | |||
708 | /** | ||
709 | * Handle a "/refresh/reveal" request | 658 | * Handle a "/refresh/reveal" request |
710 | * | 659 | * |
711 | * @param rh context of the handler | 660 | * @param rh context of the handler |
@@ -724,12 +673,14 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh, | |||
724 | { | 673 | { |
725 | struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; | 674 | struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; |
726 | int res; | 675 | int res; |
727 | PGconn *db_conn; | 676 | unsigned int kappa; |
728 | struct RefreshSession refresh_session; | 677 | unsigned int num_oldcoins; |
729 | struct MintKeyState *key_state; | 678 | json_t *transfer_p; |
730 | int i; | 679 | json_t *reveal_detail; |
731 | int j; | 680 | unsigned int i; |
681 | unsigned int j; | ||
732 | json_t *root; | 682 | json_t *root; |
683 | struct GNUNET_CRYPTO_EcdsaPrivateKey **transfer_privs; | ||
733 | 684 | ||
734 | res = TALER_MINT_parse_post_json (connection, | 685 | res = TALER_MINT_parse_post_json (connection, |
735 | connection_cls, | 686 | connection_cls, |
@@ -753,279 +704,60 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh, | |||
753 | } | 704 | } |
754 | 705 | ||
755 | 706 | ||
756 | 707 | /* Determine dimensionality of the request (kappa and #old coins) */ | |
757 | if (NULL == (db_conn = TALER_MINT_DB_get_connection ())) | 708 | res = GNUNET_MINT_parse_navigate_json (connection, root, |
758 | { | 709 | JNAV_FIELD, "transfer_privs", |
759 | GNUNET_break (0); | 710 | JNAV_RET_TYPED_JSON, JSON_ARRAY, &transfer_p); |
760 | // FIXME: return 'internal error'? | 711 | if (GNUNET_OK != res) |
761 | return MHD_NO; | 712 | return res; |
762 | } | 713 | kappa = json_array_size (transfer_p) + 1; /* 1 row is missing */ |
763 | 714 | if (3 > kappa) | |
764 | /* Send response immediately if we already know the session, | ||
765 | * and the session commited already. | ||
766 | * Do _not_ care about fields other than session_pub in this case. */ | ||
767 | |||
768 | res = TALER_MINT_DB_get_refresh_session (db_conn, | ||
769 | &refresh_session_pub, | ||
770 | &refresh_session); | ||
771 | if (GNUNET_YES == res && 0 != refresh_session.reveal_ok) | ||
772 | return helper_refresh_reveal_send_response (connection, | ||
773 | db_conn, | ||
774 | &refresh_session_pub); | ||
775 | if (GNUNET_SYSERR == res) | ||
776 | { | 715 | { |
777 | GNUNET_break (0); | 716 | GNUNET_break_op (0); |
778 | // FIXME: return 'internal error'? | 717 | // FIXME: generate error message |
779 | return MHD_NO; | 718 | return MHD_NO; |
780 | } | 719 | } |
720 | res = GNUNET_MINT_parse_navigate_json (connection, root, | ||
721 | JNAV_FIELD, "transfer_privs", | ||
722 | JNAV_INDEX, 0, | ||
723 | JNAV_RET_TYPED_JSON, JSON_ARRAY, &reveal_detail); | ||
724 | if (GNUNET_OK != res) | ||
725 | return res; | ||
726 | num_oldcoins = json_array_size (reveal_detail); | ||
781 | 727 | ||
782 | /* Check that the transfer private keys match their commitments. | ||
783 | * Then derive the shared secret for each kappa, and check that they match. */ | ||
784 | 728 | ||
785 | for (i = 0; i < refresh_session.kappa; i++) | 729 | transfer_privs = GNUNET_malloc ((kappa - 1) * |
730 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey *)); | ||
731 | for (i = 0; i < kappa - 1; i++) | ||
786 | { | 732 | { |
787 | struct GNUNET_HashCode last_shared_secret; | 733 | transfer_privs[i] = GNUNET_malloc (num_oldcoins * |
788 | int secret_initialized = GNUNET_NO; | 734 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); |
789 | 735 | for (j = 0; j < num_oldcoins; j++) | |
790 | if (i == (refresh_session.noreveal_index % refresh_session.kappa)) | ||
791 | continue; | ||
792 | |||
793 | for (j = 0; j < refresh_session.num_oldcoins; j++) | ||
794 | { | ||
795 | struct GNUNET_CRYPTO_EcdsaPrivateKey transfer_priv; | ||
796 | struct RefreshCommitLink commit_link; | ||
797 | struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; | ||
798 | struct GNUNET_HashCode transfer_secret; | ||
799 | struct GNUNET_HashCode shared_secret; | ||
800 | |||
801 | res = GNUNET_MINT_parse_navigate_json (connection, root, | ||
802 | JNAV_FIELD, "transfer_privs", | ||
803 | JNAV_INDEX, (int) i, | ||
804 | JNAV_INDEX, (int) j, | ||
805 | JNAV_RET_DATA, | ||
806 | &transfer_priv, | ||
807 | sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); | ||
808 | |||
809 | if (GNUNET_OK != res) | ||
810 | { | ||
811 | GNUNET_break (GNUNET_SYSERR != res); | ||
812 | return res; | ||
813 | } | ||
814 | |||
815 | res = TALER_MINT_DB_get_refresh_commit_link (db_conn, | ||
816 | &refresh_session_pub, | ||
817 | i, j, | ||
818 | &commit_link); | ||
819 | if (GNUNET_OK != res) | ||
820 | { | 736 | { |
821 | GNUNET_break (0); | 737 | res = GNUNET_MINT_parse_navigate_json (connection, root, |
738 | JNAV_FIELD, "transfer_privs", | ||
739 | JNAV_INDEX, (int) i, | ||
740 | JNAV_INDEX, (int) j, | ||
741 | JNAV_RET_DATA, | ||
742 | &transfer_privs[i][j], | ||
743 | sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); | ||
744 | if (GNUNET_OK != res) | ||
745 | { | ||
746 | GNUNET_break (0); | ||
822 | // FIXME: return 'internal error'? | 747 | // FIXME: return 'internal error'? |
823 | return MHD_NO; | 748 | return MHD_NO; |
749 | } | ||
824 | } | 750 | } |
825 | |||
826 | res = TALER_MINT_DB_get_refresh_melt (db_conn, &refresh_session_pub, j, &coin_pub); | ||
827 | if (GNUNET_OK != res) | ||
828 | { | ||
829 | GNUNET_break (0); | ||
830 | // FIXME: return 'internal error'? | ||
831 | return MHD_NO; | ||
832 | } | ||
833 | |||
834 | /* We're converting key types here, which is not very nice | ||
835 | * but necessary and harmless (keys will be thrown away later). */ | ||
836 | if (GNUNET_OK != GNUNET_CRYPTO_ecc_ecdh ((struct GNUNET_CRYPTO_EcdhePrivateKey *) &transfer_priv, | ||
837 | (struct GNUNET_CRYPTO_EcdhePublicKey *) &coin_pub, | ||
838 | &transfer_secret)) | ||
839 | { | ||
840 | GNUNET_break (0); | ||
841 | // FIXME: return 'internal error'? | ||
842 | return MHD_NO; | ||
843 | } | ||
844 | |||
845 | if (0 >= TALER_refresh_decrypt (commit_link.shared_secret_enc, TALER_REFRESH_SHARED_SECRET_LENGTH, | ||
846 | &transfer_secret, &shared_secret)) | ||
847 | { | ||
848 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n"); | ||
849 | // FIXME: return 'internal error'? | ||
850 | return MHD_NO; | ||
851 | } | ||
852 | |||
853 | if (GNUNET_NO == secret_initialized) | ||
854 | { | ||
855 | secret_initialized = GNUNET_YES; | ||
856 | last_shared_secret = shared_secret; | ||
857 | } | ||
858 | else if (0 != memcmp (&shared_secret, &last_shared_secret, sizeof (struct GNUNET_HashCode))) | ||
859 | { | ||
860 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "shared secrets do not match\n"); | ||
861 | // FIXME: return error code! | ||
862 | return MHD_NO; | ||
863 | } | ||
864 | |||
865 | { | ||
866 | struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub_check; | ||
867 | GNUNET_CRYPTO_ecdsa_key_get_public (&transfer_priv, &transfer_pub_check); | ||
868 | if (0 != memcmp (&transfer_pub_check, &commit_link.transfer_pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
869 | { | ||
870 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "transfer keys do not match\n"); | ||
871 | // FIXME: return error code! | ||
872 | return MHD_NO; | ||
873 | } | ||
874 | } | ||
875 | } | ||
876 | |||
877 | /* Check that the commitments for all new coins were correct */ | ||
878 | |||
879 | for (j = 0; j < refresh_session.num_newcoins; j++) | ||
880 | { | ||
881 | struct RefreshCommitCoin commit_coin; | ||
882 | struct LinkData link_data; | ||
883 | struct TALER_RSA_BlindedSignaturePurpose *coin_ev_check; | ||
884 | struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; | ||
885 | struct TALER_RSA_BlindingKey *bkey; | ||
886 | struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; | ||
887 | |||
888 | bkey = NULL; | ||
889 | res = TALER_MINT_DB_get_refresh_commit_coin (db_conn, | ||
890 | &refresh_session_pub, | ||
891 | i, j, | ||
892 | &commit_coin); | ||
893 | if (GNUNET_OK != res) | ||
894 | { | ||
895 | GNUNET_break (0); | ||
896 | // FIXME: return error code! | ||
897 | return MHD_NO; | ||
898 | } | ||
899 | |||
900 | |||
901 | if (0 >= TALER_refresh_decrypt (commit_coin.link_enc, sizeof (struct LinkData), | ||
902 | &last_shared_secret, &link_data)) | ||
903 | { | ||
904 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n"); | ||
905 | // FIXME: return error code! | ||
906 | return MHD_NO; | ||
907 | } | ||
908 | |||
909 | GNUNET_CRYPTO_ecdsa_key_get_public (&link_data.coin_priv, &coin_pub); | ||
910 | if (NULL == (bkey = TALER_RSA_blinding_key_decode (&link_data.bkey_enc))) | ||
911 | { | ||
912 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid blinding key\n"); | ||
913 | // FIXME: return error code! | ||
914 | return MHD_NO; | ||
915 | } | ||
916 | res = TALER_MINT_DB_get_refresh_order (db_conn, j, &refresh_session_pub, &denom_pub); | ||
917 | if (GNUNET_OK != res) | ||
918 | { | ||
919 | GNUNET_break (0); | ||
920 | // FIXME: return error code! | ||
921 | return MHD_NO; | ||
922 | } | ||
923 | if (NULL == (coin_ev_check = | ||
924 | TALER_RSA_message_blind (&coin_pub, | ||
925 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), | ||
926 | bkey, | ||
927 | &denom_pub))) | ||
928 | { | ||
929 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind failed\n"); | ||
930 | // FIXME: return error code! | ||
931 | return MHD_NO; | ||
932 | } | ||
933 | |||
934 | if (0 != memcmp (&coin_ev_check, | ||
935 | &commit_coin.coin_ev, | ||
936 | sizeof (struct TALER_RSA_BlindedSignaturePurpose))) | ||
937 | { | ||
938 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind envelope does not match for kappa=%d, old=%d\n", | ||
939 | (int) i, (int) j); | ||
940 | // FIXME: return error code! | ||
941 | return MHD_NO; | ||
942 | } | ||
943 | } | ||
944 | } | 751 | } |
945 | 752 | ||
946 | 753 | ||
947 | if (GNUNET_OK != TALER_MINT_DB_transaction (db_conn)) | 754 | res = TALER_MINT_db_execute_refresh_reveal (connection, |
948 | { | 755 | &refresh_session_pub, |
949 | GNUNET_break (0); | 756 | kappa, |
950 | // FIXME: return error code! | 757 | num_oldcoins, |
951 | return MHD_NO; | 758 | transfer_privs); |
952 | } | 759 | // FIXME: free memory |
953 | 760 | return res; | |
954 | for (j = 0; j < refresh_session.num_newcoins; j++) | ||
955 | { | ||
956 | struct RefreshCommitCoin commit_coin; | ||
957 | struct TALER_RSA_PublicKeyBinaryEncoded denom_pub; | ||
958 | struct TALER_MINT_DenomKeyIssuePriv *dki; | ||
959 | struct TALER_RSA_Signature ev_sig; | ||
960 | |||
961 | res = TALER_MINT_DB_get_refresh_commit_coin (db_conn, | ||
962 | &refresh_session_pub, | ||
963 | refresh_session.noreveal_index % refresh_session.kappa, | ||
964 | j, | ||
965 | &commit_coin); | ||
966 | if (GNUNET_OK != res) | ||
967 | { | ||
968 | GNUNET_break (0); | ||
969 | // FIXME: return error code! | ||
970 | return MHD_NO; | ||
971 | } | ||
972 | res = TALER_MINT_DB_get_refresh_order (db_conn, j, &refresh_session_pub, &denom_pub); | ||
973 | if (GNUNET_OK != res) | ||
974 | { | ||
975 | GNUNET_break (0); | ||
976 | // FIXME: return error code! | ||
977 | return MHD_NO; | ||
978 | } | ||
979 | |||
980 | |||
981 | key_state = TALER_MINT_key_state_acquire (); | ||
982 | dki = TALER_MINT_get_denom_key (key_state, &denom_pub); | ||
983 | TALER_MINT_key_state_release (key_state); | ||
984 | if (NULL == dki) | ||
985 | { | ||
986 | GNUNET_break (0); | ||
987 | // FIXME: return error code! | ||
988 | return MHD_NO; | ||
989 | } | ||
990 | if (GNUNET_OK != | ||
991 | TALER_RSA_sign (dki->denom_priv, | ||
992 | &commit_coin.coin_ev, | ||
993 | sizeof (struct TALER_RSA_BlindedSignaturePurpose), | ||
994 | &ev_sig)) | ||
995 | { | ||
996 | GNUNET_break (0); | ||
997 | // FIXME: return error code! | ||
998 | return MHD_NO; | ||
999 | } | ||
1000 | |||
1001 | res = TALER_MINT_DB_insert_refresh_collectable (db_conn, | ||
1002 | j, | ||
1003 | &refresh_session_pub, | ||
1004 | &ev_sig); | ||
1005 | if (GNUNET_OK != res) | ||
1006 | { | ||
1007 | GNUNET_break (0); | ||
1008 | // FIXME: return error code! | ||
1009 | return MHD_NO; | ||
1010 | } | ||
1011 | } | ||
1012 | /* mark that reveal was successful */ | ||
1013 | |||
1014 | res = TALER_MINT_DB_set_reveal_ok (db_conn, &refresh_session_pub); | ||
1015 | if (GNUNET_OK != res) | ||
1016 | { | ||
1017 | GNUNET_break (0); | ||
1018 | // FIXME: return error code! | ||
1019 | return MHD_NO; | ||
1020 | } | ||
1021 | |||
1022 | if (GNUNET_OK != TALER_MINT_DB_commit (db_conn)) | ||
1023 | { | ||
1024 | GNUNET_break (0); | ||
1025 | return MHD_NO; | ||
1026 | } | ||
1027 | |||
1028 | return helper_refresh_reveal_send_response (connection, db_conn, &refresh_session_pub); | ||
1029 | } | 761 | } |
1030 | 762 | ||
1031 | 763 | ||