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 }