aboutsummaryrefslogtreecommitdiff
path: root/src/mint/taler-mint-httpd_refresh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mint/taler-mint-httpd_refresh.c')
-rw-r--r--src/mint/taler-mint-httpd_refresh.c370
1 files changed, 51 insertions, 319 deletions
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 */
663static int
664helper_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