From 8c8793da21030b93fa52d78b41d68336a0aaa672 Mon Sep 17 00:00:00 2001 From: Ravin Perera <33562092+ravinsp@users.noreply.github.com> Date: Fri, 4 Oct 2019 15:12:46 +0530 Subject: [PATCH] Added user challenge generation and verification. --- src/crypto.cpp | 4 +- src/crypto.h | 4 +- src/main.cpp | 11 +----- src/proc.cpp | 8 ++-- src/usr/usr.cpp | 97 +++++++++++++++++++++++++++++++++++++++++++++++-- src/usr/usr.h | 10 ++++- 6 files changed, 110 insertions(+), 24 deletions(-) diff --git a/src/crypto.cpp b/src/crypto.cpp index 7c03f720..34df78ed 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -20,7 +20,7 @@ void sign(const unsigned char *msg, unsigned long long msg_len, unsigned char *s crypto_sign_detached(sig, NULL, msg, msg_len, conf::cfg.seckey); } -string sign_b64(string msg) +string sign_b64(string &msg) { unsigned char sig[crypto_sign_BYTES]; crypto_sign_detached(sig, NULL, (unsigned char *)msg.data(), msg.size() + 1, conf::cfg.seckey); @@ -33,7 +33,7 @@ bool verify(const unsigned char *msg, unsigned long long msg_len, const unsigned return result == 0; } -bool verify_b64(string msg, string sigb64, string pubkeyb64) +bool verify_b64(string &msg, string &sigb64, string &pubkeyb64) { unsigned char decoded_pubkey[crypto_sign_PUBLICKEYBYTES]; shared::base64_decode(pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES); diff --git a/src/crypto.h b/src/crypto.h index 925553c9..d8fd8933 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -16,7 +16,7 @@ void sign(const unsigned char *msg, unsigned long long msg_len, unsigned char *s /** * Returns the base64 signature for the given message using the contract's secret key. */ -string sign_b64(string msg); +string sign_b64(string &msg); /** * Verifies the given signature with the message using the provided public key. @@ -26,7 +26,7 @@ bool verify(const unsigned char *msg, unsigned long long msg_len, const unsigned /** * Verifies the given base64 signature with the message using the provided base64 public key. */ -bool verify_b64(string msg, string sigb64, string pubkeyb64); +bool verify_b64(string &msg, string &sigb64, string &pubkeyb64); } // namespace crypto diff --git a/src/main.cpp b/src/main.cpp index cf32922e..fec2a090 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,16 +35,7 @@ int main(int argc, char **argv) if (conf::ctx.command == "run") { - //TODO - - usr::add_user("pku1"); - usr::add_user("pku2"); - usr::add_user("pku3"); - - proc::ContractExecArgs ctargs; - ctargs.users = &usr::users; - - proc::exec_contract(ctargs); + usr::init(); } } diff --git a/src/proc.cpp b/src/proc.cpp index fc2bd77f..ad10612c 100644 --- a/src/proc.cpp +++ b/src/proc.cpp @@ -5,7 +5,7 @@ #include #include #include -#include "rapidjson/stringbuffer.h" +#include #include #include "proc.h" #include "conf.h" @@ -65,7 +65,7 @@ int exec_contract(ContractExecArgs &args) * "version":"0.1", * "usrfd":{ "pk1":[fd0, fd1], "pk2":[fd0, fd1] } * } - */ + */ void write_to_stdin(ContractExecArgs &args) { Document d; @@ -74,7 +74,7 @@ void write_to_stdin(ContractExecArgs &args) d.AddMember("version", StringRef(_HP_VERSION_), allocator); Value users(kObjectType); - for (auto& [pk, user] : (*args.users)) + for (auto &[pk, user] : (*args.users)) { Value fdlist(kArrayType); fdlist.PushBack(user.inpipe[0], allocator); @@ -104,9 +104,9 @@ bool is_contract_running() int status = 0; if (!waitpid(contract_pid, &status, WNOHANG)) return true; + contract_pid = 0; } - contract_pid = 0; return false; } diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 1b3ef0e4..7cf7c0e4 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -3,18 +3,87 @@ #include #include #include +#include +#include +#include +#include +#include #include "../shared.h" +#include "../conf.h" +#include "../crypto.h" #include "usr.h" using namespace std; using namespace shared; +using namespace rapidjson; namespace usr { map users; +Document challenge_response_schemadoc; -void add_user(string pubkeyb64) +void create_user_challenge(string &msg, string &challenge) +{ + unsigned char challenge_bytes[USER_CHALLENGE_LEN]; + randombytes_buf(challenge_bytes, USER_CHALLENGE_LEN); + + challenge = base64_encode(challenge_bytes, USER_CHALLENGE_LEN); + + Document d; + d.SetObject(); + Document::AllocatorType &allocator = d.GetAllocator(); + d.AddMember("version", StringRef(_HP_VERSION_), allocator); + d.AddMember("type", "public_challenge", allocator); + d.AddMember("challenge", StringRef(challenge.data()), allocator); + + StringBuffer buffer; + Writer writer(buffer); + d.Accept(writer); + msg = buffer.GetString(); +} + +bool verify_user_challenge_response(string &response, string &original_challenge, string &extracted_pubkeyb64) +{ + Document d; + d.Parse(response.data()); + + SchemaDocument schema(challenge_response_schemadoc); + SchemaValidator validator(schema); + if (!d.Accept(validator)) + { + cerr << "User challenge resposne schema invalid.\n"; + return false; + } + + string type = d["type"].GetString(); + if (type != "challenge_response") + { + cerr << "User challenge response type invalid. 'challenge_response' expeced.\n"; + return false; + } + + string challenge = d["challenge"].GetString(); + string sigb64 = d["sig"].GetString(); + string pubkeyb64 = d["pubkey"].GetString(); + + if (challenge != original_challenge) + { + cerr << "User challenge resposne: challenge mismatch.\n"; + return false; + } + + if (!crypto::verify_b64(original_challenge, sigb64, pubkeyb64)) + { + cerr << "User challenge response signature verification failed.\n"; + return false; + } + + extracted_pubkeyb64 = pubkeyb64; + return true; +} + +void add_user(string &pubkeyb64) { if (users.count(pubkeyb64) == 1) { @@ -24,7 +93,8 @@ void add_user(string pubkeyb64) int inpipe[2]; int outpipe[2]; - if (pipe(inpipe) != 0 || pipe(outpipe) != 0) { + if (pipe(inpipe) != 0 || pipe(outpipe) != 0) + { cerr << "User pipe creation failed. pubkey:" << pubkeyb64 << endl; return; } @@ -32,7 +102,7 @@ void add_user(string pubkeyb64) users.insert(pair(pubkeyb64, ContractUser(pubkeyb64, inpipe, outpipe))); } -void remove_user(string pubkeyb64) +void remove_user(string &pubkeyb64) { if (users.count(pubkeyb64) == 0) { @@ -53,7 +123,7 @@ void remove_user(string pubkeyb64) //Read per-user outputs produced by the contract process. int read_contract_user_outputs() { - for (auto& [pk, user] : users) + for (auto &[pk, user] : users) { int fdout = user.outpipe[0]; int bytes_available = 0; @@ -75,4 +145,23 @@ int read_contract_user_outputs() return 1; } +int init() +{ + const char *challenge_response_schema = + "{" + "\"type\": \"object\"," + "\"required\": [ \"type\", \"challenge\", \"sig\", \"pubkey\" ]," + "\"properties\": {" + "\"type\": { \"type\": \"string\" }," + "\"challenge\": { \"type\": \"string\" }," + "\"sig\": { \"type\": \"string\" }," + "\"pubkey\": { \"type\": \"string\" }" + "}" + "}"; + + challenge_response_schemadoc.Parse(challenge_response_schema); + + return 0; +} + } // namespace usr \ No newline at end of file diff --git a/src/usr/usr.h b/src/usr/usr.h index bb10ea6a..cdd0e987 100644 --- a/src/usr/usr.h +++ b/src/usr/usr.h @@ -1,6 +1,8 @@ #ifndef _HP_USR_H_ #define _HP_USR_H_ +#define USER_CHALLENGE_LEN 16 + #include #include #include @@ -12,8 +14,12 @@ using namespace shared; namespace usr { extern map users; -void add_user(string pubkeyb64); -void remove_user(string pubkeyb64); + +int init(); +void create_user_challenge(string &msg, string &challenge); +bool verify_user_challenge_response(string &response, string &original_challenge, string &extracted_pubkey); +void add_user(string &pubkeyb64); +void remove_user(string &pubkeyb64); } // namespace usr