File indexing completed on 2024-06-23 05:14:10

0001 /*  smartcard/card.h
0002 
0003     This file is part of Kleopatra, the KDE keymanager
0004     SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
0005     SPDX-FileContributor: Intevation GmbH
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "card.h"
0011 
0012 #include "readerstatus.h"
0013 
0014 #include "kleopatra_debug.h"
0015 
0016 using namespace Kleo;
0017 using namespace Kleo::SmartCard;
0018 
0019 namespace
0020 {
0021 static QString formatVersion(int value)
0022 {
0023     if (value < 0) {
0024         return QString();
0025     }
0026 
0027     const unsigned int a = ((value >> 24) & 0xff);
0028     const unsigned int b = ((value >> 16) & 0xff);
0029     const unsigned int c = ((value >> 8) & 0xff);
0030     const unsigned int d = ((value)&0xff);
0031     if (a) {
0032         return QStringLiteral("%1.%2.%3.%4").arg(QString::number(a), QString::number(b), QString::number(c), QString::number(d));
0033     } else if (b) {
0034         return QStringLiteral("%1.%2.%3").arg(QString::number(b), QString::number(c), QString::number(d));
0035     } else if (c) {
0036         return QStringLiteral("%1.%2").arg(QString::number(c), QString::number(d));
0037     }
0038     return QString::number(d);
0039 }
0040 }
0041 
0042 Card::Card()
0043 {
0044 }
0045 
0046 Card::~Card()
0047 {
0048 }
0049 
0050 void Card::setStatus(Status s)
0051 {
0052     mStatus = s;
0053 }
0054 
0055 Card::Status Card::status() const
0056 {
0057     return mStatus;
0058 }
0059 
0060 void Card::setSerialNumber(const std::string &sn)
0061 {
0062     mSerialNumber = sn;
0063 }
0064 
0065 std::string Card::serialNumber() const
0066 {
0067     return mSerialNumber;
0068 }
0069 
0070 QString Card::displaySerialNumber() const
0071 {
0072     return mDisplaySerialNumber;
0073 }
0074 
0075 void Card::setDisplaySerialNumber(const QString &serialNumber)
0076 {
0077     mDisplaySerialNumber = serialNumber;
0078 }
0079 
0080 std::string Card::appName() const
0081 {
0082     return mAppName;
0083 }
0084 
0085 void Card::setAppName(const std::string &name)
0086 {
0087     mAppName = name;
0088 }
0089 
0090 void Card::setAppVersion(int version)
0091 {
0092     mAppVersion = version;
0093 }
0094 
0095 int Card::appVersion() const
0096 {
0097     return mAppVersion;
0098 }
0099 
0100 QString Card::displayAppVersion() const
0101 {
0102     return formatVersion(mAppVersion);
0103 }
0104 
0105 void Card::setManufacturer(const std::string &value)
0106 {
0107     if (!manufacturer().empty()) {
0108         qCDebug(KLEOPATRA_LOG) << "Card manufacturer is already set; overwriting existing value";
0109         mCardInfo.erase("MANUFACTURER");
0110     }
0111     mCardInfo.insert({"MANUFACTURER", value});
0112 }
0113 
0114 std::string Card::manufacturer() const
0115 {
0116     return cardInfo("MANUFACTURER");
0117 }
0118 
0119 std::string Card::cardType() const
0120 {
0121     return mCardType;
0122 }
0123 
0124 int Card::cardVersion() const
0125 {
0126     return mCardVersion;
0127 }
0128 
0129 QString Card::displayCardVersion() const
0130 {
0131     return formatVersion(mCardVersion);
0132 }
0133 
0134 QString Card::cardHolder() const
0135 {
0136     return mCardHolder;
0137 }
0138 
0139 void Card::setSigningKeyRef(const std::string &keyRef)
0140 {
0141     mSigningKeyRef = keyRef;
0142 }
0143 
0144 std::string Card::signingKeyRef() const
0145 {
0146     return mSigningKeyRef;
0147 }
0148 
0149 bool Card::hasSigningKey() const
0150 {
0151     return !keyInfo(mSigningKeyRef).grip.empty();
0152 }
0153 
0154 void Card::setEncryptionKeyRef(const std::string &keyRef)
0155 {
0156     mEncryptionKeyRef = keyRef;
0157 }
0158 
0159 std::string Card::encryptionKeyRef() const
0160 {
0161     return mEncryptionKeyRef;
0162 }
0163 
0164 bool Card::hasEncryptionKey() const
0165 {
0166     return !keyInfo(mEncryptionKeyRef).grip.empty();
0167 }
0168 
0169 void Card::setAuthenticationKeyRef(const std::string &keyRef)
0170 {
0171     mAuthenticationKeyRef = keyRef;
0172 }
0173 
0174 std::string Card::authenticationKeyRef() const
0175 {
0176     return mAuthenticationKeyRef;
0177 }
0178 
0179 bool Card::hasAuthenticationKey() const
0180 {
0181     return !keyInfo(mAuthenticationKeyRef).grip.empty();
0182 }
0183 
0184 std::vector<Card::PinState> Card::pinStates() const
0185 {
0186     return mPinStates;
0187 }
0188 
0189 void Card::setPinStates(const std::vector<PinState> &pinStates)
0190 {
0191     mPinStates = pinStates;
0192 }
0193 
0194 bool Card::hasNullPin() const
0195 {
0196     return mHasNullPin;
0197 }
0198 
0199 void Card::setHasNullPin(bool value)
0200 {
0201     mHasNullPin = value;
0202 }
0203 
0204 bool Card::canLearnKeys() const
0205 {
0206     return mCanLearn;
0207 }
0208 
0209 void Card::setCanLearnKeys(bool value)
0210 {
0211     mCanLearn = value;
0212 }
0213 
0214 bool Card::operator==(const Card &other) const
0215 {
0216     return mCanLearn == other.mCanLearn && mHasNullPin == other.mHasNullPin && mStatus == other.mStatus && mSerialNumber == other.mSerialNumber
0217         && mAppName == other.mAppName && mAppVersion == other.mAppVersion && mCardType == other.mCardType && mCardVersion == other.mCardVersion
0218         && mCardHolder == other.mCardHolder && mSigningKeyRef == other.mSigningKeyRef && mEncryptionKeyRef == other.mEncryptionKeyRef
0219         && mAuthenticationKeyRef == other.mAuthenticationKeyRef && mPinStates == other.mPinStates && mErrMsg == other.mErrMsg && mKeyInfos == other.mKeyInfos
0220         && mCardInfo == other.mCardInfo;
0221 }
0222 
0223 bool Card::operator!=(const Card &other) const
0224 {
0225     return !operator==(other);
0226 }
0227 
0228 void Card::setErrorMsg(const QString &msg)
0229 {
0230     mErrMsg = msg;
0231 }
0232 
0233 QString Card::errorMsg() const
0234 {
0235     return mErrMsg;
0236 }
0237 
0238 void Card::setInitialKeyInfos(const std::vector<KeyPairInfo> &infos)
0239 {
0240     mKeyInfos = infos;
0241 }
0242 
0243 const std::vector<KeyPairInfo> &Card::keyInfos() const
0244 {
0245     return mKeyInfos;
0246 }
0247 
0248 const KeyPairInfo &Card::keyInfo(const std::string &keyRef) const
0249 {
0250     static const KeyPairInfo nullKey;
0251     for (const KeyPairInfo &k : mKeyInfos) {
0252         if (k.keyRef == keyRef) {
0253             return k;
0254         }
0255     }
0256     return nullKey;
0257 }
0258 
0259 void Card::setCardInfo(const std::vector<std::pair<std::string, std::string>> &infos)
0260 {
0261     qCDebug(KLEOPATRA_LOG) << "Card" << serialNumber().c_str() << "info:";
0262     for (const auto &pair : infos) {
0263         qCDebug(KLEOPATRA_LOG) << pair.first.c_str() << ":" << pair.second.c_str();
0264         parseCardInfo(pair.first, pair.second);
0265     }
0266     processCardInfo();
0267 }
0268 
0269 namespace
0270 {
0271 static int parseHexEncodedVersionTuple(const std::string &s)
0272 {
0273     // s is a hex-encoded, unsigned int-packed version tuple,
0274     // i.e. each byte represents one part of the version tuple
0275     bool ok;
0276     const auto version = QByteArray::fromStdString(s).toUInt(&ok, 16);
0277     return ok ? version : -1;
0278 }
0279 }
0280 
0281 void Card::parseCardInfo(const std::string &name, const std::string &value)
0282 {
0283     if (name == "APPVERSION") {
0284         mAppVersion = parseHexEncodedVersionTuple(value);
0285     } else if (name == "CARDTYPE") {
0286         mCardType = value;
0287     } else if (name == "CARDVERSION") {
0288         mCardVersion = parseHexEncodedVersionTuple(value);
0289     } else if (name == "DISP-NAME") {
0290         auto list = QString::fromUtf8(QByteArray::fromStdString(value)).split(QStringLiteral("<<"), Qt::SkipEmptyParts);
0291         std::reverse(list.begin(), list.end());
0292         mCardHolder = list.join(QLatin1Char(' ')).replace(QLatin1Char('<'), QLatin1Char(' '));
0293     } else if (name == "KEYPAIRINFO") {
0294         const KeyPairInfo info = KeyPairInfo::fromStatusLine(value);
0295         if (info.grip.empty()) {
0296             qCWarning(KLEOPATRA_LOG) << "Invalid KEYPAIRINFO status line" << QString::fromStdString(value);
0297             setStatus(Card::CardError);
0298         } else {
0299             updateKeyInfo(info);
0300         }
0301     } else if (name == "KEY-FPR") {
0302         // handle OpenPGP key fingerprints
0303         const auto values = QString::fromStdString(value).split(QLatin1Char(' '));
0304         if (values.size() < 2) {
0305             qCWarning(KLEOPATRA_LOG) << "Invalid KEY-FPR status line" << QString::fromStdString(value);
0306             setStatus(Card::CardError);
0307         }
0308         const auto keyNumber = values[0];
0309         const std::string keyRef = "OPENPGP." + keyNumber.toStdString();
0310         const auto fpr = values[1].toStdString();
0311         if (keyNumber == QLatin1Char('1') || keyNumber == QLatin1Char('2') || keyNumber == QLatin1Char('3')) {
0312             addCardInfo("KLEO-FPR-" + keyRef, fpr);
0313         } else {
0314             // Maybe more keyslots in the future?
0315             qCDebug(KLEOPATRA_LOG) << "Unhandled keyslot" << keyNumber;
0316         }
0317     } else if (name == "MANUFACTURER") {
0318         // the value of MANUFACTURER is the manufacturer ID as unsigned number
0319         // optionally followed by the name of the manufacturer, e.g.
0320         // 6 Yubico
0321         // 65534 unmanaged S/N range
0322         // for PKCS#15 cards the manufacturer ID is always 0, e.g.
0323         // 0 www.atos.net/cardos [R&S]
0324         const auto startOfManufacturerName = value.find(' ');
0325         if (startOfManufacturerName != std::string::npos) {
0326             addCardInfo(name, value.substr(startOfManufacturerName + 1));
0327         }
0328     } else {
0329         mCardInfo.insert({name, value});
0330     }
0331 }
0332 
0333 void Card::processCardInfo()
0334 {
0335 }
0336 
0337 void Card::addCardInfo(const std::string &name, const std::string &value)
0338 {
0339     mCardInfo.insert({name, value});
0340 }
0341 
0342 std::string Card::cardInfo(const std::string &name) const
0343 {
0344     const auto range = mCardInfo.equal_range(name);
0345     return range.first != range.second ? range.first->second : std::string();
0346 }
0347 
0348 void Card::updateKeyInfo(const KeyPairInfo &keyPairInfo)
0349 {
0350     for (KeyPairInfo &k : mKeyInfos) {
0351         if (k.keyRef == keyPairInfo.keyRef) {
0352             k.update(keyPairInfo);
0353             return;
0354         }
0355     }
0356     mKeyInfos.push_back(keyPairInfo);
0357 }
0358 
0359 std::string Card::keyFingerprint(const std::string &keyRef) const
0360 {
0361     return cardInfo("KLEO-FPR-" + keyRef);
0362 }