Differential D7383 Diff 27204 native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
Changeset View
Changeset View
Standalone View
Standalone View
native/cpp/CommonCpp/Notifications/BackgroundDataStorage/NotificationsCryptoModule.cpp
Show All 13 Lines | |||||
namespace comm { | namespace comm { | ||||
const std::string | const std::string | ||||
NotificationsCryptoModule::secureStoreNotificationsAccountDataKey = | NotificationsCryptoModule::secureStoreNotificationsAccountDataKey = | ||||
"notificationsCryptoAccountDataKey"; | "notificationsCryptoAccountDataKey"; | ||||
const std::string NotificationsCryptoModule::notificationsCryptoAccountID = | const std::string NotificationsCryptoModule::notificationsCryptoAccountID = | ||||
"notificationsCryptoAccountDataID"; | "notificationsCryptoAccountDataID"; | ||||
const std::string NotificationsCryptoModule::keyserverHostedNotificationsID = | |||||
"keyserverHostedNotificationsID"; | |||||
const std::string NotificationsCryptoModule::initialEncryptedMessageContent = | |||||
"{\"type\": \"init\"}"; | |||||
crypto::CryptoModule NotificationsCryptoModule::deserializeCryptoModule( | crypto::CryptoModule NotificationsCryptoModule::deserializeCryptoModule( | ||||
const std::string &path, | const std::string &path, | ||||
const std::string &picklingKey) { | const std::string &picklingKey) { | ||||
std::ifstream pickledPersistStream(path, std::ifstream::in); | std::ifstream pickledPersistStream(path, std::ifstream::in); | ||||
if (!pickledPersistStream.good()) { | if (!pickledPersistStream.good()) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"Attempt to deserialize non-existing notifications crypto account"); | "Attempt to deserialize non-existing notifications crypto account"); | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | if (rename(temporaryPath.c_str(), path.c_str()) == -1) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"Failed to replace temporary file content with notifications crypto " | "Failed to replace temporary file content with notifications crypto " | ||||
"account. Unable to atomically update notifications crypto account. " | "account. Unable to atomically update notifications crypto account. " | ||||
"Details: " + | "Details: " + | ||||
std::string(strerror(errno))); | std::string(strerror(errno))); | ||||
} | } | ||||
} | } | ||||
void NotificationsCryptoModule::callCryptoModule( | |||||
std::function<void(crypto::CryptoModule &cryptoModule)> caller, | |||||
const std::string &callingProcessName) { | |||||
CommSecureStore secureStore{}; | |||||
folly::Optional<std::string> picklingKey = secureStore.get( | |||||
NotificationsCryptoModule::secureStoreNotificationsAccountDataKey); | |||||
if (!picklingKey.hasValue()) { | |||||
throw std::runtime_error( | |||||
"Attempt to retrieve notifications crypto account before it was " | |||||
"correctly initialized."); | |||||
} | |||||
const std::string path = | |||||
PlatformSpecificTools::getNotificationsCryptoAccountPath(); | |||||
crypto::CryptoModule cryptoModule = | |||||
NotificationsCryptoModule::deserializeCryptoModule( | |||||
path, picklingKey.value()); | |||||
caller(cryptoModule); | |||||
NotificationsCryptoModule::serializeAndFlushCryptoModule( | |||||
cryptoModule, path, picklingKey.value(), callingProcessName); | |||||
} | |||||
void NotificationsCryptoModule::initializeNotificationsCryptoAccount( | void NotificationsCryptoModule::initializeNotificationsCryptoAccount( | ||||
const std::string &callingProcessName) { | const std::string &callingProcessName) { | ||||
const std::string notificationsCryptoAccountPath = | const std::string notificationsCryptoAccountPath = | ||||
PlatformSpecificTools::getNotificationsCryptoAccountPath(); | PlatformSpecificTools::getNotificationsCryptoAccountPath(); | ||||
std::ifstream notificationCryptoAccountCheck(notificationsCryptoAccountPath); | std::ifstream notificationCryptoAccountCheck(notificationsCryptoAccountPath); | ||||
if (notificationCryptoAccountCheck.good()) { | if (notificationCryptoAccountCheck.good()) { | ||||
// Implemented in CommmCoreModule semantics regarding public olm account | // Implemented in CommmCoreModule semantics regarding public olm account | ||||
// initialization is idempotent. We should follow the same approach when it | // initialization is idempotent. We should follow the same approach when it | ||||
Show All 13 Lines | crypto::CryptoModule cryptoModule{ | ||||
NotificationsCryptoModule::notificationsCryptoAccountID}; | NotificationsCryptoModule::notificationsCryptoAccountID}; | ||||
NotificationsCryptoModule::serializeAndFlushCryptoModule( | NotificationsCryptoModule::serializeAndFlushCryptoModule( | ||||
cryptoModule, | cryptoModule, | ||||
notificationsCryptoAccountPath, | notificationsCryptoAccountPath, | ||||
picklingKey, | picklingKey, | ||||
callingProcessName); | callingProcessName); | ||||
} | } | ||||
std::string NotificationsCryptoModule::getNotificationsIdentityKeys() { | std::string NotificationsCryptoModule::getNotificationsIdentityKeys( | ||||
CommSecureStore secureStore{}; | const std::string &callingProcessName) { | ||||
folly::Optional<std::string> picklingKey = secureStore.get( | std::string identityKeys; | ||||
NotificationsCryptoModule::secureStoreNotificationsAccountDataKey); | auto caller = [&identityKeys](crypto::CryptoModule cryptoModule) { | ||||
if (!picklingKey.hasValue()) { | identityKeys = cryptoModule.getIdentityKeys(); | ||||
throw std::runtime_error( | }; | ||||
"Attempt to retrieve notifications crypto account before it was " | NotificationsCryptoModule::callCryptoModule(caller, callingProcessName); | ||||
"correctly initialized."); | return identityKeys; | ||||
} | } | ||||
const std::string path = | crypto::EncryptedData NotificationsCryptoModule::initializeNotificationsSession( | ||||
PlatformSpecificTools::getNotificationsCryptoAccountPath(); | const std::string &identityKeys, | ||||
crypto::CryptoModule cryptoModule = | const std::string &prekey, | ||||
NotificationsCryptoModule::deserializeCryptoModule( | const std::string &prekeySignature, | ||||
path, picklingKey.value()); | const std::string &oneTimeKeys, | ||||
return cryptoModule.getIdentityKeys(); | const std::string &callingProcessName) { | ||||
crypto::EncryptedData initialEncryptedMessage; | |||||
auto caller = [&](crypto::CryptoModule &cryptoModule) { | |||||
cryptoModule.initializeOutboundForSendingSession( | |||||
NotificationsCryptoModule::keyserverHostedNotificationsID, | |||||
std::vector<uint8_t>(identityKeys.begin(), identityKeys.end()), | |||||
std::vector<uint8_t>(prekey.begin(), prekey.end()), | |||||
std::vector<uint8_t>(prekeySignature.begin(), prekeySignature.end()), | |||||
std::vector<uint8_t>(oneTimeKeys.begin(), oneTimeKeys.end())); | |||||
initialEncryptedMessage = cryptoModule.encrypt( | |||||
NotificationsCryptoModule::keyserverHostedNotificationsID, | |||||
NotificationsCryptoModule::initialEncryptedMessageContent); | |||||
}; | |||||
NotificationsCryptoModule::callCryptoModule(caller, callingProcessName); | |||||
return initialEncryptedMessage; | |||||
} | |||||
bool NotificationsCryptoModule::isNotificationsSessionInitialized( | |||||
const std::string &callingProcessName) { | |||||
bool sessionInitialized; | |||||
auto caller = [&sessionInitialized](crypto::CryptoModule &cryptoModule) { | |||||
sessionInitialized = cryptoModule.hasSessionFor( | |||||
NotificationsCryptoModule::keyserverHostedNotificationsID); | |||||
}; | |||||
NotificationsCryptoModule::callCryptoModule(caller, callingProcessName); | |||||
return sessionInitialized; | |||||
} | } | ||||
void NotificationsCryptoModule::clearSensitiveData() { | void NotificationsCryptoModule::clearSensitiveData() { | ||||
std::string notificationsCryptoAccountPath = | std::string notificationsCryptoAccountPath = | ||||
PlatformSpecificTools::getNotificationsCryptoAccountPath(); | PlatformSpecificTools::getNotificationsCryptoAccountPath(); | ||||
if (remove(notificationsCryptoAccountPath.c_str()) == -1 && errno != ENOENT) { | if (remove(notificationsCryptoAccountPath.c_str()) == -1 && errno != ENOENT) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"Unable to remove notifications crypto account. Security requirements " | "Unable to remove notifications crypto account. Security requirements " | ||||
"might be violated."); | "might be violated."); | ||||
} | } | ||||
} | } | ||||
} // namespace comm | } // namespace comm |