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
34bool Kleo::DeVSCompliance::isActive()
35{
36 return getCryptoConfigStringValue("gpg", "compliance") == QLatin1StringView{"de-vs"};
37}
38
39bool Kleo::DeVSCompliance::isCompliant()
40{
41 if (!isActive()) {
42 return false;
43 }
44 // The pseudo option compliance_de_vs was fully added in 2.2.34;
45 // For versions between 2.2.28 and 2.2.33 there was a broken config
46 // value with a wrong type. So for them we add an extra check. This
47 // can be removed in future versions because for GnuPG we could assume
48 // non-compliance for older versions as versions of Kleopatra for
49 // which this matters are bundled with new enough versions of GnuPG anyway.
50 if (engineIsVersion(2, 2, 28) && !engineIsVersion(2, 2, 34)) {
51 return true;
52 }
53 return getCryptoConfigIntValue("gpg", "compliance_de_vs", 0) != 0;
54}
55
56bool Kleo::DeVSCompliance::algorithmIsCompliant(std::string_view algo)
57{
58 return !isActive() || Kleo::contains(compliantAlgorithms(), algo);
59}
60
61bool Kleo::DeVSCompliance::allSubkeysAreCompliant(const GpgME::Key &key)
62{
63 if (!isActive()) {
64 return true;
65 }
66 // there is at least one usable subkey
67 const auto usableSubkeys = Kleo::count_if(key.subkeys(), [](const auto &sub) {
68 return !sub.isExpired() && !sub.isRevoked();
69 });
70 if (usableSubkeys == 0) {
71 qCDebug(LIBKLEO_LOG) << __func__ << "No usable subkeys found for key" << key;
72 return false;
73 }
74 // and all usable subkeys are compliant
75 return Kleo::all_of(key.subkeys(), [](const auto &sub) {
76 return sub.isDeVs() || sub.isExpired() || sub.isRevoked();
77 });
78}
79
80bool Kleo::DeVSCompliance::userIDIsCompliant(const GpgME::UserID &id)
81{
82 if (!isActive()) {
83 return true;
84 }
85 return (id.parent().keyListMode() & GpgME::Validate) //
86 && !id.isRevoked() //
87 && id.validity() >= GpgME::UserID::Full //
88 && allSubkeysAreCompliant(id.parent());
89}
90
91bool Kleo::DeVSCompliance::keyIsCompliant(const GpgME::Key &key)
92{
93 if (!isActive()) {
94 return true;
95 }
96 return (key.keyListMode() & GpgME::Validate) //
97 && allUserIDsHaveFullValidity(key) //
98 && allSubkeysAreCompliant(key);
99}
100
101const std::vector<std::string> &Kleo::DeVSCompliance::compliantAlgorithms()
102{
103 static const std::vector<std::string> compliantAlgos = {
104 "brainpoolP256r1",
105 "brainpoolP384r1",
106 "brainpoolP512r1",
107 "rsa3072",
108 "rsa4096",
109 };
110 return isActive() ? compliantAlgos : Kleo::availableAlgorithms();
111}
112
113const std::vector<std::string> &Kleo::DeVSCompliance::preferredCompliantAlgorithms()
114{
115 static std::vector<std::string> result;
116 if (result.empty()) {
117 const auto &preferredAlgos = Kleo::preferredAlgorithms();
118 result.reserve(preferredAlgos.size());
119 Kleo::copy_if(preferredAlgos, std::back_inserter(result), Kleo::DeVSCompliance::algorithmIsCompliant);
120 }
121 return result;
122}
123
124void Kleo::DeVSCompliance::decorate(QPushButton *button)
125{
126 decorate(button, isCompliant());
127}
128
129void Kleo::DeVSCompliance::decorate(QPushButton *button, bool compliant)
130{
131 if (!button) {
132 return;
133 }
134 if (compliant) {
135 button->setIcon(QIcon::fromTheme(QStringLiteral("security-high")));
136 if (!SystemInfo::isHighContrastModeActive()) {
138 button->setStyleSheet(QStringLiteral("QPushButton { background-color: %1; };").arg(bgColor));
139 }
140 } else {
141 button->setIcon(QIcon::fromTheme(QStringLiteral("security-medium")));
142 if (!SystemInfo::isHighContrastModeActive()) {
144 button->setStyleSheet(QStringLiteral("QPushButton { background-color: %1; };").arg(bgColor));
145 }
146 }
147}
148
149QString Kleo::DeVSCompliance::name()
150{
151 return name(isCompliant());
152}
153
154QString Kleo::DeVSCompliance::name(bool compliant)
155{
156 const auto filterId = compliant ? QStringLiteral("de-vs-filter") : QStringLiteral("not-de-vs-filter");
157 if (auto filter = KeyFilterManager::instance()->keyFilterByID(filterId)) {
158 return filter->name();
159 }
160 return compliant ? i18n("VS-NfD compliant") : i18n("Not VS-NfD compliant");
161}
QBrush background(BackgroundRole=NormalBackground) const
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 Tue Mar 26 2024 11:14:12 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.