SEKManager.cpp 7.16 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
    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 SEKManager.cpp
    @author Stan Kladko
21
    @date 2020
22 23 24
*/

#include "SEKManager.h"
25
#include "SGXException.h"
26 27 28
#include "BLSCrypto.h"
#include "LevelDB.h"

29
#include <fstream>
30
#include <iostream>
31
#include <algorithm>
32 33

#include "sgxwallet_common.h"
kladko's avatar
kladko committed
34
#include "common.h"
35 36
#include "sgxwallet.h"

37
#include "ServerDataChecker.h"
Oleh Nikolaiev's avatar
Oleh Nikolaiev committed
38
#include "third_party/spdlog/spdlog.h"
39

40 41 42 43 44 45 46
bool case_insensitive_match(string s1, string s2) {
  //convert s1 and s2 into lower case strings
  transform(s1.begin(), s1.end(), s1.begin(), ::tolower);
  transform(s2.begin(), s2.end(), s2.begin(), ::tolower);
  return s1.compare(s2);
}

47
void create_test_key() {
svetaro's avatar
svetaro committed
48 49 50 51 52 53 54 55 56
  int errStatus =  0;
  vector<char> errMsg(1024,0);
  uint32_t enc_len;

  uint8_t encrypted_key[BUF_LEN];
  memset(encrypted_key, 0, BUF_LEN);

  std::string key = TEST_VALUE;

57
  status = trustedEncryptKeyAES(eid, &errStatus, errMsg.data(), key.c_str(), encrypted_key, &enc_len);
58
  if ( status != SGX_SUCCESS ) {
svetaro's avatar
svetaro committed
59
    std::cerr << "encrypt test key failed with status " << status << std::endl;
60
    throw SGXException(status, errMsg.data()) ;
svetaro's avatar
svetaro committed
61 62
  }

63 64 65 66 67
  if ( errStatus != 0 ) {
    std::cerr << "encrypt test key failed with status " << errStatus << std::endl;
    throw SGXException(errStatus, errMsg.data()) ;
  }

svetaro's avatar
svetaro committed
68 69 70 71
  vector<char> hexEncrKey(2 * enc_len + 1, 0);

  carray2Hex(encrypted_key, enc_len, hexEncrKey.data());

svetaro's avatar
svetaro committed
72 73
  uint64_t test_len;
  vector<uint8_t>test_encr_key(1024, 0);
74
  if (!hex2carray(hexEncrKey.data(), &test_len, test_encr_key.data())) {
svetaro's avatar
svetaro committed
75 76
    std::cerr << "wrong encrypted test key" << std::endl;
  }
svetaro's avatar
svetaro committed
77

svetaro's avatar
svetaro committed
78 79 80
  LevelDB::getLevelDb() -> writeDataUnique("TEST_KEY", hexEncrKey.data());
}

81 82
bool check_SEK(const std::string& SEK) {
  std::shared_ptr <std::string> test_key_ptr = LevelDB::getLevelDb() -> readString("TEST_KEY");
83 84
  vector<uint8_t> encr_test_key(BUF_LEN, 0);
  uint64_t len;
85
  if (!hex2carray(test_key_ptr->c_str(), &len, encr_test_key.data())) {
86 87 88 89 90 91 92 93 94 95 96 97 98
    spdlog::error("wrong test key" );
    exit(-1);
  }

  vector<char> decr_key(1024,0);
  vector<char> errMsg(1024,0);
  int err_status = 0;

  vector<uint8_t> encr_SEK(1024,0);

  uint32_t l = len;

  status = trustedSetSEK_backup(eid, &err_status, errMsg.data(), encr_SEK.data(), &l, SEK.c_str() );
99
  if (status != SGX_SUCCESS) {
100 101 102 103
    cerr << "RPCException thrown with status " << status << endl;
    throw SGXException(status, errMsg.data());
  }

104 105 106 107 108
  if ( err_status != 0 ) {
    cerr << "RPCException thrown with status " << err_status << endl;
    throw SGXException(err_status, errMsg.data());
  }

109
  status = trustedDecryptKeyAES(eid, &err_status, errMsg.data(), encr_test_key.data(), len, decr_key.data());
110
  if (status != SGX_SUCCESS || err_status != 0) {
111 112 113 114 115 116
    spdlog::error("failed to decrypt test key" );
    spdlog::error(errMsg.data());
    exit(-1);
  }

  std::string test_key = TEST_VALUE;
117
  if (test_key.compare(decr_key.data()) != 0) {
118 119 120 121 122
    std::cerr << "decrypted key is " << decr_key.data() << std::endl;
    spdlog::error("Invalid SEK" );
    return false;
  }
  return true;
svetaro's avatar
svetaro committed
123 124
}

