/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "util.h" #include #include #include #include #include #include #if defined(__unix__) || defined(__APPLE__) #include #include #elif defined(WIN32) || defined(_WIN64) #include #endif static std::string GetPassword(const std::string &prompt) { std::cout << prompt << std::endl; #if defined(__unix__) || defined(__APPLE__) termios oldt; tcgetattr(STDIN_FILENO, &oldt); termios newt = oldt; newt.c_lflag &= ~ECHO; tcsetattr(STDIN_FILENO, TCSANOW, &newt); #elif defined(WIN32) || defined(_WIN64) HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; GetConsoleMode(hStdin, &mode); SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT)); #endif std::string pw; std::getline(std::cin, pw); #if defined(__unix__) || defined(__APPLE__) tcsetattr(STDIN_FILENO, TCSANOW, &oldt); #elif defined(WIN32) || defined(_WIN64) SetConsoleMode(hStdin, mode); #endif return pw; } static char *GetModulePassword(PK11SlotInfo *slot, int retry, void *arg) { if (arg == nullptr) { return nullptr; } PwData *pwData = reinterpret_cast(arg); if (retry > 0) { std::cerr << "Incorrect password/PIN entered." << std::endl; return nullptr; } switch (pwData->source) { case PW_NONE: case PW_FROMFILE: std::cerr << "Password input method not supported." << std::endl; return nullptr; case PW_PLAINTEXT: return PL_strdup(pwData->data); default: break; } std::cerr << "Password check failed: No password found." << std::endl; return nullptr; } static std::vector ReadFromIstream(std::istream &is) { std::vector data; while (is) { char buf[1024]; is.read(buf, sizeof(buf)); data.insert(data.end(), buf, buf + is.gcount()); } return data; } static std::string GetNewPasswordFromUser(void) { std::string pw; while (true) { pw = GetPassword("Enter new password: "); if (pw == GetPassword("Re-enter password: ")) { break; } std::cerr << "Passwords do not match. Try again." << std::endl; } return pw; } bool InitSlotPassword(void) { ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); if (slot.get() == nullptr) { std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl; return false; } std::cout << "Enter a password which will be used to encrypt your keys." << std::endl << std::endl; std::string pw = GetNewPasswordFromUser(); SECStatus rv = PK11_InitPin(slot.get(), nullptr, pw.c_str()); if (rv != SECSuccess) { std::cerr << "Init db password failed." << std::endl; return false; } return true; } bool ChangeSlotPassword(void) { ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); if (slot.get() == nullptr) { std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl; return false; } // get old password and authenticate to db PK11_SetPasswordFunc(&GetModulePassword); std::string oldPw = GetPassword("Enter your current password: "); PwData pwData = {PW_PLAINTEXT, const_cast(oldPw.c_str())}; SECStatus rv = PK11_Authenticate(slot.get(), false /*loadCerts*/, &pwData); if (rv != SECSuccess) { std::cerr << "Password incorrect." << std::endl; return false; } // get new password std::string newPw = GetNewPasswordFromUser(); if (PK11_ChangePW(slot.get(), oldPw.c_str(), newPw.c_str()) != SECSuccess) { std::cerr << "Failed to change password." << std::endl; return false; } std::cout << "Password changed successfully." << std::endl; return true; } bool DBLoginIfNeeded(const ScopedPK11SlotInfo &slot) { if (!PK11_NeedLogin(slot.get())) { return true; } PK11_SetPasswordFunc(&GetModulePassword); std::string pw = GetPassword("Enter your password: "); PwData pwData = {PW_PLAINTEXT, const_cast(pw.c_str())}; SECStatus rv = PK11_Authenticate(slot.get(), true /*loadCerts*/, &pwData); if (rv != SECSuccess) { std::cerr << "Could not authenticate to token " << PK11_GetTokenName(slot.get()) << ". Failed with error " << PR_ErrorToName(PR_GetError()) << std::endl; return false; } std::cout << std::endl; return true; } std::string StringToHex(const ScopedSECItem &input) { std::stringstream ss; ss << "0x"; for (size_t i = 0; i < input->len; i++) { ss << std::hex << std::setfill('0') << std::setw(2) << static_cast(input->data[i]); } return ss.str(); } std::vector ReadInputData(std::string dataPath) { std::vector data; if (dataPath.empty()) { std::cout << "No input file path given, using stdin." << std::endl; data = ReadFromIstream(std::cin); } else { std::ifstream is(dataPath, std::ifstream::binary); if (is.good()) { data = ReadFromIstream(is); } else { std::cerr << "IO Error when opening " << dataPath << std::endl; std::cerr << "Input file does not exist or you don't have permissions." << std::endl; } } return data; } std::istream &GetStreamFromFileOrStdin(std::string &path, std::ifstream &ifs) { if (path.empty()) { return std::cin; } ifs.open(path, std::ifstream::binary); if (!ifs.good()) { std::cerr << "IO Error when opening " << path << std::endl; std::cerr << "Input file does not exist or you don't have permissions." << std::endl; } return ifs; }