key_storage_libsecret.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/os_crypt/key_storage_libsecret.h"
  5. #include "base/base64.h"
  6. #include "base/logging.h"
  7. #include "base/rand_util.h"
  8. #include "base/strings/string_number_conversions.h"
  9. #include "base/time/time.h"
  10. #include "build/branding_buildflags.h"
  11. #include "components/os_crypt/libsecret_util_linux.h"
  12. namespace {
  13. const SecretSchema kKeystoreSchemaV2 = {
  14. "chrome_libsecret_os_crypt_password_v2",
  15. SECRET_SCHEMA_DONT_MATCH_NAME,
  16. {
  17. {"application", SECRET_SCHEMA_ATTRIBUTE_STRING},
  18. {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING},
  19. }};
  20. // From a search result, extracts a SecretValue, asserting that there was at
  21. // most one result. Returns nullptr if there are no results.
  22. SecretValue* ToSingleSecret(GList* secret_items) {
  23. GList* first = g_list_first(secret_items);
  24. if (first == nullptr)
  25. return nullptr;
  26. if (g_list_next(first) != nullptr) {
  27. VLOG(1) << "OSCrypt found more than one encryption keys.";
  28. }
  29. SecretItem* secret_item = static_cast<SecretItem*>(first->data);
  30. SecretValue* secret_value =
  31. LibsecretLoader::secret_item_get_secret(secret_item);
  32. return secret_value;
  33. }
  34. // Checks the timestamps of the secret item and prints findings to logs. We
  35. // presume that at most one secret item can be present.
  36. void AnalyseKeyHistory(GList* secret_items) {
  37. GList* first = g_list_first(secret_items);
  38. if (first == nullptr)
  39. return;
  40. SecretItem* secret_item = static_cast<SecretItem*>(first->data);
  41. auto created = base::Time::FromTimeT(
  42. LibsecretLoader::secret_item_get_created(secret_item));
  43. auto last_modified = base::Time::FromTimeT(
  44. LibsecretLoader::secret_item_get_modified(secret_item));
  45. VLOG(1) << "Libsecret key created: " << created;
  46. VLOG(1) << "Libsecret key last modified: " << last_modified;
  47. LOG_IF(WARNING, created != last_modified)
  48. << "the encryption key has been modified since it was created.";
  49. }
  50. } // namespace
  51. KeyStorageLibsecret::KeyStorageLibsecret(std::string application_name)
  52. : application_name_(std::move(application_name)) {}
  53. absl::optional<std::string>
  54. KeyStorageLibsecret::AddRandomPasswordInLibsecret() {
  55. std::string password;
  56. base::Base64Encode(base::RandBytesAsString(16), &password);
  57. GError* error = nullptr;
  58. bool success = LibsecretLoader::secret_password_store_sync(
  59. &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(),
  60. nullptr, &error, "application", application_name_.c_str(), nullptr);
  61. if (error) {
  62. VLOG(1) << "Libsecret lookup failed: " << error->message;
  63. g_error_free(error);
  64. return absl::nullopt;
  65. }
  66. if (!success) {
  67. VLOG(1) << "Libsecret lookup failed.";
  68. return absl::nullopt;
  69. }
  70. VLOG(1) << "OSCrypt generated a new password.";
  71. return password;
  72. }
  73. absl::optional<std::string> KeyStorageLibsecret::GetKeyImpl() {
  74. LibsecretAttributesBuilder attrs;
  75. attrs.Append("application", application_name_);
  76. LibsecretLoader::SearchHelper helper;
  77. helper.Search(&kKeystoreSchemaV2, attrs.Get(),
  78. SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS);
  79. if (!helper.success()) {
  80. VLOG(1) << "Libsecret lookup failed: " << helper.error()->message;
  81. return absl::nullopt;
  82. }
  83. SecretValue* password_libsecret = ToSingleSecret(helper.results());
  84. if (!password_libsecret) {
  85. return AddRandomPasswordInLibsecret();
  86. }
  87. AnalyseKeyHistory(helper.results());
  88. absl::optional<std::string> password(
  89. LibsecretLoader::secret_value_get_text(password_libsecret));
  90. LibsecretLoader::secret_value_unref(password_libsecret);
  91. return password;
  92. }
  93. bool KeyStorageLibsecret::Init() {
  94. bool loaded = LibsecretLoader::EnsureLibsecretLoaded();
  95. if (loaded)
  96. LibsecretLoader::EnsureKeyringUnlocked();
  97. return loaded;
  98. }