/*
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 .
@file ServerInit.cpp
@author Stan Kladko
@date 2019
*/
#include
#include
#include
#include
#include
#include
#include
#include "libff/algebra/curves/alt_bn128/alt_bn128_init.hpp"
#include
#include "bls.h"
#include "leveldb/db.h"
#include
#include "third_party/spdlog/spdlog.h"
#include
#include
#include
#include "ExitHandler.h"
#include "BLSPrivateKeyShareSGX.h"
#include "sgxwallet_common.h"
#include "third_party/intel/create_enclave.h"
#include "secure_enclave_u.h"
#include "third_party/intel/sgx_detect.h"
#include "sgxwallet.h"
#include "LevelDB.h"
#include "SGXRemoteAttestationServer.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 "zmq_src/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");
throw SGXException(EXECUTION_ULIMIT_FAILED, "Execution of '/bin/bash -c ulimit -n' failed.");
}
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);
throw SGXException(WRONG_ULIMIT, errStr);
}
}
void initUserSpace() {
libff::inhibit_profiling_counters = true;
libff::init_alt_bn128_params();
LevelDB::initDataFolderAndDBs();
#ifndef SGX_HW_SIM
systemHealthCheck();
#endif
}
uint64_t initEnclave() {
#ifndef SGX_HW_SIM
unsigned long support;
support = get_sgx_support();
if (!SGX_OK(support)) {
sgx_support_perror(support);
throw SGXException(COULD_NOT_INIT_ENCLAVE, "SGX is not supported or not enabled");
}
#endif
spdlog::info("SGX_DEBUG_FLAG = {}", SGX_DEBUG_FLAG);
sgx_status_t status = SGX_SUCCESS;
{
WRITE_LOCK(sgxInitMutex);
if (eid != 0) {
if (sgx_destroy_enclave(eid) != SGX_SUCCESS) {
spdlog::error("Could not destroy enclave");
}
}
eid = 0;
updated = 0;
status = sgx_create_enclave_search(ENCLAVE_NAME, SGX_DEBUG_FLAG, &token,
&updated, &eid, 0);
if (status != SGX_SUCCESS) {
if (status == SGX_ERROR_ENCLAVE_FILE_ACCESS) {
spdlog::error("sgx_create_enclave: {}: file not found", ENCLAVE_NAME);
spdlog::error("Did you forget to set LD_LIBRARY_PATH?");
} else {
spdlog::error("sgx_create_enclave_search failed {} {}", ENCLAVE_NAME, status);
}
throw SGXException(COULD_NOT_INIT_ENCLAVE, "Error initing enclave. Please re-check your enviroment.");
}
spdlog::info("Enclave created and started successfully");
status = trustedEnclaveInit(eid, enclaveLogLevel);
}
if (status != SGX_SUCCESS) {
spdlog::error("trustedEnclaveInit failed: {}", status);
return status;
}
spdlog::info("Enclave libtgmp library and logging initialized successfully");
return SGX_SUCCESS;
}
void initAll(uint32_t _logLevel, bool _checkCert,
bool _checkZMQSig, bool _autoSign, bool _generateTestKeys, bool _checkKeyOwnership) {
static atomic sgxServerInited(false);
static mutex initMutex;
enclaveLogLevel = _logLevel;
lock_guard lock(initMutex);
if (sgxServerInited)
return;
try {
cout << "Running sgxwallet version:" << SGXWalletServer::getVersion() << endl;
CHECK_STATE(sgxServerInited != 1)
sgxServerInited = 1;
uint64_t counter = 0;
uint64_t initResult = 0;
while ((initResult = initEnclave()) != 0 && counter < 10) {
sleep(1);
counter++;
}
if (initResult != 0) {
spdlog::error("Coult not init enclave");
}
initUserSpace();
initSEK();
SGXWalletServer::createCertsIfNeeded();
if (useHTTPS) {
spdlog::info("Initing JSON-RPC server over HTTPS");
spdlog::info("Check client cert: {}", _checkCert);
SGXWalletServer::initHttpsServer(_checkCert);
spdlog::info("Inited JSON-RPC server over HTTPS");
} else {
spdlog::info("Initing JSON-RPC server over HTTP");
SGXWalletServer::initHttpServer();
spdlog::info("Inited JSON-RPC server over HTTP");
}
SGXRemoteAttestationServer::initRemoteAttestationServer();
SGXRegistrationServer::initRegistrationServer(_autoSign);
CSRManagerServer::initCSRManagerServer();
SGXInfoServer::initInfoServer(_logLevel, _checkCert, _autoSign, _generateTestKeys);
ZMQServer::initZMQServer(_checkZMQSig, _checkKeyOwnership);
sgxServerInited = true;
} catch (SGXException &_e) {
spdlog::error(_e.getMessage());
ExitHandler::exitHandler(SIGTERM, ExitHandler::ec_initing_user_space);
} catch (exception &_e) {
spdlog::error(_e.what());
ExitHandler::exitHandler(SIGTERM, ExitHandler::ec_initing_user_space);
}
catch (...) {
exception_ptr p = current_exception();
printf("Exception %s \n", p.__cxa_exception_type()->name());
spdlog::error("Unknown exception");
ExitHandler::exitHandler(SIGTERM, ExitHandler::ec_initing_user_space);
}
};
void exitAll() {
SGXRemoteAttestationServer::exitServer();
SGXWalletServer::exitServer();
SGXRegistrationServer::exitServer();
CSRManagerServer::exitServer();
SGXInfoServer::exitServer();
ZMQServer::exitZMQServer();
}