File: key_storage_libsecret.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (112 lines) | stat: -rw-r--r-- 3,871 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/os_crypt/sync/key_storage_libsecret.h"

#include "base/base64.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "build/branding_buildflags.h"
#include "components/os_crypt/sync/libsecret_util_linux.h"

namespace {

const SecretSchema kKeystoreSchemaV2 = {
    "chrome_libsecret_os_crypt_password_v2",
    SECRET_SCHEMA_DONT_MATCH_NAME,
    {
        {"application", SECRET_SCHEMA_ATTRIBUTE_STRING},
        {nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING},
    }};

// From a search result, extracts a SecretValue, asserting that there was at
// most one result. Returns nullptr if there are no results.
SecretValue* ToSingleSecret(GList* secret_items) {
  GList* first = g_list_first(secret_items);
  if (first == nullptr)
    return nullptr;
  if (g_list_next(first) != nullptr) {
    VLOG(1) << "OSCrypt found more than one encryption keys.";
  }
  SecretItem* secret_item = static_cast<SecretItem*>(first->data);
  SecretValue* secret_value =
      LibsecretLoader::secret_item_get_secret(secret_item);
  return secret_value;
}

// Checks the timestamps of the secret item and prints findings to logs. We
// presume that at most one secret item can be present.
void AnalyseKeyHistory(GList* secret_items) {
  GList* first = g_list_first(secret_items);
  if (first == nullptr)
    return;

  SecretItem* secret_item = static_cast<SecretItem*>(first->data);
  auto created = base::Time::FromTimeT(
      LibsecretLoader::secret_item_get_created(secret_item));
  auto last_modified = base::Time::FromTimeT(
      LibsecretLoader::secret_item_get_modified(secret_item));

  VLOG(1) << "Libsecret key created: " << created;
  VLOG(1) << "Libsecret key last modified: " << last_modified;
  LOG_IF(WARNING, created != last_modified)
      << "the encryption key has been modified since it was created.";
}

}  // namespace

KeyStorageLibsecret::KeyStorageLibsecret(std::string application_name)
    : application_name_(std::move(application_name)) {}

std::optional<std::string> KeyStorageLibsecret::AddRandomPasswordInLibsecret() {
  std::string password = base::Base64Encode(base::RandBytesAsVector(16));
  GError* error = nullptr;
  bool success = LibsecretLoader::secret_password_store_sync(
      &kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(),
      nullptr, &error, "application", application_name_.c_str(), nullptr);
  if (error) {
    VLOG(1) << "Libsecret lookup failed: " << error->message;
    g_error_free(error);
    return std::nullopt;
  }
  if (!success) {
    VLOG(1) << "Libsecret lookup failed.";
    return std::nullopt;
  }

  VLOG(1) << "OSCrypt generated a new password.";
  return password;
}

std::optional<std::string> KeyStorageLibsecret::GetKeyImpl() {
  LibsecretAttributesBuilder attrs;
  attrs.Append("application", application_name_);

  LibsecretLoader::SearchHelper helper;
  helper.Search(&kKeystoreSchemaV2, attrs.Get(),
                SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS);
  if (!helper.success()) {
    VLOG(1) << "Libsecret lookup failed: " << helper.error()->message;
    return std::nullopt;
  }

  SecretValue* password_libsecret = ToSingleSecret(helper.results());
  if (!password_libsecret) {
    return AddRandomPasswordInLibsecret();
  }
  AnalyseKeyHistory(helper.results());
  std::optional<std::string> password(
      LibsecretLoader::secret_value_get_text(password_libsecret));
  LibsecretLoader::secret_value_unref(password_libsecret);
  return password;
}

bool KeyStorageLibsecret::Init() {
  bool loaded = LibsecretLoader::EnsureLibsecretLoaded();
  if (loaded)
    LibsecretLoader::EnsureKeyringUnlocked();
  return loaded;
}