diff --git a/src/utils/keys.cpp b/src/utils/keys.cpp index 3e8c5d372..00918da9f 100644 --- a/src/utils/keys.cpp +++ b/src/utils/keys.cpp @@ -1,40 +1,56 @@ /* -*- mode: c++; c-basic-offset:4 -*- utils/keys.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2022 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "keys.h" #include +// needed for GPGME_VERSION_NUMBER +#include + #include #include bool Kleo::isSelfSignature(const GpgME::UserID::Signature &signature) { return !qstrcmp(signature.parent().parent().keyID(), signature.signerKeyID()); } bool Kleo::isRevokedOrExpired(const GpgME::UserID &userId) { const auto sigs = userId.signatures(); std::vector selfSigs; std::copy_if(std::begin(sigs), std::end(sigs), std::back_inserter(selfSigs), &Kleo::isSelfSignature); std::sort(std::begin(selfSigs), std::end(selfSigs)); // check the most recent signature const auto sig = !selfSigs.empty() ? selfSigs.back() : GpgME::UserID::Signature{}; return !sig.isNull() && (sig.isRevokation() || sig.isExpired()); } bool Kleo::canCreateCertifications(const GpgME::Key &key) { - // Key::hasSecret() is also true for offline keys (i.e. keys with a secret key stub that are not stored on a card), - // but those keys cannot be used for certifications; therefore, we check whether the primary subkey has a proper secret key - // or whether its secret key is stored on a card, so that gpg can ask for the card. - return key.canCertify() && (key.subkey(0).isSecret() || key.subkey(0).isCardKey()); + return key.canCertify() && canBeUsedForSecretKeyOperations(key); +} + +bool Kleo::canBeUsedForSecretKeyOperations(const GpgME::Key &key) +{ +#if GPGME_VERSION_NUMBER >= 0x011102 // 1.17.2 + // we need to check the primary subkey because Key::hasSecret() is also true if just the secret key stub of an offline key is available + return key.subkey(0).isSecret(); +#else + // older versions of GpgME did not always set the secret flag for card keys + return key.subkey(0).isSecret() || key.subkey(0).isCardKey(); +#endif +} + +bool Kleo::isSecretKeyStoredInKeyRing(const GpgME::Key &key) +{ + return key.subkey(0).isSecret() && !key.subkey(0).isCardKey(); } diff --git a/src/utils/keys.h b/src/utils/keys.h index 0e142a7b4..928034e7d 100644 --- a/src/utils/keys.h +++ b/src/utils/keys.h @@ -1,42 +1,55 @@ /* -*- mode: c++; c-basic-offset:4 -*- utils/keys.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2022 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace Kleo { struct CertificatePair { GpgME::Key openpgp; GpgME::Key cms; }; /** Returns true if \p signature is a self-signature. */ bool isSelfSignature(const GpgME::UserID::Signature &signature); /** * Returns true if the most recent self-signature of \p userId is a revocation * signature or if it has expired. */ bool isRevokedOrExpired(const GpgME::UserID &userId); /** * Returns true if \p key can be used to certify user IDs, i.e. if the key * has the required capability and if the secret key of the (primary) * certification subkey is available in the keyring or on a smart card. + */ +bool canCreateCertifications(const GpgME::Key &key); + +/** + * Returns true if \p key can be used for operations requiring the secret key, + * i.e. if the secret key of the primary key pair is available in the keyring + * or on a smart card. * * \note Key::hasSecret() also returns true if a secret key stub, e.g. of an * offline key, is available in the keyring. */ -bool canCreateCertifications(const GpgME::Key &key); +bool canBeUsedForSecretKeyOperations(const GpgME::Key &key); + +/** + * Returns true if the secret key of the primary key pair of \p key is stored + * in the keyring. + */ +bool isSecretKeyStoredInKeyRing(const GpgME::Key &key); }