Libkleo

compliance.cpp
1/* -*- mode: c++; c-basic-offset:4 -*-
2 utils/compliance.cpp
3
4 This file is part of libkleopatra
5 SPDX-FileCopyrightText: 2022 g10 Code GmbH
6 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9*/
10
11#include <config-libkleo.h>
12
13#include "compliance.h"
14
15#include "algorithm.h"
16#include "cryptoconfig.h"
17#include "gnupg.h"
18#include "keyhelpers.h"
19#include "stringutils.h"
20#include "systeminfo.h"
21
22#include <libkleo/debug.h>
23#include <libkleo/keyfiltermanager.h>
24
25#include <libkleo_debug.h>
26
27#include <KColorScheme>
28#include <KLocalizedString>
29
30#include <QPushButton>
31
32#include <gpgme++/key.h>
33
34using namespace Kleo;
35
36bool Kleo::DeVSCompliance::isActive()
37{
38 return getCryptoConfigStringValue("gpg", "compliance") == QLatin1StringView{"de-vs"};
39}
40
41bool Kleo::DeVSCompliance::isCompliant()
42{
43 if (!isActive()) {
44 return false;
45 }
46 // The pseudo option compliance_de_vs was fully added in 2.2.34;
47 // For versions between 2.2.28 and 2.2.33 there was a broken config
48 // value with a wrong type. So for them we add an extra check. This
49 // can be removed in future versions because for GnuPG we could assume
50 // non-compliance for older versions as versions of Kleopatra for
51 // which this matters are bundled with new enough versions of GnuPG anyway.
52 if (engineIsVersion(2, 2, 28) && !engineIsVersion(2, 2, 34)) {
53 return true;
54 }
55 return getCryptoConfigIntValue("gpg", "compliance_de_vs", 0) != 0;
56}
57
58bool Kleo::DeVSCompliance::isBetaCompliance()
59{
60 if (!isActive()) {
61 return false;
62 }
63 // compliance_de_vs > 2000: GnuPG has not yet been approved for VS-NfD or is beta, but we shall assume approval
64 return getCryptoConfigIntValue("gpg", "compliance_de_vs", 0) > 2000;
65}
66
67bool Kleo::DeVSCompliance::algorithmIsCompliant(std::string_view algo)
68{
69 return !isActive() || Kleo::contains(compliantAlgorithms(), algo);
70}
71
72bool Kleo::DeVSCompliance::allSubkeysAreCompliant(const GpgME::Key &key)
73{
74 if (!isActive()) {
75 return true;
76 }
77 // there is at least one usable subkey
78 const auto usableSubkeys = Kleo::count_if(key.subkeys(), [](const auto &sub) {
79 return !sub.isExpired() && !sub.isRevoked();
80 });
81 if (usableSubkeys == 0) {
82 qCDebug(LIBKLEO_LOG) << __func__ << "No usable subkeys found for key" << key;
83 return false;
84 }
85 // and all usable subkeys are compliant
86 return Kleo::all_of(key.subkeys(), [](const auto &sub) {
87 return sub.isDeVs() || sub.isExpired() || sub.isRevoked() || (!sub.canSign() && !sub.canEncrypt() && !sub.canCertify() && sub.canAuthenticate());
88 });
89}
90
91bool Kleo::DeVSCompliance::userIDIsCompliant(const GpgME::UserID &id)
92{
93 if (!isActive()) {
94 return true;
95 }
96 return (id.parent().keyListMode() & GpgME::Validate) //
97 && !id.isRevoked() //
98 && id.validity() >= GpgME::UserID::Full //
99 && allSubkeysAreCompliant(id.parent());
100}
101
102bool Kleo::DeVSCompliance::keyIsCompliant(const GpgME::Key &key)
103{
104 if (!isActive()) {
105 return true;
106 }
107 return (key.keyListMode() & GpgME::Validate) //
108 && allUserIDsHaveFullValidity(key) //
109 && allSubkeysAreCompliant(key);
110}
111
112const std::vector<std::string> &Kleo::DeVSCompliance::compliantAlgorithms()
113{
114 static const std::vector<std::string> compliantAlgos = {
115 "brainpoolP256r1",
116 "brainpoolP384r1",
117 "brainpoolP512r1",
118 "rsa3072",
119 "rsa4096",
120 };
121 return isActive() ? compliantAlgos : Kleo::availableAlgorithms();
122}
123
124const std::vector<std::string> &Kleo::DeVSCompliance::preferredCompliantAlgorithms()
125{
126 static std::vector<std::string> result;
127 if (result.empty()) {
128 const auto &preferredAlgos = Kleo::preferredAlgorithms();
129 result.reserve(preferredAlgos.size());
130 Kleo::copy_if(preferredAlgos, std::back_inserter(result), Kleo::DeVSCompliance::algorithmIsCompliant);
131 }
132 return result;
133}
134
135void Kleo::DeVSCompliance::decorate(QPushButton *button)
136{
137 decorate(button, isCompliant());
138}
139
140void Kleo::DeVSCompliance::decorate(QPushButton *button, bool compliant)
141{
142 if (!button) {
143 return;
144 }
145 if (compliant) {
146 button->setIcon(QIcon::fromTheme(QStringLiteral("security-high")));
147 if (!SystemInfo::isHighContrastModeActive()) {
149 button->setStyleSheet(QStringLiteral("QPushButton { background-color: %1; };").arg(bgColor));
150 }
151 } else {
152 button->setIcon(QIcon::fromTheme(QStringLiteral("security-medium")));
153 if (!SystemInfo::isHighContrastModeActive()) {
155 button->setStyleSheet(QStringLiteral("QPushButton { background-color: %1; };").arg(bgColor));
156 }
157 }
158}
159
160QString Kleo::DeVSCompliance::name()
161{
162 return name(isCompliant());
163}
164
165static QString complianceName(bool compliant)
166{
167 const auto filterId = compliant ? QStringLiteral("de-vs-filter") : QStringLiteral("not-de-vs-filter");
168 if (auto filter = KeyFilterManager::instance()->keyFilterByID(filterId)) {
169 return filter->name();
170 }
171 return compliant ? i18n("VS-NfD compliant") : i18n("Not VS-NfD compliant");
172}
173
174QString Kleo::DeVSCompliance::name(bool compliant)
175{
176 if (!isActive()) {
177 return {};
178 }
179 if (compliant && isBetaCompliance()) {
180 return i18nc("@info append beta-marker to compliance", "%1 (beta)", complianceName(compliant));
181 }
182 return complianceName(compliant);
183}
QBrush background(BackgroundRole=NormalBackground) const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void setIcon(const QIcon &icon)
const QColor & color() const const
QString name(NameFormat format) const const
QIcon fromTheme(const QString &name)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
void setStyleSheet(const QString &styleSheet)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:29:01 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.