125
void gen_SEK() {
kladko's avatar
kladko committed
126
  vector<char> errMsg(1024,0);
127
  int err_status = 0;
kladko's avatar
kladko committed
128
  vector<uint8_t> encr_SEK(1024, 0);
129 130
  uint32_t enc_len = 0;

131 132 133
  char SEK[65];
  memset(SEK, 0, 65);

134
  status = trustedGenerateSEK(eid, &err_status, errMsg.data(), encr_SEK.data(), &enc_len, SEK);
135
  if ( status != SGX_SUCCESS ) {
136
    throw SGXException(status, errMsg.data()) ;
137 138
  }

139 140 141 142
  if ( err_status != 0 ) {
    throw SGXException(err_status, errMsg.data()) ;
  }

143
  vector<char> hexEncrKey(2 * enc_len + 1, 0);
144

kladko's avatar
kladko committed
145
  carray2Hex(encr_SEK.data(), enc_len, hexEncrKey.data());
146

147 148 149
  std::ofstream sek_file("backup_key.txt");
  sek_file.clear();

150 151
  cout << "ATTENTION! YOUR BACKUP KEY WILL BE WRITTEN INTO backup_key.txt.\n" <<
          "PLEASE COPY IT TO THE SAFE PLACE AND THEN DELETE THE FILE MANUALLY BY RUNNING THE FOLLOWING COMMAND:\n" <<
152
          "`docker exec -it <SGX_CONTAINER_NAME> bash && apt-get install secure-delete && srm -vz backup_key.txt`" << endl;
153
  sek_file << SEK;
154

svetaro's avatar
svetaro committed
155 156 157 158 159 160 161
  if (!autoconfirm) {
    std::string confirm_str = "I confirm";
    std::string buffer;
    do {
      std::cout << " DO YOU CONFIRM THAT YOU COPIED THE KEY? (if you confirm type - I confirm)"
                << std::endl;
      std::getline(std::cin, buffer);
162
    } while (case_insensitive_match(confirm_str, buffer));
svetaro's avatar
svetaro committed
163
  }
kladko's avatar
kladko committed
164

kladko's avatar
kladko committed
165
  LevelDB::getLevelDb()->writeDataUnique("SEK", hexEncrKey.data());
166

svetaro's avatar
svetaro committed
167
  create_test_key();
168
}
169

170
void trustedSetSEK(std::shared_ptr<std::string> hex_encr_SEK) {
171 172 173
  vector<char> errMsg(1024,0);
  int err_status = 0;

174 175
  uint8_t encr_SEK[BUF_LEN];
  memset(encr_SEK, 0, BUF_LEN);
176 177 178

  uint64_t len;

179
  if (!hex2carray(hex_encr_SEK->c_str(), &len, encr_SEK)) {
180
    throw SGXException(INVALID_HEX, "Invalid encrypted SEK Hex");
181 182
  }

183
  status = trustedSetSEK(eid, &err_status, errMsg.data(), encr_SEK, len );
184
  if ( status != SGX_SUCCESS ) {
185
    cerr << "RPCException thrown" << endl;
186
    throw SGXException(status, errMsg.data()) ;
187
  }
188 189 190 191 192

  if ( err_status != 0 ) {
    cerr << "RPCException thrown" << endl;
    throw SGXException(err_status, errMsg.data()) ;
  }
193
}
194

195
void enter_SEK() {
196 197 198 199 200
  vector<char> errMsg(1024,0);
  int err_status = 0;
  vector<uint8_t> encr_SEK(BUF_LEN, 0);
  uint32_t enc_len;

svetaro's avatar
svetaro committed
201
  std::shared_ptr <std::string> test_key_ptr = LevelDB::getLevelDb() -> readString("TEST_KEY");
202
  if (test_key_ptr == nullptr) {
svetaro's avatar
svetaro committed
203 204 205 206
    spdlog::error("empty db" );
    exit(-1);
  }

207 208 209
  std::string SEK;
  std::cout << "ENTER BACKUP KEY" << std::endl;
  std::cin >> SEK;
210
  while (!checkHex(SEK, 16) || !check_SEK(SEK)) {
211 212 213 214
    std::cout << "KEY IS INVALID.TRY ONCE MORE" << std::endl;
    SEK = "";
    std::cin >> SEK;
  }
svetaro's avatar
svetaro committed
215

216
  status = trustedSetSEK_backup(eid, &err_status, errMsg.data(), encr_SEK.data(), &enc_len, SEK.c_str());
217
  if (status != SGX_SUCCESS) {
218
    cerr << "RPCException thrown with status " << status << endl;
219
    throw SGXException(status, errMsg.data());
220 221
  }

222 223 224 225 226
  if ( err_status != 0 ) {
    cerr << "RPCException thrown" << endl;
    throw SGXException(err_status, errMsg.data()) ;
  }

227 228 229 230 231 232 233 234
  vector<char> hexEncrKey(2 * enc_len + 1, 0);

  carray2Hex(encr_SEK.data(), enc_len, hexEncrKey.data());

  LevelDB::getLevelDb() -> deleteKey("SEK");
  LevelDB::getLevelDb() -> writeDataUnique("SEK", hexEncrKey.data());
}

235
void initSEK() {
236
  std::shared_ptr<std::string> encr_SEK_ptr = LevelDB::getLevelDb()->readString("SEK");
237 238 239 240
  if (encryptKeys) {
    enter_SEK();
  } else {
      if (encr_SEK_ptr == nullptr) {
241
          spdlog::warn("SEK was not created yet. Going to create SEK");
242 243 244 245
          gen_SEK();
      } else {
          trustedSetSEK(encr_SEK_ptr);
      }
246 247
  }
}
svetaro's avatar
svetaro committed
248

249
//a002e7ca685d46a32771d16fe2518e58