Commit 3ca64c75 authored by Ingo Klöcker's avatar Ingo Klöcker
Browse files

Parse and store the key pair info in the Card base class

This affects only PIVCard. In OpenPGPCard the info was parsed and stored,
but never used.

GnuPG-bug-id: 5125, 5126, 5128
parent ea773eb9
......@@ -11,6 +11,8 @@
#include "readerstatus.h"
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::SmartCard;
......@@ -175,6 +177,22 @@ QString Card::errorMsg() const
return mErrMsg;
}
const std::vector<KeyPairInfo> & Card::keyInfos() const
{
return mKeyInfos;
}
const KeyPairInfo & Card::keyInfo(const std::string &keyRef) const
{
static const KeyPairInfo nullKey;
for (const KeyPairInfo &k : mKeyInfos) {
if (k.keyRef == keyRef) {
return k;
}
}
return nullKey;
}
namespace {
static int parseHexEncodedVersionTuple(const std::string &s) {
// s is a hex-encoded, unsigned int-packed version tuple,
......@@ -202,7 +220,27 @@ bool Card::parseCardInfo(const std::string &name, const std::string &value)
std::reverse(list.begin(), list.end());
mCardHolder = list.join(QLatin1Char(' '));
return true;
} else if (name == "KEYPAIRINFO") {
const KeyPairInfo info = KeyPairInfo::fromStatusLine(value);
if (info.grip.empty()) {
qCWarning(KLEOPATRA_LOG) << "Invalid KEYPAIRINFO status line" << QString::fromStdString(value);
setStatus(Card::CardError);
} else {
updateKeyInfo(info);
}
return true;
}
return false;
}
void Card::updateKeyInfo(const KeyPairInfo& keyPairInfo)
{
for (KeyPairInfo &k : mKeyInfos) {
if (k.keyRef == keyPairInfo.keyRef) {
k.update(keyPairInfo);
return;
}
}
mKeyInfos.push_back(keyPairInfo);
}
......@@ -9,6 +9,8 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "keypairinfo.h"
#include <string>
#include <vector>
......@@ -18,6 +20,7 @@ namespace Kleo
{
namespace SmartCard
{
/** Class representing an application on a smartcard or similar hardware token. */
class Card
{
......@@ -85,11 +88,17 @@ public:
QString errorMsg() const;
void setErrorMsg(const QString &msg);
const std::vector<KeyPairInfo> & keyInfos() const;
const KeyPairInfo & keyInfo(const std::string &keyRef) const;
protected:
void setAppName(const std::string &name);
bool parseCardInfo(const std::string &name, const std::string &value);
private:
void updateKeyInfo(const KeyPairInfo &keyPairInfo);
private:
bool mCanLearn = false;
bool mHasNullPin = false;
......@@ -103,6 +112,7 @@ private:
QString mCardHolder;
std::vector<PinState> mPinStates;
QString mErrMsg;
std::vector<KeyPairInfo> mKeyInfos;
};
} // namespace Smartcard
} // namespace Kleopatra
......
......@@ -37,3 +37,28 @@ KeyPairInfo KeyPairInfo::fromStatusLine(const std::string &s) {
}
return info;
}
void KeyPairInfo::update(const KeyPairInfo &other)
{
Q_ASSERT(keyRef == other.keyRef);
if (keyRef != other.keyRef) {
return;
}
if (grip != other.grip) {
// reset all infos if the grip changed
grip = other.grip;
usage = std::string();
keyTime = std::string();
algorithm = std::string();
}
// now update all infos from other's infos unless other's infos are empty or not specified
if (!other.usage.empty() && other.usage != "-") {
usage = other.usage;
}
if (!other.keyTime.empty() && other.keyTime != "-") {
keyTime = other.keyTime;
}
if (!other.algorithm.empty() && other.algorithm != "-") {
algorithm = other.algorithm;
}
}
......@@ -18,6 +18,8 @@ namespace SmartCard
struct KeyPairInfo {
static KeyPairInfo fromStatusLine(const std::string &s);
void update(const KeyPairInfo &other);
std::string grip;
std::string keyRef;
std::string usage;
......
......@@ -98,26 +98,6 @@ void OpenPGPCard::setCardInfo(const std::vector< std::pair<std::string, std::str
// Maybe more keyslots in the future?
qCDebug(KLEOPATRA_LOG) << "Unhandled keyslot";
}
} else if (pair.first == "KEYPAIRINFO") {
// Fun, same as above but the other way around.
const auto values = QString::fromStdString(pair.second).split(QLatin1Char(' '));
if (values.size() < 2) {
qCWarning(KLEOPATRA_LOG) << "Invalid entry.";
setStatus(Card::CardError);
continue;
}
const auto usage = values[1];
const auto grip = values[0].toStdString();
if (usage == QLatin1String("OPENPGP.1")) {
mMetaInfo.insert(std::string("SIG") + pair.first, grip);
} else if (usage == QLatin1String("OPENPGP.2")) {
mMetaInfo.insert(std::string("ENC") + pair.first, grip);
} else if (usage == QLatin1String("OPENPGP.3")) {
mMetaInfo.insert(std::string("AUTH") + pair.first, grip);
} else {
// Maybe more keyslots in the future?
qCDebug(KLEOPATRA_LOG) << "Unhandled keyslot";
}
} else {
mMetaInfo.insert(pair.first, pair.second);
}
......
......@@ -115,7 +115,7 @@ std::vector< std::pair<std::string, QString> > PIVCard::supportedAlgorithms(cons
std::string PIVCard::keyGrip(const std::string& keyRef) const
{
return mMetaInfo.value("KEYPAIRINFO-" + keyRef);
return keyInfo(keyRef).grip;
}
void PIVCard::setCardInfo(const std::vector< std::pair<std::string, std::string> > &infos)
......@@ -126,18 +126,7 @@ void PIVCard::setCardInfo(const std::vector< std::pair<std::string, std::string>
if (parseCardInfo(pair.first, pair.second)) {
continue;
}
if (pair.first == "KEYPAIRINFO") {
const KeyPairInfo info = KeyPairInfo::fromStatusLine(pair.second);
if (info.grip.empty()) {
qCWarning(KLEOPATRA_LOG) << "Invalid KEYPAIRINFO status line"
<< QString::fromStdString(pair.second);
setStatus(Card::CardError);
continue;
}
mMetaInfo.insert("KEYPAIRINFO-" + info.keyRef, info.grip);
} else {
mMetaInfo.insert(pair.first, pair.second);
}
mMetaInfo.insert(pair.first, pair.second);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment