|
|
|
@ -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(); |
|
|
|
|
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(); |
|
|
|
|
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(); |
|
|
|
|
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(); |
|
|
|
|
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,13 +1225,14 @@ 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); |
|
|
|
|
if (pkcs15PinRetries()!=-1) { // normal pin change
|
|
|
|
|
changePkcs15Pin(newPin, oldPin); |
|
|
|
|
try { |
|
|
|
|
if (sigGPinRetries()!=-1) changeSigGPin(newPin, oldPin); |
|
|
|
|
} catch (...) { |
|
|
|
@ -1229,7 +1240,38 @@ namespace cardos { |
|
|
|
|
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 (...) { |
|
|
|
|
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
|
|
|
|
|