TokenData QPKCS11::selectSlot( const QString &card, SslCertificate::KeyUsage usage ) { delete d->pslot; d->pslot = 0; TokenData t; t.setCard( card ); for( unsigned int i = 0; i < d->nslots; ++i ) { CK_TOKEN_INFO token; if( (d->err = d->f->C_GetTokenInfo( d->pslots[i], &token )) != CKR_OK || card != QByteArray( (const char*)token.serialNumber, 16 ).trimmed() ) continue; SslCertificate cert = d->readCert( d->pslots[i] ); if( !cert.keyUsage().keys().contains( usage ) ) continue; d->pslot = new CK_SLOT_ID( d->pslots[i] ); t.setCert( cert ); if( token.flags & CKF_SO_PIN_COUNT_LOW || token.flags & CKF_USER_PIN_COUNT_LOW ) t.setFlag( TokenData::PinCountLow ); if( token.flags & CKF_SO_PIN_FINAL_TRY || token.flags & CKF_USER_PIN_FINAL_TRY ) t.setFlag( TokenData::PinFinalTry ); if( token.flags & CKF_SO_PIN_LOCKED || token.flags & CKF_USER_PIN_LOCKED ) t.setFlag( TokenData::PinLocked ); break; } return t; }
QPKCS11::PinStatus QPKCS11::login( const TokenData &_t ) { CK_TOKEN_INFO token; if( !d->pslot || (d->err = d->f->C_GetTokenInfo( *(d->pslot), &token )) != CKR_OK ) return PinUnknown; if( !(token.flags & CKF_LOGIN_REQUIRED) ) return PinOK; TokenData t = _t; if( token.flags & CKF_SO_PIN_COUNT_LOW || token.flags & CKF_USER_PIN_COUNT_LOW ) t.setFlag( TokenData::PinCountLow ); if( token.flags & CKF_SO_PIN_FINAL_TRY || token.flags & CKF_USER_PIN_FINAL_TRY ) t.setFlag( TokenData::PinFinalTry ); if( token.flags & CKF_SO_PIN_LOCKED || token.flags & CKF_USER_PIN_LOCKED ) t.setFlag( TokenData::PinLocked ); if( d->session ) d->err = d->f->C_CloseSession( d->session ); d->session = 0; if( (d->err = d->f->C_OpenSession( *(d->pslot), CKF_SERIAL_SESSION, 0, 0, &d->session )) != CKR_OK ) return PinUnknown; bool pin2 = SslCertificate( t.cert() ).keyUsage().keys().contains( SslCertificate::NonRepudiation ); if( token.flags & CKF_PROTECTED_AUTHENTICATION_PATH ) { PinDialog p( pin2 ? PinDialog::Pin2PinpadType : PinDialog::Pin1PinpadType, t, qApp->activeWindow() ); QPKCS11Thread t( d ); connect( &t, SIGNAL(started()), &p, SIGNAL(startTimer()) ); p.open(); d->err = t.waitForDone(); } else { PinDialog p( pin2 ? PinDialog::Pin2Type : PinDialog::Pin1Type, t, qApp->activeWindow() ); if( !p.exec() ) return PinCanceled; QByteArray pin = p.text().toUtf8(); d->err = d->f->C_Login( d->session, CKU_USER, (unsigned char*)pin.constData(), pin.size() ); } switch( d->err ) { case CKR_OK: return PinOK; case CKR_CANCEL: case CKR_FUNCTION_CANCELED: return PinCanceled; case CKR_PIN_INCORRECT: return PinIncorrect; case CKR_PIN_LOCKED: return PinLocked; default: return PinUnknown; } }