electron/shell/browser/api/electron_api_safe_storage.cc
Charles Kerr aa23198ad8
chore: remove more unused #include calls (#43000)
* chore: in shell/renderer/renderer_client_base.h, remove include media/base/key_systems_support_registration.h

last use removed in c670e38b (##41610)

* chore: iwyu electron/fuses.h

* chore: iwyu media/base/video_frame.h

* chore: iwyu base/functional/callback.h

* chore: iwyu base/task/cancelable_task_tracker.h

* chore: iwyu shell/browser/draggable_region_provider.h

* chore: iwyu shell/browser/ui/inspectable_web_contents_view.h

* chore: iwyu ui/aura/window.h

* chore: iwyu ui/base/win/shell.h

* chore: iwyu ui/display/win/screen_win.h

* chore: iwyu ui/gfx/geometry/insets.h

* chore: iwyu ui/display/display.h

* chore: iwyu ui/gfx/geometry/skia_conversions.h

* chore: iwyu ui/gfx/geometry/rect_conversions.h

* chore: iwyu ui/gfx/geometry/point.h

* chore: iwyu ui/gfx/scoped_canvas.h

* chore: iwyu ui/gfx/image/image.h

* chore: iwyu ui/accessibility/ax_node_data.h

* chore: iwyu ui/views/animation/ink_drop_highlight.h

* chore: iwyu ui/gfx/font_list.h

* chore: iwyu ui/linux/nav_button_provider.h

* chore: iwyu shell/browser/ui/views/frameless_view.h

* chore: iwyu services/metrics/public/cpp/ukm_source_id.h

* chore: iwyu net/http/http_util.h

* chore: iwyu net/base/mime_util.h

* chore: iwyu content/public/common/content_client.h

* chore: iwyu <list>

* chore: iwyu <optional>

* chore: iwyu <memory>

* chore: iwyu base/files/file_path.h

* chore: iwyu ui/base/cursor/cursor.h

* chore: iwyu build/build_config.h

* chore: iwyu content/public/browser/web_contents.h

* chore: iwyu shell/browser/hid/hid_chooser_context.h

* chore: iwyu shell/common/platform_util.h

* chore: iwyu base/task/single_thread_task_runner.h

* chore: iwyu content/browser/renderer_host/render_widget_host_impl.h

* chore: iwyu content/public/browser/render_widget_host.h

* chore: iwyu shell/browser/electron_browser_context.h

* chore: iwyu content/public/browser/web_contents_observer.h

* chore: iwyu content/public/browser/render_frame_host.h

* chore: iwyu content/public/browser/media_stream_request.h

* chore: iwyu chrome/common/chrome_paths.h

* chore: iwyu chrome/browser/icon_manager.h

* chore: iwyu printing/print_settings.h

* chore: iwyu renderer/pepper_helper.h

* chore: iwyu shell/browser/api/process_metric.h

* chore: iwyu shell/browser/electron_browser_client.h

* chore: iwyu shell/browser/electron_browser_context.h

* chore: iwyu shell/browser/api/electron_api_session.h

* chore: iwyu shell/browser/api/electron_api_app.h

* chore: iwyu shell/browser/ui/views/client_frame_view_linux.h

* chore: iwyu shell/browser/native_window_views.h

* chore: iwyu base/win/windows_version.h

* chore: iwyu shell/common/electron_paths.h

* chore: iwyu content/public/common/content_switches.h

* chore: iwyu third_party/skia/include/core/SkRRect.h

* chore: iwyu third_party/skia/include/core/SkBitmap.h

* chore: iwyu third_party/skia

* chore: iwyu shell/browser/osr/osr_host_display_client.h

* chore: iwyu shell/browser/login_handler.h

* chore: iwyu shell/browser/javascript_environment.h

* chore: iwyu shell/browser/event_emitter_mixin.h

* fix: mac

* fix: mac

* chore: iwyu base/nix/xdg_util.h

* fix: win

* fix: win

* fix: win

* fix: win
2024-07-25 11:25:45 +02:00

150 lines
4.9 KiB
C++

// Copyright (c) 2021 Slack Technologies, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/api/electron_api_safe_storage.h"
#include <string>
#include "components/os_crypt/sync/os_crypt.h"
#include "shell/browser/browser.h"
#include "shell/browser/browser_process_impl.h"
#include "shell/common/gin_converters/base_converter.h"
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/node_includes.h"
namespace electron::safestorage {
static const char* kEncryptionVersionPrefixV10 = "v10";
static const char* kEncryptionVersionPrefixV11 = "v11";
static bool use_password_v10 = false;
bool IsEncryptionAvailable() {
#if BUILDFLAG(IS_LINUX)
// Calling IsEncryptionAvailable() before the app is ready results in a crash
// on Linux.
// Refs: https://github.com/electron/electron/issues/32206.
if (!Browser::Get()->is_ready())
return false;
return OSCrypt::IsEncryptionAvailable() ||
(use_password_v10 &&
static_cast<BrowserProcessImpl*>(g_browser_process)
->linux_storage_backend() == "basic_text");
#else
return OSCrypt::IsEncryptionAvailable();
#endif
}
void SetUsePasswordV10(bool use) {
use_password_v10 = use;
}
#if BUILDFLAG(IS_LINUX)
std::string GetSelectedLinuxBackend() {
if (!Browser::Get()->is_ready())
return "unknown";
return static_cast<BrowserProcessImpl*>(g_browser_process)
->linux_storage_backend();
}
#endif
v8::Local<v8::Value> EncryptString(v8::Isolate* isolate,
const std::string& plaintext) {
if (!IsEncryptionAvailable()) {
if (!Browser::Get()->is_ready()) {
gin_helper::ErrorThrower(isolate).ThrowError(
"safeStorage cannot be used before app is ready");
return v8::Local<v8::Value>();
}
gin_helper::ErrorThrower(isolate).ThrowError(
"Error while encrypting the text provided to "
"safeStorage.encryptString. "
"Encryption is not available.");
return v8::Local<v8::Value>();
}
std::string ciphertext;
bool encrypted = OSCrypt::EncryptString(plaintext, &ciphertext);
if (!encrypted) {
gin_helper::ErrorThrower(isolate).ThrowError(
"Error while encrypting the text provided to "
"safeStorage.encryptString.");
return v8::Local<v8::Value>();
}
return node::Buffer::Copy(isolate, ciphertext.c_str(), ciphertext.size())
.ToLocalChecked();
}
std::string DecryptString(v8::Isolate* isolate, v8::Local<v8::Value> buffer) {
if (!IsEncryptionAvailable()) {
if (!Browser::Get()->is_ready()) {
gin_helper::ErrorThrower(isolate).ThrowError(
"safeStorage cannot be used before app is ready");
return "";
}
gin_helper::ErrorThrower(isolate).ThrowError(
"Error while decrypting the ciphertext provided to "
"safeStorage.decryptString. "
"Decryption is not available.");
return "";
}
if (!node::Buffer::HasInstance(buffer)) {
gin_helper::ErrorThrower(isolate).ThrowError(
"Expected the first argument of decryptString() to be a buffer");
return "";
}
// ensures an error is thrown in Mac or Linux on
// decryption failure, rather than failing silently
const char* data = node::Buffer::Data(buffer);
auto size = node::Buffer::Length(buffer);
std::string ciphertext(data, size);
if (ciphertext.empty()) {
return "";
}
if (ciphertext.find(kEncryptionVersionPrefixV10) != 0 &&
ciphertext.find(kEncryptionVersionPrefixV11) != 0) {
gin_helper::ErrorThrower(isolate).ThrowError(
"Error while decrypting the ciphertext provided to "
"safeStorage.decryptString. "
"Ciphertext does not appear to be encrypted.");
return "";
}
std::string plaintext;
bool decrypted = OSCrypt::DecryptString(ciphertext, &plaintext);
if (!decrypted) {
gin_helper::ErrorThrower(isolate).ThrowError(
"Error while decrypting the ciphertext provided to "
"safeStorage.decryptString.");
return "";
}
return plaintext;
}
} // namespace electron::safestorage
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
gin_helper::Dictionary dict(isolate, exports);
dict.SetMethod("isEncryptionAvailable",
&electron::safestorage::IsEncryptionAvailable);
dict.SetMethod("encryptString", &electron::safestorage::EncryptString);
dict.SetMethod("decryptString", &electron::safestorage::DecryptString);
dict.SetMethod("setUsePlainTextEncryption",
&electron::safestorage::SetUsePasswordV10);
#if BUILDFLAG(IS_LINUX)
dict.SetMethod("getSelectedStorageBackend",
&electron::safestorage::GetSelectedLinuxBackend);
#endif
}
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_safe_storage, Initialize)