#ifndef MAIN_INCLUDE_CONTROLLER_H_ #define MAIN_INCLUDE_CONTROLLER_H_ /** * @file controller.h * @brief definition of controllers. * */ #include #include #include #include "string.h" #include "esp_log.h" #include "mbedtls/base64.h" #include "mbedtls/asn1.h" #include "mbedtls/asn1write.h" #include "mbedtls/sha256.h" #include "expat.h" #include "module.h" #include "model.h" #include "view.h" /** * \class Controller * * \brief abstract class Controller. C in MVC, * * Controllers are bridge between views and models. They take data from model, modify it if required and pass it to the view to present to client. * It has one main method - index(), which is called when controller is reached. * However, depending on their complexity , controller may have other methods. * * */ class Controller { protected: View * vw; /**< associated view object*/ public: virtual void index() = 0; /**< abstract method index */ virtual ~Controller(){}; /**< Destructor */ }; /** * \class IndexController * \brief sample inherited controller * */ class IndexController : public Controller { public: IndexController(); /**< constructor */ void index(); /**< a method that prints welcome message */ void end(); /**< a method that prints final screen */ }; /** * \class AuthorizationController * \brief responsible for logic behind mobilID authorization * * * */ class AuthorizationController : public Controller{ private: UserModel * model; /**< user model*/ const char * TAG = "authController"; const char* sni; /**< SNI for authorization */ public: AuthorizationController(BaseModel *model, const char* sni); /**< constructor */ /** * @brief JSON body generator to retrieve Authentication Certificate * Example: * * { * "id": 0.0, * "method": "RPC.Authenticate", * "params": [ * { * "OS": "Operating System,2,0", * "PhoneNo": "+37200000766", * "IdCode": "60001019906" * } * ] * } * * */ char* generateAuthenticateRequestJSON(); /** * @brief JSON body generator to retrieve Authentication Status * * Example: * * { * "id": 0.0, * "method": "RPC.AuthenticateStatus", * "params": [ * { * "OS": "Operating System,2,0", * "SessionCode": "2127729011", * "SessionID": "057229fdfa2df7d3c7f4ced81b02760b" * } * ] * } * * */ char* generateAuthenticateStatusRequestJSON(); /** * @brief index method * * This method does nothing specific. * */ void index(); /** * @brief authorization request method. * * This method invokes authorization request to voting server. * Server doesn't directly send authorization token. Instead, sends a challenge to user to verify (verification code) * Session ID is also returned which will be used in all upcoming requests. * */ void auth(); /** * @brief authorization status method * * After auth() called, server returns challenge code, session id and session code. Challenge code is displayed to user verify itself. * To check whether user has been verified and get authorization token that is also going to be used in all upcoming requests, authorization status * request has to be sent to server. This function sends that request until user verifies itself every 10 seconds. * * Upon successful verification, authorization token is obtained and stored in model. * */ void authStatus(); }; /** * \class ChoiceController * \brief An authenticated user can request for list of candidates from voting server. * * Voting server returns list of candidates in special scheme in JSON format. ChoiceController parses that response and * make candidate names be displayed on screen. * */ class ChoiceController : public Controller{ private: ChoiceModel *model; /**< choices model */ const char * TAG = "choicesCtrl"; const char* sni; /**< SNI for choices service */ public: /** * @brief JSON body generator to retrieve the List of Choices * * @param at Authentication token * @param ssid SessionID * * Example: * * { * "id": 0.0, * "method": "RPC.VoterChoices", * "params": [ * { * "AuthMethod": "ticket", * "AuthToken": "G1RTZqBSBKrzqReuKYrmFUFXWFPvaxhJjdiZi6zqAnaK3OvrT...", * "OS": "Operating System,2,0", * "SessionID": "057229fdfa2df7d3c7f4ced81b02760b" * } * ] * } * * */ char* generateChoicesRequestJSON(ChoiceModel *cm); ChoiceController(BaseModel *model, const char* sni); /**< constructor*/ /** * @brief fetches data from server and waits user select a candidate * */ void index(); /** * Recursive function to parse JSON which holds the list of choices into choiceList,choiceListKeys and partyNameOf * @param item pointer to cJSON structure * @param par party (also, parent) name of current element, otherwise "" * * Example JSON body: * * { * "Kuused":{ * "0000.101":"ARA SMIRNOVVVK", * "0000.102":"MARGUS OTT KOVTP" * }, * "Männid":{ * "0000.103":"ADINE SÄDEVVK" * }, * "Üksikkandidaadid":{ * "0000.104":"LEILI KOVTP", * "0000.107":"JUTA KOVVALAH", * "0000.105":"KAJA KOVVALAG", * "0000.106":"MAREK KOVVALAG" * } * } * * */ void parse_object(cJSON *item, char* par); }; /** * \class EncryptionController * \brief A controller where selected candidate is turned into ballot and encrypted * * */ class EncryptionController : public Controller{ private: EncryptionModel *model; /**< encryption model*/ const char * TAG = "encCtrl"; public: /** * @brief main controller method. * * Encrypt voters casted ballot using public election key * * */ void index(); EncryptionController(BaseModel *model); /**< constructor */ }; /** * \class SignatureController * \brief digitally sign encrypted ballot * */ class SignatureController : Controller{ private: SignatureModel *model; /**< signature model*/ const char* sni; /**< sni for signature service*/ const char* TAG = "signCtrl"; /** * XML container for element SignedProperties * */ const char * SignedProperties = "" "" "" "%s" "" "" "" "" "%s" "" "" "%s" "%s" "" "" "" "" "" "" "application/octet-stream" "" "" ""; /** * XML container for element SignedInfo * */ const char * SignedInfo = "" "" "" "" "" "" "%s" "" "" "" "" "" "" "%s" "" ""; /** * XML container for element SignatureValue * */ const char * SignatureValue = "%s"; /** * XML container for element XadESSignature * */ const char * Signature = "" "" "" "%s" "%s" "" "" "%s" "" "" "" "" "%s" "" "" "" ""; public: SignatureController(BaseModel *model, const char* sni); /** * @brief retrieve user's public siging Certificate * */ void index(); /** * @brief JSON body generator to get signing Certificate * * Example: * * { * "id": 0.0, * "method": "RPC.GetCertificate", * "params": [ * { * "AuthMethod": "ticket", * "AuthToken": "G1RTZqBSBKrzqReuKYrmFUFXWFPvaxhJjdiZi6zqAnaK3OvrT...", * "OS": "Operating System,2,0", * "SessionID": "057229fdfa2df7d3c7f4ced81b02760b" * "PhoneNo": "+37200000766", * "IdCode": "60001019906" * } * ] * } * * */ char* generateGetCertificateRequestJSON(); /* * JSON body generator to initiate vote signing * Example: * { * "id": 0.0, * "method": "RPC.Sign", * "params": [ * { * "AuthMethod": "ticket", * "AuthToken": "G1RTZqBSBKrzqReuKYrmFUFXWFPvaxhJjdiZi6zqAnaK3OvrT...", * "Hash": "9IBrA05ylt2StdjxKkSTYMW/rQXY3Vub4upzShdfEzo=", * "OS": "Operating System,2,0", * "SessionID": "057229fdfa2df7d3c7f4ced81b02760b" * "PhoneNo": "+37200000766", * "IdCode": "60001019906" * } * ] * } * * */ char* generateSignRequestJSON(); /** * @brief send sign request for encrypted ballot hash * * * */ void sign(); /* * @brief JSON body generator to retrieve Signing Status * * Example: * * { * "id": 0.0, * "method": "RPC.SignStatus", * "params": [ * { * "OS": "Operating System,2,0", * "SessionCode": "2127729011", * "SessionID": "057229fdfa2df7d3c7f4ced81b02760b" * } * ] * } * * */ char* generateSignStatusRequestJSON(); /** * @brief check status of sign request * */ void status(); /** * @brief a helper method to put all xml elements into one single large elements. * */ void combine(); }; /** * \class ZipController * \brief BDOC container creator for singature file * */ class ZipController : public Controller{ private: ZipModel *model; const char* TAG = "zipCtrl"; /** * XML container for manifest.xml */ const char * manifest = "\n" "\n" " \n" " \n" ""; public: ZipController(BaseModel *model); /**< constructor */ /** * @brief create signature container according to BDOC 2.0 standards * * Using slightly modified miniz library, create .zip archieve with following file structure * * \META-INF * singature0.xml * manifest.xml * EP2065.1.ballot * mimetype * */ void index(); }; /** * \class VoteController * \brief cast signed ballot file to voting service * * */ class VoteController : public Controller{ private: VoteModel *model; const char * TAG = "voteCtrl"; const char * sni; public: VoteController(BaseModel *model, const char* sni); /**< constructor */ /** * @brief send bdoc container to voting service to cast your vote. * * A vote id is returned after bdoc container and vote data is validated in server side * */ void index(); /** * @brief JSON body generator to send signed vote * * Example * * { * "id": 0.0, * "method": "RPC.Vote", * "params": [ * { * "AuthMethod": "ticket", * "AuthToken": "G1RTZqBSBKrzqReuKYrmFUFXWFPvaxhJjdiZi6zqAnaK3OvrT...", * "Choices": "0140.1", * "SessionID": "ec3a0cab353d552952289f2c7ad52e27", * "OS": "Operating System,2,0", * "Type": "bdoc", * "Vote": "UEsDBAoABgAAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlv\nbi92bmQuZX..." * } * ] * } * */ char* generateVoteRequestJSON(); }; /** * \class QRController * \brief show vote data to verification app as QR code * * */ class QRController : public Controller{ private: QRModel *model; /**< qr model */ const char* TAG = "btCtrl"; public: QRController(BaseModel* model); /**< controller */ /** * @brief create QRcode from session id, randomness and vote id, then show it on screen * */ void index(); }; #endif /* MAIN_INCLUDE_CONTROLLER_H_ */