puk-unlock forgotten - added; refs #30

master
Marc Wäckerlin 10 years ago
parent f2a1435cf4
commit 245dde6f5b
  1. 96
      src/cardos.hxx
  2. 8
      src/suisseid.hxx

@ -50,15 +50,14 @@ namespace cardos {
wrong_pin(const std::string& s) throw(): exception("wrong pin "+s) {}
};
//----------------------------------------------------------------------------
class user_pin_locked: public exception {
class pin_locked: public exception {
public:
user_pin_locked(const std::string& s) throw():
exception("user pin locked "+s) {}
pin_locked() throw(): exception("pin is locked and cannot be changed") {}
};
//----------------------------------------------------------------------------
class wrong_puk: public exception {
class wrong_puk: public wrong_pin {
public:
wrong_puk(const std::string& s) throw(): exception("wrong puk "+s) {}
wrong_puk(const std::string& s) throw(): wrong_pin("wrong puk "+s) {}
};
//----------------------------------------------------------------------------
class wrong_result: public exception {
@ -116,11 +115,6 @@ namespace cardos {
+"; length: "+mrw::string(j)) {
}
};
//----------------------------------------------------------------------------
class pin_locked: public exception {
public:
pin_locked() throw(): exception("pin is locked and cannot be changed") {}
};
//@}
//============================================================================
@ -1088,7 +1082,7 @@ namespace cardos {
//! Performs a PIN test (CHV test)
void verify(std::string pin, unsigned char id,
VerifyMode mode = SEARCH_FROM_DF) {
CRYPTOLOG("log");
CRYPTOLOG("log pin=\""<<pin<<"\" id=\""<<std::hex<<(int)id<<"\"");
check(send(0x00, 0x20, 0x00, (unsigned char)(id|mode), pin));
}
@ -1152,10 +1146,14 @@ namespace cardos {
/// Logon with transport PIN
void logonTransport(std::string pin) {
CRYPTOLOG("log");
CRYPTOLOG("log pin=\""<<pin<<"\"");
pcsc::Connection::Reader::Transaction lock(_reader);
selectSigG();
logon(transportPin(), pin);
try {
logon(transportPin(), pin);
} catch (std::exception& x) {
throw wrong_pin(x.what());
}
}
/// Logon with SigG (Signaturgesetz) secure PIN
@ -1163,7 +1161,11 @@ namespace cardos {
CRYPTOLOG("log");
pcsc::Connection::Reader::Transaction lock(_reader);
selectSigG();
logon(sigGPin(), pin);
try {
logon(sigGPin(), pin);
} catch (std::exception& x) {
throw wrong_pin(x.what());
}
}
/// Logon with PKCS#15 user PUK to unlock user PIN
@ -1171,7 +1173,11 @@ namespace cardos {
CRYPTOLOG("log");
pcsc::Connection::Reader::Transaction lock(_reader);
selectMF();
logon(puk(), pin);
try {
logon(puk(), pin);
} catch (std::exception& x) {
throw wrong_puk(x.what());
}
}
/// Logon with PKCS#15 user PIN
@ -1179,7 +1185,11 @@ namespace cardos {
CRYPTOLOG("log");
pcsc::Connection::Reader::Transaction lock(_reader);
selectMF();
logon(pkcs15Pin(), pin);
try {
logon(pkcs15Pin(), pin);
} catch (std::exception& x) {
throw wrong_pin(x.what());
}
}
/// Change SigG (Signaturgesetz) secure PIN
@ -1187,7 +1197,7 @@ namespace cardos {
transport PIN and then the card is unlocked and the
transport state is unset. */
void changeSigGPin(std::string newPin, std::string oldPin) {
CRYPTOLOG("log");
CRYPTOLOG("log newPin=\""<<newPin<<"\" oldPin=\""<<oldPin<<"\"");
if (transportState()) { // first time use, reset transport state
pcsc::Connection::Reader::Transaction lock(_reader);
logonTransport(oldPin);
@ -1203,7 +1213,7 @@ namespace cardos {
/// Change PKCS#15 user PIN
void changePkcs15Pin(std::string newPin, std::string oldPin) {
CRYPTOLOG("log");
CRYPTOLOG("log newPin=\""<<newPin<<"\" oldPin=\""<<oldPin<<"\"");
pcsc::Connection::Reader::Transaction lock(_reader);
selectMF();
changeReferenceData(pkcs15Pin(), newPin, oldPin);
@ -1215,21 +1225,53 @@ namespace cardos {
change PIN on PKCS#15 and SigG from the same old PIN to the
same new PIN. */
void changePins(std::string newPin, std::string oldPin) {
CRYPTOLOG("log");
CRYPTOLOG("log newPin=\""<<newPin<<"\" oldPin=\""<<oldPin<<"\"");
pcsc::Connection::Reader::Transaction lock(_reader);
if (transportState()) {
if (transportState()) { // transport state
changeSigGPin(newPin, oldPin);
changePkcs15Pin(newPin, oldPin);
} else {
if (pkcs15PinRetries()!=-1) changePkcs15Pin(newPin, oldPin);
try {
if (sigGPinRetries()!=-1) changeSigGPin(newPin, oldPin);
if (pkcs15PinRetries()!=-1) { // normal pin change
changePkcs15Pin(newPin, oldPin);
try {
if (sigGPinRetries()!=-1) changeSigGPin(newPin, oldPin);
} catch (...) {
// undo PKCS#15 PIN change
if (pkcs15PinRetries()!=-1) changePkcs15Pin(oldPin, newPin);
throw;
}
} else if (pukRetries()==-1 && sigGPinRetries()!=-1) {
changeSigGPin(newPin, oldPin); // only valid sigg left
} else throw pin_locked();
}
}
/// Unlock PKCS#15 PIN using PUK
/** If the PIN is still the same as the old PIN was, SigG PIN
can be saved. If you have forgotten your SigG PIN, just use
@c force to completely break it. Otherwise PIN will first be
applied to SigG, if that works, PKCS#15 will be changed
accordingly. */
void unlock(std::string pin, std::string puk, bool force=false) {
CRYPTOLOG("log");
if (pkcs15PinRetries()!=-1) return; // all ok
if (pukRetries()==-1) throw pin_locked(); // too late, puk broken
logonPuk(puk);
CRYPTOLOG("PUK accepted");
while (sigGPinRetries()!=-1) try {
logonSigG(pin); // check SigG
CRYPTOLOG("SigG successfully checked");
break; // SigG still works
} catch (...) {
// undo PKCS#15 PIN change
if (pkcs15PinRetries()!=-1) changePkcs15Pin(oldPin, newPin);
throw;
CRYPTOLOG("SigG PIN failed");
if (!force) throw; // don't enforce, abort after one try
// otherwise break the SigG PUK now
// continue until SigG is broken
CRYPTOLOG("Force kill SigG");
}
}
selectMF();
changeReferenceData(pkcs15Pin(), pin);
CRYPTOLOG("Successfully restored PKCS#15 PIN");
}
/// Select a file in the PKCS#15 part on the smart card

@ -545,10 +545,10 @@ namespace suisseid {
}
/// install certificates on the card
/** @param reinstall whether to force reinstallation of existing
certificates
/** parameter @c bool whether to force reinstallation of existing
certificates
@return @c true on success */
virtual bool installCerts(bool reinstall = true) {
virtual bool installCerts(bool = true) {
CRYPTOLOG("log");
return false;
}
@ -617,7 +617,7 @@ namespace suisseid {
return pukLocked(), false;
PinPukChange pins(pinChangePuk());
if (!pins.valid()) return false;
_card->changePins(pins.newpin, pins.oldpin);
_card->unlock(pins.newpin, pins.oldpin);
return start();
}

Loading…
Cancel
Save