Unverified Commit ae4b4be1 authored by Stan Kladko's avatar Stan Kladko Committed by GitHub

Merge pull request #303 from skalenetwork/beta

Beta to stable
parents 20f290df 4989ebec
......@@ -21,17 +21,3 @@ jobs:
run: git submodule update --init --recursive
- name: Build the Docker image
run: docker build . --file DockerfileBase --tag skalenetwork/sgxwallet_base:latest && docker push skalenetwork/sgxwallet_base:latest
- name: deploy docker image
if: contains(github.ref, 'develop') || contains(github.ref, 'beta') || contains(github.ref, 'master') || contains(github.ref, 'stable')
run : |
export BRANCH=${GITHUB_REF##*/}
echo "Branch $BRANCH"
export VERSION=$(cat VERSION)
echo "Version $VERSION"
export VERSION=$(bash ./scripts/calculate_version.sh $BRANCH $VERSION)
echo "::set-env name=VERSION::$VERSION"
echo "Version $VERSION"
export RELEASE=true
echo "::set-env name=RELEASE::$RELEASE"
bash ./scripts/build_image.sh DockerfileBase sgxwallet_base
bash ./scripts/publish_image.sh sgxwallet_base
......@@ -17,8 +17,11 @@ jobs:
- name: submodule update
run: git submodule update --init --recursive
- name: build and deploy docker image
if: |
contains(github.ref, 'stable')
if: |
contains(github.ref, 'develop') || contains(github.ref, 'beta') ||
contains(github.ref, 'master') || contains(github.ref, 'stable') ||
contains(github.ref, 'SECURE_ENCLAVE_CHANGES')
run : |
export BRANCH=${GITHUB_REF##*/}
echo "Branch $BRANCH"
......
......@@ -49,4 +49,6 @@
/secure_enclave/*.o
/*.user
/cert/*.csr
/cert/*.crt
\ No newline at end of file
/cert/*.crt
/jsonrpc/
/sgx-gmp/
......@@ -16,3 +16,12 @@
[submodule "sgx-software-enable"]
path = sgx-software-enable
url = https://github.com/intel/sgx-software-enable
[submodule "libzmq"]
path = libzmq
url = https://github.com/zeromq/libzmq.git
[submodule "cppzmq"]
path = cppzmq
url = https://github.com/zeromq/cppzmq.git
[submodule "rapidjson"]
path = rapidjson
url = https://github.com/Tencent/rapidjson.git
......@@ -129,36 +129,6 @@ bool hex2carray(const char *_hex, uint64_t *_bin_len,
return true;
}
bool sign(const char *_encryptedKeyHex, const char *_hashHex, size_t _t, size_t _n, size_t _signerIndex,
char *_sig) {
CHECK_STATE(_encryptedKeyHex);
CHECK_STATE(_hashHex);
CHECK_STATE(_sig);
auto keyStr = make_shared<string>(_encryptedKeyHex);
auto hash = make_shared < array < uint8_t,
32 >> ();
uint64_t binLen;
if (!hex2carray(_hashHex, &binLen, hash->data(), hash->size())) {
throw SGXException(INVALID_HEX, "Invalid hash");
}
auto keyShare = make_shared<BLSPrivateKeyShareSGX>(keyStr, _t, _n);
auto sigShare = keyShare->signWithHelperSGX(hash, _signerIndex);
auto sigShareStr = sigShare->toString();
strncpy(_sig, sigShareStr->c_str(), BUF_LEN);
return true;
}
bool sign_aes(const char *_encryptedKeyHex, const char *_hashHex, size_t _t, size_t _n, char *_sig) {
CHECK_STATE(_encryptedKeyHex);
......@@ -170,7 +140,7 @@ bool sign_aes(const char *_encryptedKeyHex, const char *_hashHex, size_t _t, siz
uint64_t binLen;
if (!hex2carray(_hashHex, &binLen, hash->data(), hash->size())) {
throw SGXException(INVALID_HEX, "Invalid hash");
throw SGXException(SIGN_AES_INVALID_HASH, string(__FUNCTION__) + ":Invalid hash");
}
shared_ptr <signatures::Bls> obj;
......@@ -214,10 +184,8 @@ bool sign_aes(const char *_encryptedKeyHex, const char *_hashHex, size_t _t, siz
sgx_status_t status = SGX_SUCCESS;
RESTART_BEGIN
status = trustedBlsSignMessage(eid, &errStatus, errMsg.data(), encryptedKey,
sz, xStrArg, yStrArg, signature);
RESTART_END
status = trustedBlsSignMessage(eid, &errStatus, errMsg.data(), encryptedKey,
sz, xStrArg, yStrArg, signature);
HANDLE_TRUSTED_FUNCTION_ERROR(status, errStatus, errMsg.data());
......@@ -256,10 +224,8 @@ string encryptBLSKeyShare2Hex(int *errStatus, char *err_string, const char *_key
sgx_status_t status = SGX_SUCCESS;
RESTART_BEGIN
status = trustedEncryptKey(eid, errStatus, errMsg.data(), keyArray->data(), encryptedKey->data(),
&encryptedLen);
RESTART_END_POINTER
status = trustedEncryptKey(eid, errStatus, errMsg.data(), keyArray->data(), encryptedKey->data(),
&encryptedLen);
HANDLE_TRUSTED_FUNCTION_ERROR(status, *errStatus, errMsg.data());
......
......@@ -149,10 +149,8 @@ string BLSPrivateKeyShareSGX::signWithHelperSGXstr(
sgx_status_t status = SGX_SUCCESS;
RESTART_BEGIN
status = trustedBlsSignMessage(eid, &errStatus, errMsg.data(), encryptedKey,
encryptedKeyHex->size() / 2, xStrArg, yStrArg, signature);
RESTART_END
status = trustedBlsSignMessage(eid, &errStatus, errMsg.data(), encryptedKey,
encryptedKeyHex->size() / 2, xStrArg, yStrArg, signature);
HANDLE_TRUSTED_FUNCTION_ERROR(status, errStatus, errMsg.data());
......
//
// Created by kladko on 15.12.20.
//
#include "BLSSignReqMessage.h"
#include "SGXWalletServer.hpp"
Json::Value BLSSignReqMessage::process() {
auto keyName = getStringRapid("kn");
auto hash = getStringRapid("mh");
auto t = getUint64Rapid("t");
auto n = getUint64Rapid("n");
return SGXWalletServer::blsSignMessageHashImpl(keyName, hash, t, n);
}
\ No newline at end of file
/*
Copyright (C) 2018-2019 SKALE Labs
This file is part of libBLS.
libBLS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libBLS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with libBLS. If not, see <https://www.gnu.org/licenses/>.
@file BLSReqSignMessage.h
@author Stan Kladko
@date 2020
*/
#ifndef SGXWALLET_BLSSIGNREQMSG_H
#define SGXWALLET_BLSSIGNREQMSG_H
#include "ZMQMessage.h"
class BLSSignReqMessage : public ZMQMessage {
public:
BLSSignReqMessage(shared_ptr<rapidjson::Document>& _d) : ZMQMessage(_d) {};
virtual Json::Value process();
};
#endif //SGXWALLET_BLSSIGNREQMSG_H
This diff is collapsed.
......@@ -51,6 +51,8 @@ string decryptDHKey(const string& polyName, int ind);
bool createBLSShare( const string& blsKeyName, const char * s_shares, const char * encryptedKeyHex);
bool createBLSShareV2( const string& blsKeyName, const char * s_shares, const char * encryptedKeyHex);
vector<string> getBLSPubKey(const char * encryptedKeyHex);
vector<string> mult_G2(const string& x);
......
......@@ -59,11 +59,9 @@ vector <string> genECDSAKey() {
sgx_status_t status = SGX_SUCCESS;
RESTART_BEGIN
status = trustedGenerateEcdsaKey(eid, &errStatus,
errMsg.data(), encr_pr_key.data(), &enc_len,
pub_key_x.data(), pub_key_y.data());
RESTART_END
status = trustedGenerateEcdsaKey(eid, &errStatus,
errMsg.data(), encr_pr_key.data(), &enc_len,
pub_key_x.data(), pub_key_y.data());
HANDLE_TRUSTED_FUNCTION_ERROR(status, errStatus,errMsg.data());
......@@ -96,15 +94,13 @@ string getECDSAPubKey(const std::string& _encryptedKeyHex) {
if (!hex2carray(_encryptedKeyHex.c_str(), &enc_len, encrPrKey.data(),
BUF_LEN)) {
throw SGXException(INVALID_HEX, "Invalid encryptedKeyHex");
throw SGXException(GET_ECDSA_PUB_KEY_INVALID_KEY_HEX, "Invalid encryptedKeyHex");
}
sgx_status_t status = SGX_SUCCESS;
RESTART_BEGIN
status = trustedGetPublicEcdsaKey(eid, &errStatus,
errMsg.data(), encrPrKey.data(), enc_len, pubKeyX.data(), pubKeyY.data());
RESTART_END
status = trustedGetPublicEcdsaKey(eid, &errStatus,
errMsg.data(), encrPrKey.data(), enc_len, pubKeyX.data(), pubKeyY.data());
HANDLE_TRUSTED_FUNCTION_ERROR(status, errStatus, errMsg.data())
......@@ -185,17 +181,15 @@ vector <string> ecdsaSignHash(const std::string& encryptedKeyHex, const char *ha
if (!hex2carray(encryptedKeyHex.c_str(), &decLen, encryptedKey.data(),
BUF_LEN)) {
throw SGXException(INVALID_HEX, "Invalid encryptedKeyHex");
throw SGXException(ECDSA_SIGN_INVALID_KEY_HEX, "Invalid encryptedKeyHex");
}
sgx_status_t status = SGX_SUCCESS;
RESTART_BEGIN
status = trustedEcdsaSign(eid, &errStatus,
errMsg.data(), encryptedKey.data(), decLen, hashHex,
signatureR.data(),
signatureS.data(), &signatureV, base);
RESTART_END
status = trustedEcdsaSign(eid, &errStatus,
errMsg.data(), encryptedKey.data(), decLen, hashHex,
signatureR.data(),
signatureS.data(), &signatureV, base);
HANDLE_TRUSTED_FUNCTION_ERROR(status, errStatus, errMsg.data());
......@@ -242,10 +236,9 @@ string encryptECDSAKey(const string& _key) {
uint64_t enc_len = 0;
sgx_status_t status = SGX_SUCCESS;
RESTART_BEGIN
status = trustedEncryptKey(eid, &errStatus, errString.data(), key.data(),
encryptedKey.data(), &enc_len);
RESTART_END
status = trustedEncryptKey(eid, &errStatus, errString.data(), key.data(),
encryptedKey.data(), &enc_len);
if (status != 0) {
throw SGXException(status, string("Could not encrypt ECDSA key: " + string(errString.begin(), errString.end())).c_str());
......
//
// Created by kladko on 15.12.20.
//
#include "SGXWalletServer.hpp"
#include "ECDSASignReqMessage.h"
Json::Value ECDSASignReqMessage::process() {
auto base = getUint64Rapid("bs");
auto keyName = getStringRapid("kn");
auto hash = getStringRapid("mh");
return SGXWalletServer::ecdsaSignMessageHashImpl(base, keyName, hash);
}
\ No newline at end of file
/*
Copyright (C) 2018-2019 SKALE Labs
This file is part of libBLS.
libBLS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
libBLS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with libBLS. If not, see <https://www.gnu.org/licenses/>.
@file ECDSAReqSignMessage.h
@author Stan Kladko
@date 2020
*/
#ifndef SGXWALLET_ECDSASIGNREQMESSAGE_H
#define SGXWALLET_ECDSASIGNREQMESSAGE_H
#include "ZMQMessage.h"
class ECDSASignReqMessage : public ZMQMessage {
public:
ECDSASignReqMessage(shared_ptr <rapidjson::Document> &_d) : ZMQMessage(_d) {};
virtual Json::Value process();
};
#endif //SGXWALLET_ECDSASIGNREQMESSAGE_H
......@@ -27,6 +27,7 @@
#include <iostream>
#include "leveldb/db.h"
#include <jsonrpccpp/client.h>
#include "sgxwallet_common.h"
#include "SGXException.h"
......@@ -42,6 +43,14 @@ using namespace leveldb;
static WriteOptions writeOptions;
static ReadOptions readOptions;
shared_ptr<string> LevelDB::readNewStyleValue(const string& value) {
Json::Value key_data;
Json::Reader reader;
reader.parse(value.c_str(), key_data);
return std::make_shared<string>(key_data["value"].asString());
}
std::shared_ptr<string> LevelDB::readString(const string &_key) {
auto result = std::make_shared<string>();
......@@ -56,17 +65,26 @@ std::shared_ptr<string> LevelDB::readString(const string &_key) {
return nullptr;
}
if (result->at(0) == '{') {
return readNewStyleValue(*result);
}
return result;
}
void LevelDB::writeString(const string &_key, const string &_value) {
Json::Value writerData;
writerData["value"] = _value;
writerData["timestamp"] = std::to_string(std::time(nullptr));
Json::FastWriter fastWriter;
std::string output = fastWriter.write(writerData);
auto status = db->Put(writeOptions, Slice(_key), Slice(_value));
auto status = db->Put(writeOptions, Slice(_key), Slice(output));
throwExceptionOnError(status);
}
void LevelDB::deleteDHDKGKey(const string &_key) {
string full_key = "DKG_DH_KEY_" + _key;
......@@ -94,18 +112,6 @@ void LevelDB::deleteKey(const string &_key) {
}
void LevelDB::writeByteArray(string &_key, const char *value,
size_t _valueLen) {
CHECK_STATE(value);
auto status = db->Put(writeOptions, Slice(_key), Slice(value, _valueLen));
throwExceptionOnError(status);
}
void LevelDB::throwExceptionOnError(Status _status) {
if (_status.IsNotFound())
return;
......@@ -155,15 +161,65 @@ std::vector<string> LevelDB::writeKeysToVector1(uint64_t _maxKeysToVisit){
}
void LevelDB::writeDataUnique(const string & name, const string &value) {
auto key = name;
if (readString(name)) {
spdlog::debug("Name {} already exists", name);
throw SGXException(KEY_SHARE_ALREADY_EXISTS, "Data with this name already exists");
}
writeString(key, value);
writeString(name, value);
}
pair<stringstream, uint64_t> LevelDB::getAllKeys() {
stringstream keysInfo;
leveldb::Iterator *it = db->NewIterator(readOptions);
uint64_t counter = 0;
for (it->SeekToFirst(); it->Valid(); it->Next()) {
++counter;
string key = it->key().ToString();
string value;
if (it->value().ToString()[0] == '{') {
// new style keys
Json::Value key_data;
Json::Reader reader;
reader.parse(it->value().ToString().c_str(), key_data);
string timestamp_to_date_command = "date -d @" + key_data["timestamp"].asString();
value = " VALUE: " + key_data["value"].asString() + ", TIMESTAMP: " + exec(timestamp_to_date_command.c_str()) + '\n';
} else {
// old style keys
value = " VALUE: " + it->value().ToString();
}
keysInfo << "KEY: " << key << ',' << value;
}
return {std::move(keysInfo), counter};
}
pair<string, uint64_t> LevelDB::getLatestCreatedKey() {
leveldb::Iterator *it = db->NewIterator(readOptions);
int64_t latest_timestamp = 0;
string latest_created_key_name = "";
for (it->SeekToFirst(); it->Valid(); it->Next()) {
if (it->value().ToString()[0] == '{') {
// new style keys
Json::Value key_data;
Json::Reader reader;
reader.parse(it->value().ToString().c_str(), key_data);
if (std::stoi(key_data["timestamp"].asString()) > latest_timestamp) {
latest_timestamp = std::stoi(key_data["timestamp"].asString());
latest_created_key_name = it->key().ToString();
}
} else {
// old style keys
// assuming server has at least one new-style key created
continue;
}
}
return {latest_created_key_name, latest_timestamp};
}
......@@ -219,7 +275,7 @@ void LevelDB::initDataFolderAndDBs() {
if (getcwd(cwd, sizeof(cwd)) == NULL) {
spdlog::error("could not get current workin directory");
exit(-1);
exit(-2);
}
sgx_data_folder = string(cwd) + "/" + SGXDATA_FOLDER;
......@@ -233,7 +289,7 @@ void LevelDB::initDataFolderAndDBs() {
}
else{
spdlog::error("Couldnt create creating sgx_data folder");
exit(-1);
exit(-3);
}
}
......
......@@ -26,10 +26,12 @@
#define SGXWALLET_LEVELDB_H
#include <memory>
#include <sstream>
#include <string>
#include <mutex>
#include <vector>
#include "common.h"
namespace leveldb {
class DB;
class Status;
......@@ -55,7 +57,6 @@ class LevelDB {
public:
static void initDataFolderAndDBs();
static const shared_ptr<LevelDB> &getLevelDb();
......@@ -66,20 +67,17 @@ public:
public:
shared_ptr<string> readString(const string& _key);
shared_ptr<string> readNewStyleValue(const string& value);
void writeString(const string &key1, const string &value1);
pair<stringstream, uint64_t> getAllKeys();
void writeDataUnique(const string & Name, const string &value);
void writeByteArray(const char *_key, size_t _keyLen, const char *value,
size_t _valueLen);
pair<string, uint64_t> getLatestCreatedKey();
void writeString(const string &key1, const string &value1);
void writeByteArray(string& _key, const char *value,
size_t _valueLen);
void writeDataUnique(const string & Name, const string &value);
void deleteDHDKGKey (const string &_key);
......@@ -89,15 +87,10 @@ public:
public:
void throwExceptionOnError(leveldb::Status result);
LevelDB(string& filename);
class KeyVisitor {
public:
virtual void visitDBKey(const char* _data) = 0;
......
......@@ -52,7 +52,7 @@ level_enum Log::logLevelFromString(string &_s) {
}
void Log::handleSGXException(Json::Value& _result, SGXException& _e ) {
spdlog::error("Responding with JSON error:" + _e.errString);
_result["status"] = _e.status;
_result["errorMessage"] = _e.errString;
spdlog::error("Responding with JSON error:" + _e.getErrString());
_result["status"] = _e.getStatus();
_result["errorMessage"] = _e.getErrString();
}
/*
*
Copyright (C) 2019-Present SKALE Labs
This file is part of sgxwallet.
......@@ -74,26 +75,54 @@ public:
static void handleSGXException(Json::Value &_result, SGXException &_e);
};
#define COUNT_STATISTICS \
static uint64_t __COUNT__ = 0; \
__COUNT__++; \
if (__COUNT__ % 1000 == 0) { \
spdlog::info(string(__FUNCTION__) + " processed " + to_string(__COUNT__) + " requests"); \
struct sysinfo memInfo; \
sysinfo (&memInfo); \
long long totalPhysMem = memInfo.totalram; \
/*Multiply in next statement to avoid int overflow on right hand side...*/ \
totalPhysMem *= memInfo.mem_unit; \
int usedByCurrentProcess = getValue(); \
if ( 0.5 * totalPhysMem < usedByCurrentProcess ) { \
exit(-103); \
} \
}
// if uknown error, the error is 10000 + line number
#define INIT_RESULT(__RESULT__) Json::Value __RESULT__; \
int errStatus = UNKNOWN_ERROR; boost::ignore_unused(errStatus); string errMsg(BUF_LEN, '\0');__RESULT__["status"] = UNKNOWN_ERROR; __RESULT__["errorMessage"] = \
"Server error. Please see server log.";
int errStatus = -1 * (10000 + __LINE__); boost::ignore_unused(errStatus); string errMsg(BUF_LEN, '\0');__RESULT__["status"] = -1 * (10000 + __LINE__); __RESULT__["errorMessage"] = \
string(__FUNCTION__); \
string(__FUNCTION__) + ": server error. Please see server log.";
#define HANDLE_SGX_EXCEPTION(__RESULT__) \
catch (SGXException& _e) { \
if (_e.status != 0) {__RESULT__["status"] = _e.status;} else { __RESULT__["status"] = UNKNOWN_ERROR;}; \
__RESULT__["errorMessage"] = _e.errString; \
spdlog::error("JSON call failed {}", __FUNCTION__); \
catch (const SGXException& _e) { \
if (_e.getStatus() != 0) {__RESULT__["status"] = _e.getStatus();} else { __RESULT__["status"] = -1 * (10000 + __LINE__);}; \
auto errStr = __FUNCTION__ + string(" failed:") + _e.getErrString(); \
__RESULT__["errorMessage"] = errStr; \
spdlog::error(errStr); \
return __RESULT__; \
} catch (exception& _e) { \
__RESULT__["errorMessage"] = _e.what(); \
spdlog::error("JSON call failed {}", __FUNCTION__); \
} catch (const exception& _e) { \
__RESULT__["status"] = -1 * (10000 + __LINE__); \
exception_ptr p = current_exception(); \
auto errStr = __FUNCTION__ + string(" failed:") + p.__cxa_exception_type()->name() + ":" + _e.what(); \
__RESULT__["errorMessage"] = errStr; \
spdlog::error(errStr); \
return __RESULT__; \
}\
} \
catch (...) { \
exception_ptr p = current_exception(); \
printf("Exception %s \n", p.__cxa_exception_type()->name()); \
__RESULT__["errorMessage"] = "Unknown exception"; \
spdlog::error("JSON call failed {}", __FUNCTION__); \
auto errStr = __FUNCTION__ + string(" failed:") + p.__cxa_exception_type()->name(); \
spdlog::error(errStr); \
__RESULT__["errorMessage"] = errStr ; \
spdlog::error(errStr); \
return __RESULT__; \
}
......
......@@ -45,11 +45,14 @@ secure_enclave.edl: secure_enclave/secure_enclave.edl
#AM_CPPFLAGS += -g -Og
AM_CFLAGS = -DUSER_SPACE -g -Og -rdynamic -Wl,--no-as-needed -lSegFault -DSGXWALLET_VERSION="$(WALLET_VERSION)"
AM_CFLAGS = -DUSER_SPACE -O2 -rdynamic -Wl,--no-as-needed -lSegFault -DSGXWALLET_VERSION="$(WALLET_VERSION)"
AM_CXXFLAGS = ${AM_CPPFLAGS} -rdynamic -Wl,--no-as-needed -lSegFault -DSGXWALLET_VERSION="$(WALLET_VERSION)"
AM_CPPFLAGS += -DSGXWALLET_VERSION="$(WALLET_VERSION)" -Wall -DSKALE_SGX=1 -DBINARY_OUTPUT=1 -Ileveldb/include -IlibBLS/bls -IlibBLS/libff -IlibBLS -fno-builtin-memset $(GMP_CPPFLAGS) -I. -I./libBLS/deps/deps_inst/x86_or_x64/include
AM_CPPFLAGS += -DSGXWALLET_VERSION="$(WALLET_VERSION)" -Wall -DSKALE_SGX=1 -DBINARY_OUTPUT=1 -Ileveldb/include -IlibBLS/bls\
-IlibBLS/libff -IlibBLS -fno-builtin-memset $(GMP_CPPFLAGS) -I. \
-I./libBLS/deps/deps_inst/x86_or_x64/include -I./libzmq/include -I./cppzmq -I./third_party/zguide \
-I./rapidjson/include/rapidjson
## Additional targets to remove with 'make clean'. You must list
## any edger8r generated files here.
......@@ -59,19 +62,19 @@ CLEANFILES = $(COMMON_ENCLAVE_SRC) secure_enclave.edl secure_enclave.signed.so
## The build target
bin_PROGRAMS = sgxwallet testw cert_util
bin_PROGRAMS = sgxwallet testw sgx_util
## You can't use $(wildcard ...) with automake so all source files
## have to be explicitly listed.
## have to be explicitly listed
COMMON_SRC = InvalidStateException.cpp Exception.cpp InvalidArgumentException.cpp Log.cpp \
COMMON_SRC = ECDSASignReqMessage.cpp BLSSignReqMessage.cpp ZMQMessage.cpp ZMQServer.cpp ServerWorker.cpp InvalidStateException.cpp Exception.cpp InvalidArgumentException.cpp Log.cpp \
SGXWalletServer.cpp SGXRegistrationServer.cpp CSRManagerServer.cpp BLSCrypto.cpp \
ECDSACrypto.cpp \
DKGCrypto.cpp ServerInit.cpp BLSPrivateKeyShareSGX.cpp LevelDB.cpp ServerDataChecker.cpp SEKManager.cpp \
third_party/intel/sgx_stub.c third_party/intel/sgx_detect_linux.c third_party/intel/create_enclave.c third_party/intel/oc_alloc.c \
ECDSAImpl.c TestUtils.cpp sgxwallet.c
ECDSAImpl.c TestUtils.cpp sgxwallet.c SGXInfoServer.cpp ECDSACrypto.cpp
COMMON_ENCLAVE_SRC = secure_enclave_u.c secure_enclave_u.h
sgxwallet_SOURCES = sgxwall.cpp $(COMMON_SRC)
......@@ -100,8 +103,10 @@ secure_enclave.signed.so: secure_enclave/secure_enclave.signed.so
sgxwallet_LDADD=-l$(SGX_URTS_LIB) -l$(SGX_UAE_SERVICE_LIB) -LlibBLS/deps/deps_inst/x86_or_x64/lib -Lleveldb/build -LlibBLS/build \
-LlibBLS/build/libff/libff \
-Llibzmq/build/lib/ \
-l:libbls.a -l:libleveldb.a \
-l:libff.a -lgmp -ldl -l:libsgx_capable.a -l:libsgx_tprotected_fs.a \
-l:libzmq.a \
-ljsonrpccpp-stub -ljsonrpccpp-server -ljsonrpccpp-client -ljsonrpccpp-common -ljsoncpp -lmicrohttpd \
-lboost_system -lboost_thread -lgnutls -lgcrypt -lidn2 -lcurl -lssl -lcrypto -lz -lpthread -lstdc++fs
......@@ -111,8 +116,12 @@ nodist_testw_SOURCES=${nodist_sgxwallet_SOURCES}
EXTRA_testw_DEPENDENCIES=${EXTRA_sgxwallet_DEPENDENCIES}
testw_LDADD= ${sgxwallet_LDADD}
cert_util_SOURCES= InvalidStateException.cpp Exception.cpp InvalidArgumentException.cpp Log.cpp cert_util.cpp stubclient.cpp LevelDB.cpp SGXRegistrationServer.cpp CSRManagerServer.cpp
cert_util_LDADD=-LlibBLS/deps/deps_inst/x86_or_x64/lib -Lleveldb/build -LlibBLS/build \
sgx_util_SOURCES= InvalidStateException.cpp Exception.cpp InvalidArgumentException.cpp Log.cpp sgx_util.cpp stubclient.cpp LevelDB.cpp SGXRegistrationServer.cpp CSRManagerServer.cpp
sgx_util_LDADD=-LlibBLS/deps/deps_inst/x86_or_x64/lib -Lleveldb/build -LlibBLS/build \
-LlibBLS/build/libff/libff \
-Llibzmq/build/lib/ \
-l:libzmq.a \
-l:libbls.a -l:libleveldb.a \
-l:libff.a -lgmp -ljsonrpccpp-stub -ljsonrpccpp-server -ljsonrpccpp-client -ljsonrpccpp-common -ljsoncpp -lmicrohttpd -lgnutls -lgcrypt -lidn2 -lcurl -lssl -lcrypto -lz -lpthread -ldl
# sgxwallet: SKALE SGX-based hardware crypto wallet
# sgxwallet: SKALE SGX-based hardware crypto wallet
<!-- SPDX-License-Identifier: (AGPL-3.0-only OR CC-BY-4.0) -->
......
......@@ -9,3 +9,7 @@ You can report security bugs by emailing us directly at security@skalelabs.com.
## Comments on This Policy
If you have suggestions on how this process could be improved, please submit a pull request.
## Bug Reporting Bounty
Please check out the SKALE Network's HackerOne program for any bug bounties related to SGX Wallet: <https://hackerone.com/skale_network>
......@@ -90,7 +90,7 @@ void validate_SEK() {
if (!hex2carray(test_key_ptr->c_str(), &len, encr_test_key.data(),
BUF_LEN)) {
spdlog::error("Corrupt test key is LevelDB");
exit(-1);
exit(-4);
}
sgx_status_t status = SGX_SUCCESS;
......@@ -108,7 +108,7 @@ void validate_SEK() {
spdlog::error("Invalid storage key. You need to recover using backup key");
spdlog::error("Set the correct backup key into sgx_datasgxwallet_backup_key.txt");
spdlog::error("Then run sgxwallet using backup flag");
exit(-1);
exit(-5);
}
}
......@@ -215,7 +215,7 @@ void safeExit() {
auto previousValue = isSgxWalletExiting.exchange(1);
if (previousValue != 1)
exit(3);
exit(-6);
}
void setSEK(shared_ptr <string> hex_encrypted_SEK) {
......@@ -231,7 +231,7 @@ void setSEK(shared_ptr <string> hex_encrypted_SEK) {
if (!hex2carray(hex_encrypted_SEK->c_str(), &len, encrypted_SEK,
BUF_LEN)) {
throw SGXException(INVALID_HEX, "Invalid encrypted SEK Hex");
throw SGXException(SET_SEK_INVALID_SEK_HEX, "Invalid encrypted SEK Hex");
}
sgx_status_t status = SGX_SUCCESS;
......@@ -256,13 +256,13 @@ void enter_SEK() {
shared_ptr <string> test_key_ptr = LevelDB::getLevelDb()->readString("TEST_KEY");
if (test_key_ptr == nullptr) {
spdlog::error("Error: corrupt or empty LevelDB database");
exit(-1);
exit(-7);
}
if (!experimental::filesystem::is_regular_file(BACKUP_PATH)) {
spdlog::error("File does not exist: " BACKUP_PATH);
exit(-1);
exit(-8);
}
ifstream sek_file(BACKUP_PATH);
......@@ -278,7 +278,7 @@ void enter_SEK() {
while (!checkHex(sek, 16)) {
spdlog::error("Invalid hex in key");
exit(-1);
exit(-9);
}
auto encrypted_SEK = check_and_set_SEK(sek);
......
......@@ -27,19 +27,30 @@
#include <string>
#include <exception>
class SGXException : public std::exception {
using namespace std;
class SGXException : public exception {
const int32_t status;
const string errString;
public:
int32_t status;
std::string errString;
SGXException(int32_t _status, const string& _errString) : status(_status), errString(_errString) {}
const string getMessage() const {
return "SGXException:status:" + to_string(status) + ":" + errString;
}
SGXException(int32_t _status, const char* _errString) : status(_status), errString(_errString) {}
const string& getErrString() const {
return errString;
}
std::string getMessage() {
return "SGXException:status:" + std::to_string(status) + ":" + errString;
const int32_t getStatus() const {
return status;
}
};
#endif //SGXD_RPCEXCEPTION_H
/*
Copyright (C) 2020-Present SKALE Labs
This file is part of sgxwallet.
sgxwallet is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
sgxwallet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with sgxwallet. If not, see <https://www.gnu.org/licenses/>.
@file SGXInfoServer.cpp
@author Oleh Nikolaiev
@date 2020
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include <stdio.h>
#include "sgxwallet_common.h"
#include "SGXException.h"
#include "LevelDB.h"
#include "SGXInfoServer.h"
#include "LevelDB.h"
#include "Log.h"
#include "common.h"
shared_ptr <SGXInfoServer> SGXInfoServer::server = nullptr;
shared_ptr <HttpServer> SGXInfoServer::httpServer = nullptr;
SGXInfoServer::SGXInfoServer(AbstractServerConnector &connector, serverVersion_t type,
uint32_t _logLevel, bool _autoSign, bool _checkCerts, bool _generateTestKeys)
: AbstractInfoServer(connector, type) {
logLevel_ = _logLevel;
autoSign_ = _autoSign;
checkCerts_ = _checkCerts;
generateTestKeys_ = _generateTestKeys;
}
Json::Value SGXInfoServer::getAllKeysInfo() {
Json::Value result;
try {
auto allKeysInfo = LevelDB::getLevelDb()->getAllKeys();
result["allKeys"] = allKeysInfo.first.str();
result["keysNumber"] = std::to_string(allKeysInfo.second);
} HANDLE_SGX_EXCEPTION(result)
RETURN_SUCCESS(result)
}
Json::Value SGXInfoServer::getLatestCreatedKey() {
Json::Value result;
try {
pair<string, uint64_t> key = LevelDB::getLevelDb()->getLatestCreatedKey();
result["keyName"] = key.first;
result["creationTime"] = std::to_string(key.second);
} HANDLE_SGX_EXCEPTION(result)
RETURN_SUCCESS(result)
}
Json::Value SGXInfoServer::getServerConfiguration() {
Json::Value result;
try {
result["autoConfirm"] = autoconfirm;
result["logLevel"] = logLevel_;
result["enterBackupKey"] = enterBackupKey;
result["useHTTPS"] = useHTTPS;
result["autoSign"] = autoSign_;
result["checkCerts"] = checkCerts_;
result["generateTestKeys"] = generateTestKeys_;
} HANDLE_SGX_EXCEPTION(result)
RETURN_SUCCESS(result)
}
Json::Value SGXInfoServer::isKeyExist(const string& key) {
Json::Value result;
result["isExists"] = false;
try {
shared_ptr <string> keyPtr = LevelDB::getLevelDb()->readString(key);
if (keyPtr != nullptr) {
result["IsExist"] = true;
}
} HANDLE_SGX_EXCEPTION(result)
RETURN_SUCCESS(result)
}
int SGXInfoServer::initInfoServer(uint32_t _logLevel, bool _autoSign, bool _checkCerts, bool _generateTestKeys) {
httpServer = make_shared<HttpServer>(BASE_PORT + 4);
server = make_shared<SGXInfoServer>(*httpServer, JSONRPC_SERVER_V2, _logLevel, _autoSign, _checkCerts, _generateTestKeys); // hybrid server (json-rpc 1.0 & 2.0)
if (!server->StartListening()) {
spdlog::error("Info server could not start listening on port {}", BASE_PORT + 4);
exit(-10);
} else {
spdlog::info("Info server started on port {}", BASE_PORT + 4);
}
return 0;
}
shared_ptr<SGXInfoServer> SGXInfoServer::getServer() {
CHECK_STATE(server);
return server;
}
/*
Copyright (C) 2020-Present SKALE Labs
This file is part of sgxwallet.
sgxwallet is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
sgxwallet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with sgxwallet. If not, see <https://www.gnu.org/licenses/>.
@file SGXInfoServer.h
@author Oleh Nikolaiev
@date 2020
*/
#ifndef SGXINFOSERVER_H
#define SGXINFOSERVER_H
#include <mutex>
#include "abstractinfoserver.h"
#include <jsonrpccpp/server/connectors/httpserver.h>
using namespace jsonrpc;
using namespace std;
class SGXInfoServer : public AbstractInfoServer {
recursive_mutex m;
uint32_t logLevel_;
bool autoSign_;
bool checkCerts_;
bool generateTestKeys_;
static shared_ptr <HttpServer> httpServer;
static shared_ptr <SGXInfoServer> server;
public:
static shared_ptr <SGXInfoServer> getServer();
SGXInfoServer(AbstractServerConnector &connector, serverVersion_t type,
uint32_t _logLevel, bool _autoSign, bool _checkCerts, bool _generateTestKeys);
virtual Json::Value getAllKeysInfo();
virtual Json::Value getLatestCreatedKey();
virtual Json::Value getServerConfiguration();
virtual Json::Value isKeyExist(const string& key);
static int initInfoServer(uint32_t _logLevel, bool _autoSign, bool _checkCerts, bool _generateTestKeys);
};
#endif // SGXINFOSERVER_H
......@@ -170,7 +170,7 @@ int SGXRegistrationServer::initRegistrationServer(bool _autoSign) {
if (!server->StartListening()) {
spdlog::error("Registration server could not start listening on port {}", BASE_PORT + 1);
exit(-1);
exit(-10);
} else {
spdlog::info("Registration server started on port {}", BASE_PORT + 1);
}
......
This diff is collapsed.
......@@ -25,6 +25,9 @@
#define SGXWALLET_SGXWALLETSERVER_HPP
#include "mutex"
#include "memory"
#include <jsonrpccpp/server/connectors/httpserver.h>
#include "abstractstubserver.h"
......@@ -35,9 +38,23 @@ using namespace std;
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
class SGXWalletServer : public AbstractStubServer {
static shared_ptr<SGXWalletServer> server;
static shared_ptr<HttpServer> httpServer;
static map<string,string> blsRequests;
static recursive_mutex blsRequestsLock;
static map<string,string> ecdsaRequests;
static recursive_mutex ecdsaRequestsLock;
static void checkForDuplicate(map <string, string> &_map, recursive_mutex &_m, const string &_key,
const string &_value);
public:
static const char* getVersion() {
return TOSTRING(SGXWALLET_VERSION);
......@@ -95,6 +112,8 @@ public:
virtual Json::Value dkgVerificationV2(const string &_publicShares, const string &ethKeyName, const string &SecretShare, int t, int n, int index);
virtual Json::Value createBLSPrivateKeyV2(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string & SecretShare, int t, int n);
static shared_ptr<string> readFromDb(const string &name, const string &prefix = "");
static shared_ptr <string> checkDataFromDb(const string &name, const string &prefix = "");
......@@ -151,6 +170,8 @@ public:
static Json::Value dkgVerificationV2Impl(const string &_publicShares, const string &_ethKeyName, const string &_secretShare, int _t, int _n, int _index);
virtual Json::Value createBLSPrivateKeyV2Impl(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string & SecretShare, int t, int n);
static void printDB();
static int initHttpServer();
......
......@@ -39,6 +39,8 @@
#include "third_party/spdlog/spdlog.h"
#include <gmp.h>
#include <sgx_urts.h>
#include <unistd.h>
#include "BLSPrivateKeyShareSGX.h"
......@@ -50,15 +52,46 @@
#include "LevelDB.h"
#include "SGXWalletServer.h"
#include "SGXRegistrationServer.h"
#include "SGXInfoServer.h"
#include "SEKManager.h"
#include "CSRManagerServer.h"
#include "BLSCrypto.h"
#include "ServerInit.h"
#include "SGXException.h"
#include "ZMQServer.h"
#include "SGXWalletServer.hpp"
uint32_t enclaveLogLevel = 0;
using namespace std;
void systemHealthCheck() {
string ulimit;
try {
ulimit = exec( "/bin/bash -c \"ulimit -n\"" );
} catch ( ... ) {
spdlog::error("Execution of '/bin/bash -c ulimit -n' failed");
exit(-15);
}
int noFiles = strtol( ulimit.c_str(), NULL, 10 );
auto noUlimitCheck = getenv( "NO_ULIMIT_CHECK" ) != nullptr;
if ( noFiles < 65535 && !noUlimitCheck) {
string errStr =
"sgxwallet requires setting Linux file descriptor limit to at least 65535 "
"You current limit (ulimit -n) is less than 65535. \n Please set it to 65535:"
"by editing /etc/systemd/system.conf"
"and setting 'DefaultLimitNOFILE=65535'\n"
"After that, restart sgxwallet";
spdlog::error(errStr);
exit(-16);
}
}
static ZMQServer* zmqServer = nullptr;
atomic<bool> exiting(false);
void initUserSpace() {
libff::inhibit_profiling_counters = true;
......@@ -66,6 +99,30 @@ void initUserSpace() {
libff::init_alt_bn128_params();
LevelDB::initDataFolderAndDBs();
#ifndef SGX_HW_SIM
systemHealthCheck();
#endif
#ifdef EXPERIMENTAL_ZMQ_SERVER
zmqServer = new ZMQServer();
static std::thread serverThread(std::bind(&ZMQServer::run, zmqServer));
#endif
}
void exitZMQServer() {
#ifdef EXPERIMENTAL_ZMQ_SERVER
auto doExit = !exiting.exchange(true);
if (doExit) {
spdlog::info("Exiting zmq server ...");
delete zmqServer;
spdlog::info("Exited zmq server ...");
zmqServer = nullptr;
}
#endif
}
uint64_t initEnclave() {
......@@ -76,7 +133,7 @@ uint64_t initEnclave() {
support = get_sgx_support();
if (!SGX_OK(support)) {
sgx_support_perror(support);
exit(1);
exit(-17);
}
#endif
......@@ -107,7 +164,7 @@ uint64_t initEnclave() {
} else {
spdlog::error("sgx_create_enclave_search failed {} {}", ENCLAVE_NAME, status);
}
exit(1);
exit(-21);
}
spdlog::info("Enclave created and started successfully");
......@@ -127,8 +184,8 @@ uint64_t initEnclave() {
void initAll(uint32_t _logLevel, bool _checkCert, bool _autoSign, bool _generateTestKeys) {
void initAll(uint32_t _logLevel, bool _checkCert, bool _autoSign) {
static atomic<bool> sgxServerInited(false);
static mutex initMutex;
......@@ -146,7 +203,7 @@ void initAll(uint32_t _logLevel, bool _checkCert, bool _autoSign) {
CHECK_STATE(sgxServerInited != 1)
sgxServerInited = 1;
uint64_t counter = 0;
uint64_t counter = 0;
uint64_t initResult = 0;
while ((initResult = initEnclave()) != 0 && counter < 10){
......@@ -168,18 +225,20 @@ void initAll(uint32_t _logLevel, bool _checkCert, bool _autoSign) {
} else {
SGXWalletServer::initHttpServer();
}
SGXInfoServer::initInfoServer(_logLevel, _checkCert, _autoSign, _generateTestKeys);
sgxServerInited = true;
} catch (SGXException &_e) {
spdlog::error(_e.getMessage());
exit(-1);
exit(-18);
} catch (exception &_e) {
spdlog::error(_e.what());
exit(-1);
exit(-19);
}
catch (...) {
exception_ptr p = current_exception();
printf("Exception %s \n", p.__cxa_exception_type()->name());
spdlog::error("Unknown exception");
exit(-1);
exit(-22);
}
};
......@@ -32,12 +32,14 @@
#define EXTERNC
#endif
EXTERNC void initAll(uint32_t _logLevel, bool _checkCert, bool _autoSign);
EXTERNC void initAll(uint32_t _logLevel, bool _checkCert, bool _autoSign, bool _generateTestKeys);
EXTERNC void initUserSpace();
EXTERNC uint64_t initEnclave();
EXTERNC void exitZMQServer();
#endif //SGXWALLET_SERVERINIT_H
//
// Created by kladko on 14.12.20.
//
#include "common.h"
#include <json/writer.h>
#include "ZMQMessage.h"
#include "ServerWorker.h"
ServerWorker::ServerWorker(zmq::context_t &ctx, int sock_type) : ctx_(ctx),
worker_(ctx_, sock_type) {};
void ServerWorker::work() {
worker_.connect("inproc://backend");
try {
while (true) {
zmq::message_t msg;
zmq::message_t copied_msg;
worker_.recv(&msg);
vector<uint8_t> msgData(msg.size() + 1, 0);
memcpy(msgData.data(), msg.data(), msg.size());
auto parsedMsg = ZMQMessage::parse(msgData);
CHECK_STATE(parsedMsg);
auto reply = parsedMsg->process();
Json::FastWriter fastWriter;
std::string replyStr = fastWriter.write(reply);
zmq::message_t replyMsg(replyStr.c_str(),replyStr.size() + 1);
worker_.send(replyMsg);
}
}
catch (std::exception &e) {
spdlog::info("Exiting zmq server worker:{}", e.what());
return;
} catch (...) {
spdlog::error("Error in zmq server worker");
return;
}
}
//
// Created by kladko on 14.12.20.
//
#ifndef SGXWALLET_SERVERWORKER_H
#define SGXWALLET_SERVERWORKER_H
#include <vector>
#include <thread>
#include <memory>
#include <functional>
#include "abstractstubserver.h"
#include <zmq.hpp>
#include "zhelpers.hpp"
#include "third_party/spdlog/spdlog.h"
#include "document.h"
class ServerWorker {
public:
ServerWorker(zmq::context_t &ctx, int sock_type );
void work();
private:
zmq::context_t &ctx_;
zmq::socket_t worker_;
};
#endif //SGXWALLET_SERVERWORKER_H
......@@ -21,10 +21,8 @@
@date 2020
*/
#include <dkg/dkg.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include <libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp>
#include <dkg/dkg.h>
#include "sgxwallet_common.h"
#include "third_party/intel/create_enclave.h"
#include "secure_enclave_u.h"
......@@ -241,7 +239,7 @@ void TestUtils::sendRPCRequest() {
auto hash_arr = make_shared < array < uint8_t, 32 >> ();
uint64_t binLen;
if (!hex2carray(hash.c_str(), &binLen, hash_arr->data(), 32)) {
throw SGXException(INVALID_HEX, "Invalid hash");
throw SGXException(TEST_INVALID_HEX, "Invalid hash");
}
map <size_t, shared_ptr<BLSPublicKeyShare>> coeffs_pkeys_map;
......@@ -355,7 +353,7 @@ void TestUtils::sendRPCRequestV2() {
auto hash_arr = make_shared < array < uint8_t, 32 >> ();
uint64_t binLen;
if (!hex2carray(hash.c_str(), &binLen, hash_arr->data(), 32)) {
throw SGXException(INVALID_HEX, "Invalid hash");
throw SGXException(TEST_INVALID_HEX, "Invalid hash");
}
map <size_t, shared_ptr<BLSPublicKeyShare>> coeffs_pkeys_map;
......@@ -373,7 +371,7 @@ void TestUtils::sendRPCRequestV2() {
string blsName = "BLS_KEY" + polyNames[i].substr(4);
string secretShare = secretShares[i]["secretShare"].asString();
auto response = c.createBLSPrivateKey(blsName, ethKeys[i]["keyName"].asString(), polyNames[i], secShares[i], t, n);
auto response = c.createBLSPrivateKeyV2(blsName, ethKeys[i]["keyName"].asString(), polyNames[i], secShares[i], t, n);
CHECK_STATE(response["status"] == 0);
pubBLSKeys[i] = c.getBLSPublicKeyShare(blsName);
CHECK_STATE(pubBLSKeys[i]["status"] == 0);
......@@ -488,7 +486,7 @@ void TestUtils::doDKG(StubClient &c, int n, int t,
auto hash_arr = make_shared<array<uint8_t, 32 >>();
uint64_t binLen;
if (!hex2carray(hash.c_str(), &binLen, hash_arr->data(), 32)) {
throw SGXException(INVALID_HEX, "Invalid hash");
throw SGXException(TEST_INVALID_HEX, "Invalid hash");
}
map<size_t, shared_ptr<BLSPublicKeyShare>> pubKeyShares;
......@@ -629,7 +627,7 @@ void TestUtils::doDKGV2(StubClient &c, int n, int t,
auto hash_arr = make_shared<array<uint8_t, 32 >>();
uint64_t binLen;
if (!hex2carray(hash.c_str(), &binLen, hash_arr->data(), 32)) {
throw SGXException(INVALID_HEX, "Invalid hash");
throw SGXException(TEST_INVALID_HEX, "Invalid hash");
}
map<size_t, shared_ptr<BLSPublicKeyShare>> pubKeyShares;
......@@ -640,7 +638,7 @@ void TestUtils::doDKGV2(StubClient &c, int n, int t,
_blsKeyNames.push_back(blsName);
string secretShare = secretShares[i]["secretShare"].asString();
auto response = c.createBLSPrivateKey(blsName, ethKeys[i]["keyName"].asString(), polyNames[i], secShares[i], t,
auto response = c.createBLSPrivateKeyV2(blsName, ethKeys[i]["keyName"].asString(), polyNames[i], secShares[i], t,
n);
CHECK_STATE(response["status"] == 0);
pubBLSKeys[i] = c.getBLSPublicKeyShare(blsName);
......@@ -721,7 +719,6 @@ int sessionKeyRecoverDH(const char *skey_str, const char *sshare, char *common_k
mpz_clear(skey);
point_clear(pub_keyB);
point_clear(session_key);
return ret;
}
......
1.59.1
\ No newline at end of file
1.70.0
/*
Copyright (C) 2020 SKALE Labs
This file is part of skale-consensus.
skale-consensus is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
skale-consensus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with skale-consensus. If not, see <https://www.gnu.org/licenses/>.
@file ZMQMessage.cpp
@author Stan Kladko
@date 2020
*/
#include "common.h"
#include "BLSSignReqMessage.h"
#include "ECDSASignReqMessage.h"
#include "ZMQMessage.h"
uint64_t ZMQMessage::getUint64Rapid(const char *_name) {
CHECK_STATE(_name);
CHECK_STATE(d->HasMember(_name));
const rapidjson::Value& a = (*d)[_name];
CHECK_STATE(a.IsUint64());
return a.GetUint64();
};
string ZMQMessage::getStringRapid(const char *_name) {
CHECK_STATE(_name);
CHECK_STATE(d->HasMember(_name));
CHECK_STATE((*d)[_name].IsString());
return (*d)[_name].GetString();
};
shared_ptr<ZMQMessage> ZMQMessage::parse(vector<uint8_t>& _msg) {
CHECK_STATE(_msg.at(_msg.size() - 1) == 0);
auto d = make_shared<rapidjson::Document>();
d->Parse((const char*) _msg.data());
CHECK_STATE(!d->HasParseError());
CHECK_STATE(d->IsObject())
CHECK_STATE(d->HasMember("type"));
CHECK_STATE((*d)["type"].IsString());
auto type = (*d)["type"].GetString();
shared_ptr<ZMQMessage> result;
if (type == ZMQMessage::BLS_SIGN_REQ) {
result = make_shared<BLSSignReqMessage>(d);
} else if (type == ZMQMessage::ECDSA_SIGN_REQ) {
result = make_shared<ECDSASignReqMessage>(d);
} else {
throw SGXException(-301, "Incorrect zmq message type: " + string(type));
}
return result;
}
/*
Copyright (C) 2018-2019 SKALE Labs
This file is part of skale-consensus.
skale-consensus is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
skale-consensus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with skale-consensus. If not, see <https://www.gnu.org/licenses/>.
@file ZMQMessage.h
@author Stan Kladko
@date 2018
*/
#pragma once
#include <memory>
#include <vector>
#include "abstractstubserver.h"
#include "document.h"
#include "SGXException.h"
using namespace std;
class ZMQMessage {
shared_ptr<rapidjson::Document> d;
static constexpr const char *BLS_SIGN_REQ = "BLSSignReq";
static constexpr const char *BLS_SIGN_RSP = "BLSSignRsp";
static constexpr const char *ECDSA_SIGN_REQ = "ECDSASignReq";
static constexpr const char *ECDSA_SIGN_RSP = "ECDSASignRsp";
protected:
public:
explicit ZMQMessage(shared_ptr<rapidjson::Document> &_d) : d(_d) {
};
string getStringRapid(const char *_name);
uint64_t getUint64Rapid(const char *_name);
static shared_ptr<ZMQMessage> parse(vector<uint8_t> &_msg);
virtual Json::Value process() = 0;
};
\ No newline at end of file
......@@ -16,65 +16,73 @@
You should have received a copy of the GNU Affero General Public License
along with sgxwallet. If not, see <https://www.gnu.org/licenses/>.
@file cert_util.cpp
@file ZMQServer.cpp
@author Stan Kladko
@date 2019
*/
#include <iostream>
#include <cstring>
#include <jsonrpccpp/client/connectors/httpclient.h>
#include "stubclient.h"
#include <unistd.h>
int print_hashes(){
jsonrpc::HttpClient client("http://localhost:1028");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Client inited" << std::endl;
std::cout << c.getUnsignedCSRs() << std::endl;
exit(0);
}
#include "third_party/spdlog/spdlog.h"
void sign_by_hash(std::string & hash, int status){
jsonrpc::HttpClient client("http://localhost:1028");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Client inited" << std::endl;
std::cout << c.signByHash(hash, status) << std::endl;
exit(0);
}
#include "ZMQServer.h"
#include "sgxwallet_common.h"
using namespace std;
ZMQServer::ZMQServer()
: isExitRequested(false), ctx_(1),
frontend_(ctx_, ZMQ_ROUTER),
backend_(ctx_, ZMQ_DEALER) {}
void ZMQServer::run() {
auto port = BASE_PORT + 4;
spdlog::info("Starting zmq server ...");
try {
frontend_.bind("tcp://*:" + to_string(BASE_PORT + 4));
} catch (...) {
spdlog::error("Server task could not bind to port:{}", port);
exit(-100);
}
int main(int argc, char *argv[]) {
int opt;
if (argc > 1 && strlen(argv[1]) == 1) {
fprintf(stderr, "option is too short %s\n", argv[1]);
exit(1);
}
if (argc == 1) {
std::cout << "You may use following flags:" << std::endl;
std::cout << " -p print all unsigned csr hashes " << std::endl;
std::cout << " -s [hash] sign csr by hash" << std::endl;
std::cout << " -r [hash] reject csr by hash" << std::endl;
exit(0);
}
std::string hash;
while ((opt = getopt(argc, argv, "ps:r:")) != -1) {
switch (opt) {
case 'p': print_hashes();
break;
case 's': hash = optarg;
sign_by_hash(hash, 0);
break;
case 'r': hash = optarg;
sign_by_hash(hash, 2);
break;
case '?': // fprintf(stderr, "unknown flag\n");
exit(1);
}
}
return 0;
spdlog::info("Bound port ...");
try {
backend_.bind("inproc://backend");
} catch (exception &e) {
spdlog::error("Could not bind to zmq backend: {}", e.what());
exit(-101);
}
spdlog::info("Creating {} zmq server workers ...", kMaxThread);
try {
for (int i = 0; i < kMaxThread; ++i) {
worker.push_back(new ServerWorker(ctx_, ZMQ_DEALER));
worker_thread.push_back(new std::thread(std::bind(&ServerWorker::work, worker[i])));
}
} catch (std::exception &e) {
spdlog::error("Could not create zmq server workers:{} ", e.what());
exit(-102);
}
try {
zmq::proxy(static_cast<void *>(frontend_), static_cast<void *>(backend_), nullptr);
} catch (exception& _e) {
spdlog::info("Exiting zmq server {}", _e.what());
return;
} catch (...) {
spdlog::info("Exiting zmq server");
return;
}
}
/*
Copyright (C) 2019-Present SKALE Labs
This file is part of sgxwallet.
sgxwallet is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
sgxwallet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with sgxwallet. If not, see <https://www.gnu.org/licenses/>.
@file ZMQServer.h
@author Stan Kladko
@date 2020
*/
#ifndef SGXWALLET_ZMQServer_H
#define SGXWALLET_ZMQServer_H
#include <vector>
#include <thread>
#include <memory>
#include <functional>
#include <atomic>
#include <zmq.hpp>
#include "zhelpers.hpp"
#include "ServerWorker.h"
using namespace std;
class ZMQServer {
public:
ZMQServer();
atomic<bool> isExitRequested;
enum {
kMaxThread = 5
};
void run();
private:
zmq::context_t ctx_;
zmq::socket_t frontend_;
zmq::socket_t backend_;
std::vector<ServerWorker *> worker;
std::vector<std::thread *> worker_thread;
};
#endif //SGXWALLET_ZMQServer_H
/*
Copyright (C) 2020-Present SKALE Labs
This file is part of sgxwallet.
sgxwallet is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
sgxwallet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with sgxwallet. If not, see <https://www.gnu.org/licenses/>.
@file abstractinfoserver.h
@author Oleh Nikolaiev
@date 2020
*/
#ifndef ABSTRACTINFOSERVER_H
#define ABSTRACTINFOSERVER_H
#include <jsonrpccpp/server.h>
#include <iostream>
class AbstractInfoServer : public jsonrpc::AbstractServer<AbstractInfoServer>
{
public:
AbstractInfoServer(jsonrpc::AbstractServerConnector &conn, jsonrpc::serverVersion_t type = jsonrpc::JSONRPC_SERVER_V2) : jsonrpc::AbstractServer<AbstractInfoServer>(conn, type)
{
this->bindAndAddMethod(jsonrpc::Procedure("getAllKeysInfo", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, NULL), &AbstractInfoServer::getAllKeysInfoI);
this->bindAndAddMethod(jsonrpc::Procedure("getLatestCreatedKey", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, NULL), &AbstractInfoServer::getLatestCreatedKeyI);
this->bindAndAddMethod(jsonrpc::Procedure("getServerConfiguration", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, NULL), &AbstractInfoServer::getServerConfigurationI);
this->bindAndAddMethod(jsonrpc::Procedure("isKeyExist", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT,"keyName",jsonrpc::JSON_STRING, NULL), &AbstractInfoServer::isKeyExistI);
}
inline virtual void getAllKeysInfoI(const Json::Value &request, Json::Value &response)
{
response = this->getAllKeysInfo();
}
inline virtual void getLatestCreatedKeyI(const Json::Value &request, Json::Value &response)
{
response = this->getLatestCreatedKey();
}
inline virtual void getServerConfigurationI(const Json::Value &request, Json::Value &response)
{
response = this->getServerConfiguration();
}
inline virtual void isKeyExistI(const Json::Value &request, Json::Value &response)
{
response = this->isKeyExist(request["keyName"].asString());
}
virtual Json::Value getAllKeysInfo() = 0;
virtual Json::Value getLatestCreatedKey() = 0;
virtual Json::Value getServerConfiguration() = 0;
virtual Json::Value isKeyExist(const std::string& key) = 0;
};
#endif // ABSTRACTINFOSERVER_H
......@@ -61,6 +61,7 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer>
this->bindAndAddMethod(jsonrpc::Procedure("getSecretShareV2", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "polyName",jsonrpc::JSON_STRING,"publicKeys",jsonrpc::JSON_ARRAY, "n",jsonrpc::JSON_INTEGER,"t",jsonrpc::JSON_INTEGER, NULL), &AbstractStubServer::getSecretShareV2I);
this->bindAndAddMethod(jsonrpc::Procedure("dkgVerificationV2", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "publicShares",jsonrpc::JSON_STRING, "ethKeyName",jsonrpc::JSON_STRING, "secretShare",jsonrpc::JSON_STRING,"t",jsonrpc::JSON_INTEGER, "n",jsonrpc::JSON_INTEGER, "index",jsonrpc::JSON_INTEGER, NULL), &AbstractStubServer::dkgVerificationV2I);
this->bindAndAddMethod(jsonrpc::Procedure("createBLSPrivateKeyV2", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "blsKeyName",jsonrpc::JSON_STRING, "ethKeyName",jsonrpc::JSON_STRING, "polyName", jsonrpc::JSON_STRING, "secretShare",jsonrpc::JSON_STRING,"t", jsonrpc::JSON_INTEGER,"n",jsonrpc::JSON_INTEGER, NULL), &AbstractStubServer::createBLSPrivateKeyV2I);
}
inline virtual void importBLSKeyShareI(const Json::Value &request, Json::Value &response)
......@@ -155,6 +156,10 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer>
{
response = this->dkgVerificationV2(request["publicShares"].asString(), request["ethKeyName"].asString(), request["secretShare"].asString(), request["t"].asInt(), request["n"].asInt(), request["index"].asInt());
}
inline virtual void createBLSPrivateKeyV2I(const Json::Value &request, Json::Value &response)
{
response = this->createBLSPrivateKeyV2(request["blsKeyName"].asString(), request["ethKeyName"].asString(), request["polyName"].asString(),request["secretShare"].asString(),request["t"].asInt(), request["n"].asInt());
}
virtual Json::Value importBLSKeyShare(const std::string& keyShare, const std::string& keyShareName) = 0;
virtual Json::Value blsSignMessageHash(const std::string& keyShareName, const std::string& messageHash, int t, int n ) = 0;
......@@ -167,8 +172,8 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer>
virtual Json::Value getVerificationVector(const std::string& polyName, int t, int n) = 0;
virtual Json::Value getSecretShare(const std::string& polyName, const Json::Value& publicKeys, int t, int n) = 0;
virtual Json::Value dkgVerification( const std::string& publicShares, const std::string& ethKeyName, const std::string& SecretShare, int t, int n, int index) = 0;
virtual Json::Value createBLSPrivateKey(const std::string & blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string & SecretShare, int t, int n) = 0;
virtual Json::Value getBLSPublicKeyShare(const std::string & blsKeyName) = 0;
virtual Json::Value createBLSPrivateKey(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string& SecretShare, int t, int n) = 0;
virtual Json::Value getBLSPublicKeyShare(const std::string& blsKeyName) = 0;
virtual Json::Value calculateAllBLSPublicKeys(const Json::Value& publicShares, int t, int n) = 0;
virtual Json::Value complaintResponse(const std::string& polyName, int t, int n, int ind) = 0;
virtual Json::Value multG2(const std::string & x) = 0;
......@@ -180,6 +185,7 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer>
virtual Json::Value getSecretShareV2(const std::string& polyName, const Json::Value& publicKeys, int t, int n) = 0;
virtual Json::Value dkgVerificationV2( const std::string& publicShares, const std::string& ethKeyName, const std::string& SecretShare, int t, int n, int index) = 0;
virtual Json::Value createBLSPrivateKeyV2(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string & SecretShare, int t, int n) = 0;
};
#endif //JSONRPC_CPP_STUB_ABSTRACTSTUBSERVER_H_
......@@ -32,11 +32,18 @@ using namespace std;
#include <map>
#include <memory>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <string.h>
#include <vector>
#include <boost/throw_exception.hpp>
#include <gmp.h>
#include "secure_enclave/Verify.h"
#include "InvalidStateException.h"
#include "SGXException.h"
#define SAFE_FREE(__POINTER__) {if (__POINTER__) {free(__POINTER__); __POINTER__ = NULL;}}
......@@ -64,15 +71,41 @@ inline void print_stack() {
// print out all the frames to stderr
fprintf(stderr, "Error: signal \n");
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
exit(-1);
}
inline int parseLine(char* line) {
// This assumes that a digit will be found and the line ends in " Kb".
int i = strlen(line);
const char* p = line;
while (*p <'0' || *p > '9') p++;
line[i-3] = '\0';
i = atoi(p);
return i;
}
inline int getValue() { //Note: this value is in KB!
FILE* file = fopen("/proc/self/status", "r");
int result = -1;
char line[128];
while (fgets(line, 128, file) != NULL){
if (strncmp(line, "VmRSS:", 6) == 0){
result = parseLine(line);
break;
}
}
fclose(file);
return result;
}
#define CHECK_STATE(_EXPRESSION_) \
if (!(_EXPRESSION_)) { \
auto __msg__ = std::string("State check failed::") + #_EXPRESSION_ + " " + std::string(__FILE__) + ":" + std::to_string(__LINE__); \
print_stack(); \
throw InvalidStateException(__msg__, __CLASS_NAME__);}
BOOST_THROW_EXCEPTION(SGXException(-100, string(__CLASS_NAME__) + ":" + __msg__));}
#define HANDLE_TRUSTED_FUNCTION_ERROR(__STATUS__, __ERR_STATUS__, __ERR_MSG__) \
......@@ -81,7 +114,7 @@ string __ERR_STRING__ = string("SGX enclave call to ") + \
__FUNCTION__ + " failed with status:" \
+ to_string(__STATUS__) + \
" Err message:" + __ERR_MSG__; \
BOOST_THROW_EXCEPTION(runtime_error(__ERR_MSG__)); \
BOOST_THROW_EXCEPTION(SGXException(-102, string(__ERR_MSG__))); \
}\
\
if (__ERR_STATUS__ != 0) {\
......@@ -96,17 +129,30 @@ BOOST_THROW_EXCEPTION(runtime_error(__ERR_STRING__)); \
#define SAFE_CHAR_BUF(__X__, __Y__) ;char __X__ [ __Y__ ]; memset(__X__, 0, __Y__);
#define SAFE_UINT8_BUF(__X__, __Y__) ;uint8_t __X__ [ __Y__ ]; memset(__X__, 0, __Y__);
// Copy from libconsensus
inline string exec( const char* cmd ) {
CHECK_STATE( cmd );
std::array< char, 128 > buffer;
std::string result;
std::unique_ptr< FILE, decltype( &pclose ) > pipe( popen( cmd, "r" ), pclose );
if ( !pipe ) {
BOOST_THROW_EXCEPTION( std::runtime_error( "popen() failed!" ) );
}
while ( fgets( buffer.data(), buffer.size(), pipe.get() ) != nullptr ) {
result += buffer.data();
}
return result;
}
#include <shared_mutex>
extern std::shared_timed_mutex sgxInitMutex;
extern uint64_t initTime;
#ifdef SGX_HW_SIM
#define ENCLAVE_RESTART_PERIOD_S 5
#else
#define ENCLAVE_RESTART_PERIOD_S 60 * 10
#endif
#define LOCK(__X__) std::lock_guard<std::recursive_mutex> __LOCK__(__X__);
#define READ_LOCK(__X__) std::shared_lock<std::shared_timed_mutex> __LOCK__(__X__);
#define WRITE_LOCK(__X__) std::unique_lock<std::shared_timed_mutex> __LOCK__(__X__);
......
Subproject commit 18db4568f9ff1568193d3a496d87bed4bc9ec59e
......@@ -5,6 +5,7 @@
- [Verify that your hardware and software can run SGX](prerequisites.md)
- [Enable SGX](enabling-sgx.md)
- [Start, stop and upgrade sgxwallet](run-in-hardware-mode.md)
- [Increase max process limit](run-in-hardware-mode.md#increase-max-process-limit)
- [Docker Compose configuration](run-in-hardware-mode.md#docker-compose-configuration)
- [Run sgxwallet in secure mode](run-in-hardware-mode.md#run-sgxwallet-in-secure-mode)
- [Start, stop and upgrade sgxwallet containers](run-in-hardware-mode.md#start-stop-and-upgrade-sgxwallet-containers)
......
......@@ -22,7 +22,7 @@ Docker engine is pre-installed on Ubuntu 18.04. You can re-install it as
described below
```bash
sudo apt-get install -y docker-io
sudo apt-get install -y docker.io
```
To verify a correct installation, run `sudo docker run hello-world`
......@@ -55,9 +55,6 @@ curl -I http://whitelist.trustedservices.intel.com/SGX/LCWL/Linux/sgx_white_lis
If you need to set advanced options, such as outgoing network proxy, edit "/etc/aesmd.conf" file in
the sgxwallet docker container.
#endif"
### Verify SGX support
Install cpuid and libelf-dev packages:
......
......@@ -2,11 +2,32 @@
# Run in hardware secure mode
- [Increase max process limit](#increase-max-process-limit)
- [Docker Compose configuration](#docker-compose-configuration)
- [Run sgxwallet in secure mode](#run-sgxwallet-in-secure-mode)
- [Start, stop and upgrade sgxwallet containers](#start-stop-and-upgrade-sgxwallet-containers)
- [Logging](#logging)
## Increase max process limit
sgxwallet requires setting Linux ulimit to at least 65535.
To display you current limit, run
```
ulimit -n
```
If you current ulimit is less than 65535, please set it to 65535 by editing /etc/systemd/system.conf
and setting
```
DefaultLimitNOFILE=65535
```
Then reboot and check ulimit again.
## Docker Compose configuration
Install docker-compose:
......
......@@ -90,12 +90,11 @@ make
make install
cd ..
#tar -xzf ./pre_downloaded/libjson-rpc-cpp.tar.gz
git clone https://github.com/skalenetwork/libjson-rpc-cpp.git --recursive
cd libjson-rpc-cpp
git checkout develop
git pull
rn -rf build || true
rm -rf build || true
mkdir -p build
cd build
cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_ROOT -DCMAKE_BUILD_TYPE=$TOP_CMAKE_BUILD_TYPE \
......
Subproject commit 75dfbae0d1dc65312d2aaad6902911a3214f4819
Subproject commit 0ccdbf364c577803e2a751f5aededce935314313
......@@ -8,6 +8,7 @@ services:
- "1027:1027"
- "1028:1028"
- "1029:1029"
- "1030:1030"
devices:
- "/dev/isgx"
- "/dev/mei0"
......
......@@ -8,6 +8,7 @@ services:
- "1027:1027"
- "1028:1028"
- "1029:1029"
- "1030:1030"
volumes:
- ./sgx_data:/usr/src/sdk/sgx_data
- /dev/urandom:/dev/random
......
......@@ -34,14 +34,21 @@ makeExecutable = subprocess.check_output(["which", "make"])
SCRIPTS_DIR = topDir + "/scripts"
GMP_DIR = topDir + "/sgx-gmp"
SGX_SDK_DIR_SSL = topDir + "/sgx-sdk-build/sgxsdk"
ZMQ_DIR = topDir + "/libzmq"
ZMQ_BUILD_DIR = ZMQ_DIR + "/build"
CZMQ_DIR = topDir + "/cppzmq"
CZMQ_BUILD_DIR = CZMQ_DIR + "/build"
LEVELDB_DIR = topDir + "/leveldb"
LEVELDB_BUILD_DIR = LEVELDB_DIR + "/build"
GMP_BUILD_DIR = topDir + "/gmp-build"
TGMP_BUILD_DIR = topDir + "/tgmp-build"
SDK_DIR = topDir + "/sgx-sdk-build"
JSON_LIBS_DIR = topDir + "/jsonrpc"
BLS_DIR = topDir + "/libBLS"
BLS_BUILD_DIR = BLS_DIR + "/build"
JSON_LIBS_DIR = topDir + "/jsonrpc"
print("Cleaning")
......@@ -58,17 +65,13 @@ subprocess.call(["rm", "-rf", TGMP_BUILD_DIR])
subprocess.call(["rm", "-rf", SDK_DIR])
assert subprocess.call(["cp", "configure.gmp", GMP_DIR + "/configure"]) == 0
print("Build LevelDB");
os.chdir(LEVELDB_DIR)
assert subprocess.call(["bash", "-c", "mkdir -p build"]) == 0
os.chdir(LEVELDB_BUILD_DIR)
assert subprocess.call(["bash", "-c", "cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build ."]) == 0
assert subprocess.call(["cp", "configure.gmp", GMP_DIR + "/configure"]) == 0
print("Build LibBLS");
os.chdir(BLS_DIR + "/deps")
......@@ -77,7 +80,23 @@ os.chdir(BLS_DIR)
assert subprocess.call(["bash", "-c", "cmake -H. -Bbuild"]) == 0
os.chdir(BLS_DIR + "/build")
assert subprocess.call(["bash", "-c", "make"]) == 0
print("Build ZMQ");
os.chdir(ZMQ_DIR)
assert subprocess.call(["bash", "-c", "mkdir -p build"]) == 0
os.chdir(ZMQ_BUILD_DIR)
assert subprocess.call(["bash", "-c", "cmake -DDZMQ_EXPERIMENTAL=1 -DCMAKE_BUILD_TYPE=Release .. && cmake --build ."]) == 0
print("Build LevelDB");
os.chdir(LEVELDB_DIR)
assert subprocess.call(["bash", "-c", "mkdir -p build"]) == 0
os.chdir(LEVELDB_BUILD_DIR)
assert subprocess.call(["bash", "-c", "cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build ."]) == 0
print("Build JSON");
os.chdir(JSON_LIBS_DIR)
......
......@@ -18,7 +18,7 @@ openssl dgst -sha256 -out ../signed_enclaves/skale_sgx_enclave_signature${ENCLAV
rm -rf ../signed_enclaves/submission${ENCLAVE_VERSION}
mkdir -p ../signed_enclaves/submission${ENCLAVE_VERSION}
/opt/intel/sgxsdk/bin/x64/sgx_sign dump -enclave ../signed_enclaves/secure_enclave_signed${ENCLAVE_VERSION}.so -dumpfile ../signed_enclaves/skale_sgx_enclave_metadata_info${ENCLAVE_VERSION}.txt -cssfile ../signed_enclaves/submission${ENCLAVE_VERSION}/nodeanstalt_sgxwallet_PUTWHITELISTENTRYIDHERE_sigstruct.bin
/opt/intel/sgxsdk/bin/x64/sgx_sign dump -enclave ../signed_enclaves/secure_enclave_signed${ENCLAVE_VERSION}.so -dumpfile ../signed_enclaves/skale_sgx_enclave_metadata_info${ENCLAVE_VERSION}.txt -cssfile ../signed_enclaves/submission${ENCLAVE_VERSION}/nodeanstalt_sgxwallet_180_sigstruct.bin
tail -n 6 ../signed_enclaves/skale_sgx_enclave_metadata_info${ENCLAVE_VERSION}.txt > ../signed_enclaves/submission${ENCLAVE_VERSION}/skale_sgx_enclave_mrsigner${ENCLAVE_VERSION}.txt
......
......@@ -345,7 +345,13 @@ int hash_key(char* key, char* hashed_key) {
return ret;
}
ret = sgx_sha256_msg((uint8_t*)key, ECDSA_SKEY_LEN - 1, (uint8_t*)hashed_key);
uint8_t key_to_hash[33];
uint64_t len;
if (!hex2carray(key, &len, key_to_hash)) {
return ret;
}
ret = sgx_sha256_msg(key_to_hash, ECDSA_BIN_LEN - 1, (uint8_t*)hashed_key);
return ret;
}
......@@ -62,7 +62,7 @@ ENCLAVE_KEY=test_insecure_private_key.pem #$(ENCLAVE)_private.pem
## Additional Automake flags needed to build the enclave.
AM_CPPFLAGS += -Wall -Wno-implicit-function-declaration $(TGMP_CPPFLAGS) -I./third_party/SCIPR -I../third_party/SCIPR -I../sgx-sdk-build/sgxsdk/include/libcxx
AM_CPPFLAGS += -O2 -Wall -Wno-implicit-function-declaration $(TGMP_CPPFLAGS) -I./third_party/SCIPR -I../third_party/SCIPR -I../sgx-sdk-build/sgxsdk/include/libcxx
AM_CXXFLAGS += -fno-builtin -fstack-protector-strong
......
#define SIGNED_ENCLAVE_VERSION "2"
\ No newline at end of file
#define SIGNED_ENCLAVE_VERSION "3"
......@@ -1244,6 +1244,117 @@ void trustedCreateBlsKey(int *errStatus, char *errString, const char *s_shares,
LOG_INFO("SGX call completed");
}
void trustedCreateBlsKeyV2(int *errStatus, char *errString, const char *s_shares,
uint8_t *encryptedPrivateKey, uint64_t key_len, uint8_t *encr_bls_key,
uint64_t *enc_bls_key_len) {
LOG_INFO(__FUNCTION__);
INIT_ERROR_STATE
CHECK_STATE(s_shares);
CHECK_STATE(encryptedPrivateKey);
CHECK_STATE(encr_bls_key);
SAFE_CHAR_BUF(skey, BUF_LEN);
mpz_t sum;
mpz_init(sum);
mpz_set_ui(sum, 0);
mpz_t q;
mpz_init(q);
mpz_set_str(q, "21888242871839275222246405745257275088548364400416034343698204186575808495617", 10);
mpz_t bls_key;
mpz_init(bls_key);
uint8_t type = 0;
uint8_t exportable = 0;
int status = AES_decrypt(encryptedPrivateKey, key_len, skey, BUF_LEN,
&type, &exportable);
CHECK_STATUS2("aes decrypt failed with status %d");
skey[ECDSA_SKEY_LEN - 1] = 0;
int num_shares = strlen(s_shares) / 192;
for (int i = 0; i < num_shares; i++) {
SAFE_CHAR_BUF(encr_sshare, 65);
strncpy(encr_sshare, s_shares + 192 * i, 64);
encr_sshare[64] = 0;
SAFE_CHAR_BUF(s_share, 193);
strncpy(s_share, s_shares + 192 * i, 192);
s_share[192] = 0;
SAFE_CHAR_BUF(common_key, 65);
status = session_key_recover(skey, s_share, common_key);
CHECK_STATUS("session_key_recover failed");
common_key[64] = 0;
SAFE_CHAR_BUF(derived_key, BUF_LEN);
status = hash_key(common_key, derived_key);
CHECK_STATUS("hash key failed")
derived_key[ECDSA_BIN_LEN - 1] = 0;
SAFE_CHAR_BUF(decr_sshare, 65);
status = xor_decrypt_v2(derived_key, encr_sshare, decr_sshare);
CHECK_STATUS("xor_decrypt failed");
decr_sshare[64] = 0;
mpz_t decr_secret_share;
mpz_init(decr_secret_share);
if (mpz_set_str(decr_secret_share, decr_sshare, 16) == -1) {
*errStatus = 111;
snprintf(errString, BUF_LEN, "invalid decrypted secret share");
LOG_ERROR(errString);
mpz_clear(decr_secret_share);
goto clean;
}
mpz_addmul_ui(sum, decr_secret_share, 1);
mpz_clear(decr_secret_share);
}
mpz_mod(bls_key, sum, q);
SAFE_CHAR_BUF(key_share, BLS_KEY_LENGTH);
SAFE_CHAR_BUF(arr_skey_str, BUF_LEN);
mpz_get_str(arr_skey_str, 16, bls_key);
int n_zeroes = 64 - strlen(arr_skey_str);
for (int i = 0; i < n_zeroes; i++) {
key_share[i] = '0';
}
strncpy(key_share + n_zeroes, arr_skey_str, 65 - n_zeroes);
key_share[BLS_KEY_LENGTH - 1] = 0;
status = AES_encrypt(key_share, encr_bls_key, BUF_LEN, BLS, NON_EXPORTABLE, enc_bls_key_len);
CHECK_STATUS2("aes encrypt bls private key failed with status %d ");
SET_SUCCESS
clean:
mpz_clear(bls_key);
mpz_clear(sum);
mpz_clear(q);
LOG_INFO(__FUNCTION__ );
LOG_INFO("SGX call completed");
}
void
trustedGetBlsPubKey(int *errStatus, char *errString, uint8_t *encryptedPrivateKey, uint64_t key_len,
char *bls_pub_key) {
......
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>2</ISVSVN>
<ISVSVN>3</ISVSVN>
<StackMaxSize>0x1000000</StackMaxSize>
<HeapMaxSize>0x10000000</HeapMaxSize>
<TCSNum>256</TCSNum>
......
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>2</ISVSVN>
<ISVSVN>3</ISVSVN>
<StackMaxSize>0x1000000</StackMaxSize>
<HeapMaxSize>0x10000000</HeapMaxSize>
<TCSNum>256</TCSNum>
......
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>2</ISVSVN>
<ISVSVN>3</ISVSVN>
<StackMaxSize>0x200000</StackMaxSize>
<HeapMaxSize>0x200000</HeapMaxSize>
<TCSNum>20</TCSNum>
......
......@@ -156,6 +156,15 @@ enclave {
[out, count = SMALL_BUF_SIZE] uint8_t * encr_bls_key,
[out] uint64_t *enc_bls_key_len);
public void trustedCreateBlsKeyV2(
[out]int *errStatus,
[out, count = SMALL_BUF_SIZE] char* err_string,
[in, count = 6145] const char* s_shares,
[in, count = SMALL_BUF_SIZE] uint8_t* encrypted_key,
uint64_t key_len,
[out, count = SMALL_BUF_SIZE] uint8_t * encr_bls_key,
[out] uint64_t *enc_bls_key_len);
public void trustedBlsSignMessage (
[out] int *errStatus,
[out, count = TINY_BUF_SIZE] char* err_string,
......
/*
Copyright (C) 2019-Present SKALE Labs
This file is part of sgxwallet.
sgxwallet is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
sgxwallet is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with sgxwallet. If not, see <https://www.gnu.org/licenses/>.
@file sgx_util.cpp
@author Stan Kladko
@date 2019
*/
#include <iostream>
#include <cstring>
#include <jsonrpccpp/client/connectors/httpclient.h>
#include "stubclient.h"
#include "common.h"
#include <unistd.h>
int print_hashes(){
jsonrpc::HttpClient client("http://localhost:1028");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Client inited" << std::endl;
std::cout << c.getUnsignedCSRs() << std::endl;
exit(0);
}
void sign_by_hash(std::string & hash, int status){
jsonrpc::HttpClient client("http://localhost:1028");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Client inited" << std::endl;
std::cout << c.signByHash(hash, status) << std::endl;
exit(0);
}
void getNumberOfKeysCreated() {
jsonrpc::HttpClient client("http://localhost:1030");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Info client inited" << std::endl;
std::cout << c.getAllKeysInfo()["keysNumber"].asString() << std::endl;
exit(0);
}
void getAllKeysInfo() {
jsonrpc::HttpClient client("http://localhost:1030");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Info client inited" << std::endl;
std::cout << c.getAllKeysInfo()["allKeys"].asString() << std::endl;
std::cout << "TOTAL KEYS IN DATABASE: " << c.getAllKeysInfo()["keysNumber"].asString() << std::endl;
exit(0);
}
void getLatestCreatedKey() {
jsonrpc::HttpClient client("http://localhost:1030");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Info client inited" << std::endl;
Json::Value lastCreatedKey = c.getLatestCreatedKey();
std::cout << "Last created key name: " << lastCreatedKey["keyName"] << std::endl;
std::string timestamp_to_date_command = "date -d @" + lastCreatedKey["creationTime"].asString();
std::cout << "Last created key creation time: " << exec(timestamp_to_date_command.c_str());
exit(0);
}
void getServerConfiguration() {
jsonrpc::HttpClient client("http://localhost:1030");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Info client inited" << std::endl;
Json::Value response = c.getServerConfiguration();
std::cout << "OPTION autoConfirm certificates switched to " << response["autoConfirm"] << '\n';
uint32_t logLevel = response["logLevel"].asInt();
std::string logLevelStr;
switch(logLevel) {
case 0:
logLevelStr = "trace";
break;
case 1:
logLevelStr = "debug";
break;
case 2:
logLevelStr = "info";
break;
case 3:
logLevelStr = "warning";
break;
case 4:
logLevelStr = "error";
break;
}
std::cout << "OPTION logLevel switched to " << logLevelStr << '\n';
std::cout << "OPTION enterBackupKey switched to " << response["enterBackupKey"] << '\n';
std::cout << "OPTION useHTTPS switched to " << response["useHTTPS"] << '\n';
std::cout << "OPTION autoSign certificates switched to " << response["autoSign"] << '\n';
std::cout << "OPTION checkCerts switched to " << response["checkCerts"] << '\n';
std::cout << "OPTION generateTestKeys switched to " << response["generateTestKeys"] << '\n';
exit(0);
}
void isKeyExists(const std::string& key) {
jsonrpc::HttpClient client("http://localhost:1030");
StubClient c(client, jsonrpc::JSONRPC_CLIENT_V2);
std::cout << "Info client inited" << std::endl;
if (c.isKeyExist(key)["IsExist"].asBool()) {
std::cout << "Key with name " << key << " presents in server database.\n";
} else {
std::cout << "Key with name " << key << " does not exist in server's database.\n";
}
exit(0);
}
int main(int argc, char *argv[]) {
int opt;
if (argc > 1 && strlen(argv[1]) == 1) {
fprintf(stderr, "option is too short %s\n", argv[1]);
exit(1);
}
if (argc == 1) {
std::cout << "You may use following flags:" << std::endl;
std::cout << " -p print all unsigned csr hashes " << std::endl;
std::cout << " -s [hash] sign csr by hash" << std::endl;
std::cout << " -r [hash] reject csr by hash" << std::endl;
std::cout << " -a print all keys" << std::endl;
std::cout << " -l print latest created key" << std::endl;
std::cout << " -n print number of keys stored in database" << std::endl;
std::cout << " -c print server's config" << std::endl;
std::cout << " -i [name] check if key with such name presents in database" << std::endl;
exit(0);
}
std::string hash;
std::string key;
while ((opt = getopt(argc, argv, "ps:r:alci:n")) != -1) {
switch (opt) {
case 'p': print_hashes();
break;
case 's': hash = optarg;
sign_by_hash(hash, 0);
break;
case 'r': hash = optarg;
sign_by_hash(hash, 2);
break;
case 'a':
getAllKeysInfo();
break;
case 'l':
getLatestCreatedKey();
break;
case 'c':
getServerConfiguration();
break;
case 'i': key = optarg;
isKeyExists(key);
break;
case 'n':
getNumberOfKeysCreated();
break;
case '?': // fprintf(stderr, "unknown flag\n");
exit(1);
}
}
return 0;
}
......@@ -34,13 +34,16 @@
#include "TestUtils.h"
#include "ZMQServer.h"
#include "testw.h"
#include "sgxwall.h"
#include "sgxwallet.h"
void SGXWallet::usage() {
cerr << "usage: sgxwallet\n";
exit(1);
exit(-21);
}
void SGXWallet::printUsage() {
......@@ -100,14 +103,14 @@ int main(int argc, char *argv[]) {
if (argc > 1 && strlen(argv[1]) == 1) {
SGXWallet::printUsage();
exit(1);
exit(-22);
}
while ((opt = getopt(argc, argv, "cshd0abyvVnT")) != -1) {
switch (opt) {
case 'h':
SGXWallet::printUsage();
exit(0);
exit(-24);
case 'c':
checkClientCertOption = false;
break;
......@@ -144,7 +147,7 @@ int main(int argc, char *argv[]) {
break;
default:
SGXWallet::printUsage();
exit(1);
exit(-23);
break;
}
}
......@@ -171,7 +174,7 @@ int main(int argc, char *argv[]) {
enclaveLogLevel = L_TRACE;
}
initAll(enclaveLogLevel, checkClientCertOption, autoSignClientCertOption);
initAll(enclaveLogLevel, checkClientCertOption, autoSignClientCertOption, generateTestKeys);
ifstream is("sgx_data/4node.json");
......@@ -201,6 +204,8 @@ int main(int argc, char *argv[]) {
cerr << "Successfully completed generating test keys into sgx_data" << endl;
}
while (true) {
sleep(10);
}
......
......@@ -67,35 +67,98 @@ extern bool autoconfirm;
#define ECDSA_ENCR_LEN 93
#define ECDSA_BIN_LEN 33
#define UNKNOWN_ERROR -1
#define PLAINTEXT_KEY_TOO_LONG -2
#define UNPADDED_KEY -3
#define NULL_KEY -4
#define INCORRECT_STRING_CONVERSION -5
#define ENCRYPTED_KEY_TOO_LONG -6
#define SEAL_KEY_FAILED -7
#define KEY_SHARE_DOES_NOT_EXIST -7
#define KEY_SHARE_ALREADY_EXISTS -8
#define COULD_NOT_ACCESS_DATABASE -9
#define NULL_DATABASE -10
#define INVALID_POLY_NAME -11
#define INVALID_DKG_PARAMS -12
#define BLS_SIGN_INVALID_KS_NAME -11
#define BLS_SIGN_INVALID_PARAMS -12
#define INVALID_SECRET_SHARES_LENGTH -13
#define INVALID_BLS_NAME -15
#define CERT_REQUEST_DOES_NOT_EXIST -14
#define BLS_IMPORT_INVALID_KEY_NAME -15
#define SEAL_KEY_FAILED -16
#define GET_VV_INVALID_POLY_HEX -17
#define GET_SS_INVALID_HEX -18
#define DECRYPT_DH_KEY_INVALID_KEY_HEX -19
#define INVALID_ECDSA_KEY_NAME -20
#define INVALID_HEX -21
#define VERIFY_SHARES_INVALID_KEY_HEX -21
#define INVALID_ECSDA_SIGNATURE -22
#define KEY_NAME_ALREADY_EXISTS -23 \
#define KEY_NAME_ALREADY_EXISTS -23
#define BLS_IMPORT_EMPTY_ENCRYPTED_KEY_SHARE -24
#define BLS_IMPORT_INVALID_KEY_SHARE -25
#define INVALID_BLS_HEX -26
#define INVALID_ECDSA_HEX -27
#define COULD_NOT_BLS_SIGN -28
#define INVALID_ECDSA_IMPORT_KEY_NAME -29
#define INVALID_ECDSA_IMPORT_HEX -30
#define ECDSA_GEN_EMPTY_KEY -31
#define INVALID_ECDSA_SIGN_KEY_NAME -32
#define ERROR_IN_ENCLAVE -33
#define INVALID_ECDSA_SIGN_HASH -34
#define INVALID_ECDSA_SIGN_BASE -35
#define INVALID_ECSDA_SIGN_SIGNATURE -36
#define INVALID_ECDSA_GETPKEY_KEY_NAME -37
#define INVALID_GEN_DKG_POLY_NAME -38
#define INVALID_GEN_DKG_PARAM_T -39
#define INVALID_VERIFY_DKG_PARAM_T -40
#define INVALID_DKG_GETVV_POLY_NAME -41
#define INVALID_DKG_GETVV_PARAMS -42
#define INVALID_DKG_GETSS_POLY_NAME -43
#define FILE_NOT_FOUND -44
#define INVALID_DKG_GETSS_PARAMS -45
#define INVALID_DKG_GETSS_PUB_KEY_COUNT -46
#define INVALID_DKG_GETSS_KEY_HEX -47
#define INVALID_DKG_VERIFY_ECDSA_KEY_NAME -48
#define INVALID_DKG_VERIFY_PARAMS -49
#define INVALID_DKG_VERIFY_SS_HEX -50
#define INVALID_DKG_VERIFY_PUBSHARES_LENGTH -51
#define INVALID_CREATE_BLS_KEY_SECRET_SHARES_LENGTH -52
#define INVALID_CREATE_BLS_ECDSA_KEY_NAME -53
#define INVALID_CREATE_BLS_POLY_NAME -54
#define FAIL_TO_CREATE_CERTIFICATE -55
#define INVALID_CREATE_BLS_KEY_NAME -56
#define INVALID_CREATE_BLS_DKG_PARAMS -57
#define INVALID_CREATE_BLS_SHARE -58
#define INVALID_GET_BLS_PUBKEY_NAME -59
#define INVALID_DKG_CALCULATE_ALL_PARAMS -60
#define INVALID_DKG_CALCULATE_ALL_PUBSHARES -61
#define INVALID_DKG_CALCULATE_ALL_PUBSHARES_SIZE -62
#define INVALID_DKG_CALCULATE_ALL_PUBSHARES_STRING -63
#define INVALID_DKG_CALCULATE_ALL_STRING_PUBSHARES_SLENGTH -64
#define INVALID_DKG_CALCULATE_ALL_STRING_PUBKEYS_SIZE -65
#define INVALID_COMPLAINT_RESPONSE_POLY_NAME -66
#define INVALID_DKG_GETSS_V2_PARAMS -63
#define INVALID_DKG_GETSS_V2_POLY_NAME -64
#define INVALID_DKG_GETSS_V2_PUBKEY_COUNT -65
#define INVALID_DKG_GETSS_V2_PUBKEY_HEX -66
#define INVALID_DKG_VV_V2_ECDSA_KEY_NAME -67
#define INVALID_DKG_VV_V2_PARAMS -68
#define INVALID_DKG_VV_V2_SS_HEX -69
#define INVALID_DKG_VV_V2_SS_COUNT -70
#define EXCEPTION_IN_CONVERT_HEX_TO_DEC -71
#define GET_SS_V2_INVALID_HEX -72
#define EXCEPTION_IN_CONVERT_G2_STRING -73
#define CONVERT_G2_INCORRECT_STRING_CONVERSION -74
#define DELETE_BLS_KEY_INVALID_KEYNAME -75
#define DELETE_BLS_KEY_NOT_FOUND -76
#define VERIFY_SHARES_INVALID_PUBLIC_SHARES -77
#define VERIFY_SHARES_V2_INVALID_POLY_HEX -78
#define VERIFY_SHARES_V2_INVALID_PUBLIC_SHARES -79
#define CREATE_BLS_SHARE_INVALID_KEY_HEX -80
#define GET_BLS_PUBKEY_INVALID_KEY_HEX -81
#define GENERATE_DKG_POLY_INVALID_PARAMS -82
#define SIGN_FUNCTION_INVALID_HEX -83
#define SIGN_AES_INVALID_HASH -84
#define GET_ECDSA_PUB_KEY_INVALID_KEY_HEX -85
#define ECDSA_SIGN_INVALID_KEY_HEX -86
#define SET_SEK_INVALID_SEK_HEX -87
#define TEST_INVALID_HEX -88
#define SGX_ENCLAVE_ERROR -666
......@@ -110,32 +173,5 @@ extern bool autoconfirm;
#define TEST_VALUE "1234567890"
#define RESTART_BEGIN \
int __ATTEMPTS__ = 0; \
do {\
__ATTEMPTS__++; \
{\
READ_LOCK(sgxInitMutex);
#define RESTART_END \
} \
if (status != SGX_SUCCESS || errStatus == 3) { \
spdlog::error(__FUNCTION__); \
spdlog::error("Exiting sgx on status errStatus... {} {}", status, errStatus); \
safeExit(); \
} \
} while ((status != SGX_SUCCESS || errStatus == 3) && __ATTEMPTS__ < 2);
#define RESTART_END_POINTER \
} \
if (status != SGX_SUCCESS || *errStatus == 3) { \
spdlog::error(__FUNCTION__);\
spdlog::error("Restarting sgx on status errStatus... {} {}", status, *errStatus); \
safeExit(); \
} \
} while ((status != SGX_SUCCESS || *errStatus == 3) && __ATTEMPTS__ < 2);
#endif //SGXWALLET_SGXWALLET_COMMON_H
......@@ -187,6 +187,22 @@ class StubClient : public jsonrpc::Client
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value createBLSPrivateKeyV2(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string& SecretShare, int t, int n)
{
Json::Value p;
p["blsKeyName"] = blsKeyName;
p["ethKeyName"] = ethKeyName;
p["polyName"] = polyName;
p["secretShare"] = SecretShare;
p["n"] = n;
p["t"] = t;
Json::Value result = this->CallMethod("createBLSPrivateKeyV2",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value getBLSPublicKeyShare(const std::string & blsKeyName)
{
Json::Value p;
......@@ -263,55 +279,99 @@ class StubClient : public jsonrpc::Client
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value getServerStatus()
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getServerStatus",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value getServerVersion() {
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getServerVersion",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
////CSRManagerServer
Json::Value getUnsignedCSRs()
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getUnsignedCSRs",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value signByHash(const std::string& hash, int status)
{
Json::Value p;
p["hash"] = hash;
p["status"] = status;
Json::Value result = this->CallMethod("signByHash",p);
if (result.isObject())
Json::Value getUnsignedCSRs()
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getUnsignedCSRs",p);
if (result.isObject())
return result;
else
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
}
Json::Value signByHash(const std::string& hash, int status)
{
Json::Value p;
p["hash"] = hash;
p["status"] = status;
Json::Value result = this->CallMethod("signByHash",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value getServerStatus()
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getServerStatus",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
/// InfoServer
Json::Value getServerVersion() {
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getServerVersion",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value getAllKeysInfo()
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getAllKeysInfo", p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value getLatestCreatedKey()
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getLatestCreatedKey", p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value getServerConfiguration()
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("getServerConfiguration", p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value isKeyExist(const std::string& key)
{
Json::Value p;
p["keyName"] = key;
Json::Value result = this->CallMethod("isKeyExist", p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
};
......
......@@ -72,7 +72,7 @@ public:
TestFixture() {
TestUtils::resetDB();
setOptions(L_INFO, false, true);
initAll(L_INFO, false, true);
initAll(L_INFO, false, true, false);
}
~TestFixture() {
......@@ -85,10 +85,11 @@ public:
TestFixtureHTTPS() {
TestUtils::resetDB();
setOptions(L_INFO, true, true);
initAll(L_INFO, false, true);
initAll(L_INFO, false, true, false);
}
~TestFixtureHTTPS() {
exitZMQServer();
TestUtils::destroyEnclave();
}
};
......@@ -97,10 +98,11 @@ class TestFixtureNoResetFromBackup {
public:
TestFixtureNoResetFromBackup() {
setFullOptions(L_INFO, false, true, true);
initAll(L_INFO, false, true);
initAll(L_INFO, false, true, false);
}
~TestFixtureNoResetFromBackup() {
exitZMQServer();
TestUtils::destroyEnclave();
}
};
......@@ -110,10 +112,11 @@ class TestFixtureNoReset {
public:
TestFixtureNoReset() {
setOptions(L_INFO, false, true);
initAll(L_INFO, false, true);
initAll(L_INFO, false, true, false);
}
~TestFixtureNoReset() {
exitZMQServer();
TestUtils::destroyEnclave();
}
};
......@@ -825,7 +828,7 @@ TEST_CASE_METHOD(TestFixture, "AES_DKG test", "[aes-dkg]") {
uint64_t binLen;
if (!hex2carray(hash.c_str(), &binLen, hash_arr->data(), 32)) {
throw SGXException(INVALID_HEX, "Invalid hash");
throw SGXException(TEST_INVALID_HEX, "Invalid hash");
}
map <size_t, shared_ptr<BLSPublicKeyShare>> coeffs_pkeys_map;
......@@ -943,7 +946,11 @@ TEST_CASE_METHOD(TestFixture, "AES_DKG V2 test", "[aes-dkg-v2]") {
SAFE_CHAR_BUF(common_key, BUF_LEN);
REQUIRE(sessionKeyRecoverDH(dhKey.c_str(), encr_sshare, common_key) == 0);
auto hashed_key = cryptlite::sha256::hash_hex(string(common_key, 64));
uint8_t key_to_hash[33];
uint64_t len;
REQUIRE( hex2carray(common_key, &len, key_to_hash, 64) );
auto hashed_key = cryptlite::sha256::hash_hex(string((char*)key_to_hash, 32));
SAFE_CHAR_BUF(derived_key, 33)
......@@ -991,7 +998,7 @@ TEST_CASE_METHOD(TestFixture, "AES_DKG V2 test", "[aes-dkg-v2]") {
uint64_t binLen;
if (!hex2carray(hash.c_str(), &binLen, hash_arr->data(), 32)) {
throw SGXException(INVALID_HEX, "Invalid hash");
throw SGXException(TEST_INVALID_HEX, "Invalid hash");
}
map <size_t, shared_ptr<BLSPublicKeyShare>> coeffs_pkeys_map;
......@@ -999,7 +1006,7 @@ TEST_CASE_METHOD(TestFixture, "AES_DKG V2 test", "[aes-dkg-v2]") {
for (int i = 0; i < t; i++) {
string endName = polyNames[i].substr(4);
string blsName = "BLS_KEY" + polyNames[i].substr(4);
auto response = c.createBLSPrivateKey(blsName, ethKeys[i]["keyName"].asString(), polyNames[i], secShares[i], t,
auto response = c.createBLSPrivateKeyV2(blsName, ethKeys[i]["keyName"].asString(), polyNames[i], secShares[i], t,
n);
REQUIRE(response["status"] == 0);
......@@ -1071,7 +1078,7 @@ TEST_CASE_METHOD(TestFixture, "Many threads ecdsa dkg v2 bls", "[many-threads-cr
vector <thread> threads;
int num_threads = 4;
for (int i = 0; i < num_threads; i++) {
threads.push_back(thread(TestUtils::sendRPCRequest));
threads.push_back(thread(TestUtils::sendRPCRequestV2));
}
for (auto &thread : threads) {
......
Copyright (c) 2010-2013 iMatix Corporation and Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
#ifndef __ZHELPERS_HPP_INCLUDED__
#define __ZHELPERS_HPP_INCLUDED__
// Include a bunch of headers that we will need in the examples
#include <zmq.hpp> // https://github.com/zeromq/cppzmq
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <time.h>
#include <assert.h>
#include <stdlib.h> // random() RAND_MAX
#include <stdio.h>
#include <stdarg.h>
#include <signal.h>
#if (!defined(WIN32))
# include <sys/time.h>
# include <unistd.h>
#endif
// Bring Windows MSVC up to C99 scratch
#if (defined (WIN32))
typedef unsigned long ulong;
typedef unsigned int uint;
typedef __int64 int64_t;
#endif
// On some version of Windows, POSIX subsystem is not installed by default.
// So define srandom and random ourself.
//
#if (defined (WIN32))
# define srandom srand
# define random rand
#endif
// Visual Studio versions below 2015 do not support sprintf properly. This is a workaround.
// Taken from http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf c99_snprintf
#define vsnprintf c99_vsnprintf
inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = c99_vsnprintf(outBuf, size, format, ap);
va_end(ap);
return count;
}
#endif
// Provide random number from 0..(num-1)
#define within(num) (int) ((float)((num) * random ()) / (RAND_MAX + 1.0))
// Receive 0MQ string from socket and convert into C string
// Caller must free returned string.
inline static char *
s_recv(void *socket, int flags = 0) {
zmq_msg_t message;
zmq_msg_init(&message);
int rc = zmq_msg_recv(&message, socket, flags);
if (rc < 0)
return nullptr; // Context terminated, exit
size_t size = zmq_msg_size(&message);
char *string = (char*)malloc(size + 1);
memcpy(string, zmq_msg_data(&message), size);
zmq_msg_close(&message);
string[size] = 0;
return (string);
}
// Receive 0MQ string from socket and convert into string
inline static std::string
s_recv (zmq::socket_t & socket, int flags = 0) {
zmq::message_t message;
socket.recv(&message, flags);
return std::string(static_cast<char*>(message.data()), message.size());
}
inline static bool s_recv(zmq::socket_t & socket, std::string & ostring, int flags = 0)
{
zmq::message_t message;
bool rc = socket.recv(&message, flags);
if (rc) {
ostring = std::string(static_cast<char*>(message.data()), message.size());
}
return (rc);
}
// Convert C string to 0MQ string and send to socket
inline static int
s_send(void *socket, const char *string, int flags = 0) {
int rc;
zmq_msg_t message;
zmq_msg_init_size(&message, strlen(string));
memcpy(zmq_msg_data(&message), string, strlen(string));
rc = zmq_msg_send(&message, socket, flags);
assert(-1 != rc);
zmq_msg_close(&message);
return (rc);
}
// Convert string to 0MQ string and send to socket
inline static bool
s_send (zmq::socket_t & socket, const std::string & string, int flags = 0) {
zmq::message_t message(string.size());
memcpy (message.data(), string.data(), string.size());
bool rc = socket.send (message, flags);
return (rc);
}
// Sends string as 0MQ string, as multipart non-terminal
inline static int
s_sendmore(void *socket, char *string) {
int rc;
zmq_msg_t message;
zmq_msg_init_size(&message, strlen(string));
memcpy(zmq_msg_data(&message), string, strlen(string));
//rc = zmq_send(socket, string, strlen(string), ZMQ_SNDMORE);
rc = zmq_msg_send(&message, socket, ZMQ_SNDMORE);
assert(-1 != rc);
zmq_msg_close(&message);
return (rc);
}
// Sends string as 0MQ string, as multipart non-terminal
inline static bool
s_sendmore (zmq::socket_t & socket, const std::string & string) {
zmq::message_t message(string.size());
memcpy (message.data(), string.data(), string.size());
bool rc = socket.send (message, ZMQ_SNDMORE);
return (rc);
}
// Receives all message parts from socket, prints neatly
//
inline static void
s_dump (zmq::socket_t & socket)
{
std::cout << "----------------------------------------" << std::endl;
while (1) {
// Process all parts of the message
zmq::message_t message;
socket.recv(&message);
// Dump the message as text or binary
size_t size = message.size();
std::string data(static_cast<char*>(message.data()), size);
bool is_text = true;
size_t char_nbr;
unsigned char byte;
for (char_nbr = 0; char_nbr < size; char_nbr++) {
byte = data [char_nbr];
if (byte < 32 || byte > 127)
is_text = false;
}
std::cout << "[" << std::setfill('0') << std::setw(3) << size << "]";
for (char_nbr = 0; char_nbr < size; char_nbr++) {
if (is_text)
std::cout << (char)data [char_nbr];
else
std::cout << std::setfill('0') << std::setw(2)
<< std::hex << (unsigned int) data [char_nbr];
}
std::cout << std::endl;
int more = 0; // Multipart detection
size_t more_size = sizeof (more);
socket.getsockopt (ZMQ_RCVMORE, &more, &more_size);
if (!more)
break; // Last message part
}
}
#if (!defined (WIN32))
// Set simple random printable identity on socket
// Caution:
// DO NOT call this version of s_set_id from multiple threads on MS Windows
// since s_set_id will call rand() on MS Windows. rand(), however, is not
// reentrant or thread-safe. See issue #521.
inline std::string
s_set_id (zmq::socket_t & socket)
{
std::stringstream ss;
ss << std::hex << std::uppercase
<< std::setw(4) << std::setfill('0') << within (0x10000) << "-"
<< std::setw(4) << std::setfill('0') << within (0x10000);
socket.setsockopt(ZMQ_IDENTITY, ss.str().c_str(), ss.str().length());
return ss.str();
}
#else
// Fix #521
inline std::string
s_set_id(zmq::socket_t & socket, intptr_t id)
{
std::stringstream ss;
ss << std::hex << std::uppercase
<< std::setw(4) << std::setfill('0') << id;
socket.setsockopt(ZMQ_IDENTITY, ss.str().c_str(), ss.str().length());
return ss.str();
}
#endif
// Report 0MQ version number
//
inline static void
s_version (void)
{
int major, minor, patch;
zmq_version (&major, &minor, &patch);
std::cout << "Current 0MQ version is " << major << "." << minor << "." << patch << std::endl;
}
inline static void
s_version_assert (int want_major, int want_minor)
{
int major, minor, patch;
zmq_version (&major, &minor, &patch);
if (major < want_major
|| (major == want_major && minor < want_minor)) {
std::cout << "Current 0MQ version is " << major << "." << minor << std::endl;
std::cout << "Application needs at least " << want_major << "." << want_minor
<< " - cannot continue" << std::endl;
exit (EXIT_FAILURE);
}
}
// Return current system clock as milliseconds
inline static int64_t
s_clock (void)
{
#if (defined (WIN32))
FILETIME fileTime;
GetSystemTimeAsFileTime(&fileTime);
unsigned __int64 largeInt = fileTime.dwHighDateTime;
largeInt <<= 32;
largeInt |= fileTime.dwLowDateTime;
largeInt /= 10000; // FILETIME is in units of 100 nanoseconds
return (int64_t)largeInt;
#else
struct timeval tv;
gettimeofday (&tv, NULL);
return (int64_t) (tv.tv_sec * 1000 + tv.tv_usec / 1000);
#endif
}
// Sleep for a number of milliseconds
inline static void
s_sleep (int msecs)
{
#if (defined (WIN32))
Sleep (msecs);
#else
struct timespec t;
t.tv_sec = msecs / 1000;
t.tv_nsec = (msecs % 1000) * 1000000;
nanosleep (&t, NULL);
#endif
}
inline static void
s_console (const char *format, ...)
{
time_t curtime = time (NULL);
struct tm *loctime = localtime (&curtime);
char *formatted = new char[20];
strftime (formatted, 20, "%y-%m-%d %H:%M:%S ", loctime);
printf ("%s", formatted);
delete[] formatted;
va_list argptr;
va_start (argptr, format);
vprintf (format, argptr);
va_end (argptr);
printf ("\n");
}
// ---------------------------------------------------------------------
// Signal handling
//
// Call s_catch_signals() in your application at startup, and then exit
// your main loop if s_interrupted is ever 1. Works especially well with
// zmq_poll.
static int s_interrupted = 0;
inline static void s_signal_handler (int signal_value)
{
s_interrupted = 1;
}
inline static void s_catch_signals ()
{
#if (!defined(WIN32))
struct sigaction action;
action.sa_handler = s_signal_handler;
action.sa_flags = 0;
sigemptyset (&action.sa_mask);
sigaction (SIGINT, &action, NULL);
sigaction (SIGTERM, &action, NULL);
#endif
}
#endif
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment