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; }
void QSigner::emitDataChanged() { TokenData data; data.setCard( d->selectedCard ); data.setCards( d->cards.keys() ); data.setCert( d->cert ); data.setFlags( d->flags ); Q_EMIT dataChanged( data ); }
TokenData QCSP::selectCert( const QString &cn, SslCertificate::KeyUsage usage ) { TokenData t; t.setCard( cn ); if( d->h ) CryptReleaseContext( d->h, 0 ); QPair<QString,QString> c = d->certs.value( cn ); if( !CryptAcquireContextW( &d->h, LPCWSTR(c.second.utf16()), LPCWSTR(c.first.utf16()), PROV_RSA_FULL, 0 ) ) return t; HCRYPTKEY key = 0; if( !CryptGetUserKey( d->h, usage == SslCertificate::NonRepudiation ? AT_SIGNATURE : AT_KEYEXCHANGE, &key ) ) return t; SslCertificate cert = QSslCertificate( d->keyParam( key, KP_CERTIFICATE, 0 ), QSsl::Der ); CryptDestroyKey( key ); if( cert.keyUsage().keys().contains( usage ) ) t.setCert( cert ); return t; }
bool AccessCert::download( bool noCard ) { if( noCard ) { QDesktopServices::openUrl( QUrl( tr("http://www.sk.ee/toend/") ) ); return false; } SslCertificate tempel( qApp->signer()->tokensign().cert() ); if( tempel.type() & SslCertificate::TempelType ) { setIcon( Information ); setText( tr("For getting server access certificate to Tempel contact <a href=\"mailto:[email protected]\">[email protected]</a>") ); return false; } setIcon( Information ); setText( tr("Hereby I agree to terms and conditions of validity confirmation service and " "will use the service in extent of 10 signatures per month. If you going to " "exceed the limit of 10 signatures per month or/and will use the service for " "commercial purposes, please refer to IT support of your company. Additional " "information is available from <a href=\"%1\">%1</a> or phone 1777") .arg( tr("http://www.id.ee/kehtivuskinnitus") ) ); setStandardButtons( Help ); QPushButton *agree = addButton( tr("Agree"), AcceptRole ); if( exec() == Help ) { QDesktopServices::openUrl( QUrl( tr("http://www.id.ee/kehtivuskinnitus") ) ); return false; } removeButton( agree ); QSigner *s = qApp->signer(); QPKCS11 *p = qobject_cast<QPKCS11*>(reinterpret_cast<QObject*>(s->handle())); #ifdef Q_OS_WIN QCNG *c = qobject_cast<QCNG*>(reinterpret_cast<QObject*>(s->handle())); if( !p && !c ) return false; #endif s->lock(); Qt::HANDLE key = 0; TokenData token; if( p ) { bool retry = false; do { retry = false; token.setCard( s->tokensign().card() ); Q_FOREACH( const TokenData &t, p->tokens() ) if( token.card() == t.card() && SslCertificate( t.cert() ).enhancedKeyUsage().contains( SslCertificate::ClientAuth ) ) token.setCert( t.cert() ); QPKCS11::PinStatus status = p->login( token ); switch( status ) { case QPKCS11::PinOK: break; case QPKCS11::PinCanceled: s->unlock(); return false; case QPKCS11::PinIncorrect: showWarning( QPKCS11::errorString( status ) ); retry = true; break; default: showWarning( tr("Error downloading server access certificate!") + "\n" + QPKCS11::errorString( status ) ); s->unlock(); return false; } } while( retry ); key = p->key(); } else {
QList<TokenData> QCNG::tokens() const { qWarning() << "Start enumerationg providers"; QHash<SslCertificate,QCNGCache> cache; DWORD count = 0; NCryptProviderName *names = nullptr; NCryptEnumStorageProviders( &count, &names, NCRYPT_SILENT_FLAG ); for( DWORD i = 0; i < count; ++i ) { qWarning() << "Found provider" << QString::fromWCharArray(names[i].pszName); if( wcscmp( names[i].pszName, MS_SMART_CARD_KEY_STORAGE_PROVIDER ) == 0 ) { for( const QString &reader: QPCSC::instance().readers() ) { qWarning() << reader; QString scope = QString(R"(\\.\%1\)").arg(reader); d->enumKeys( cache, names[i].pszName, LPCWSTR(scope.utf16()) ); } } else d->enumKeys( cache, names[i].pszName ); } NCryptFreeBuffer( names ); d->cache = cache; qWarning() << "End enumerationg providers"; QList<TokenData> result; for(QHash<SslCertificate,QCNGCache>::const_iterator i = cache.constBegin(); i != cache.constEnd(); ++i) { TokenData t; t.setCard(i.key().type() & SslCertificate::EstEidType || i.key().type() & SslCertificate::DigiIDType ? i.value().guid : i.key().subjectInfo(QSslCertificate::CommonName)); t.setCert(i.key()); result << t; } return result; } TokenData QCNG::selectCert( const SslCertificate &cert ) { qWarning() << "Select:" << cert.subjectInfo( "CN" ); if( !d->cache.contains( cert ) ) return TokenData(); d->selected = d->cache[cert]; qWarning() << "Found:" << d->selected.guid << d->selected.key; TokenData t; t.setCard( cert.type() & SslCertificate::EstEidType || cert.type() & SslCertificate::DigiIDType ? d->selected.guid : cert.subjectInfo( QSslCertificate::CommonName ) ); t.setCert( cert ); return t; } QByteArray QCNG::sign( int method, const QByteArray &digest ) const { d->err = PinUnknown; BCRYPT_PKCS1_PADDING_INFO padInfo = { NCRYPT_SHA256_ALGORITHM }; switch( method ) { case NID_sha224: padInfo.pszAlgId = L"SHA224"; break; case NID_sha256: padInfo.pszAlgId = NCRYPT_SHA256_ALGORITHM; break; case NID_sha384: padInfo.pszAlgId = NCRYPT_SHA384_ALGORITHM; break; case NID_sha512: padInfo.pszAlgId = NCRYPT_SHA512_ALGORITHM; break; case NID_md5_sha1: //padInfo.pszAlgId = L"SHAMD5"; break; default: break; } DWORD size = 0; QByteArray res; NCRYPT_KEY_HANDLE k = d->key(); QString algo(5, 0); SECURITY_STATUS err = NCryptGetProperty(k, NCRYPT_ALGORITHM_GROUP_PROPERTY, PBYTE(algo.data()), DWORD((algo.size() + 1) * 2), &size, 0); algo.resize(size/2 - 1); bool isRSA = algo == "RSA"; err = NCryptSignHash(k, isRSA ? &padInfo : nullptr, PBYTE(digest.constData()), DWORD(digest.size()), nullptr, 0, &size, isRSA ? BCRYPT_PAD_PKCS1 : 0); if(FAILED(err)) return res; res.resize(int(size)); err = NCryptSignHash(k, isRSA ? &padInfo : nullptr, PBYTE(digest.constData()), DWORD(digest.size()), PBYTE(res.data()), DWORD(res.size()), &size, isRSA ? BCRYPT_PAD_PKCS1 : 0); NCryptFreeObject( k ); switch( err ) { case ERROR_SUCCESS: d->err = PinOK; return res; case SCARD_W_CANCELLED_BY_USER: d->err = PinCanceled; break; default: res.clear(); break; } return res; }