Both slots on Yubikey are now polled for challenge/response

This commit is contained in:
Jonathan White 2017-10-07 21:25:42 -04:00 committed by Jonathan White
parent 2e81751131
commit 3bc8a79b9b
4 changed files with 56 additions and 19 deletions

View File

@ -70,9 +70,6 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey()));
connect(m_ui->comboChallengeResponse, SIGNAL(activated(int)), SLOT(activateChallengeResponse()));
connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection);
connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection);
#else
m_ui->checkChallengeResponse->setVisible(false);
m_ui->buttonRedetectYubikey->setVisible(false);
@ -98,10 +95,24 @@ void DatabaseOpenWidget::showEvent(QShowEvent* event)
m_ui->editPassword->setFocus();
#ifdef WITH_XC_YUBIKEY
connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection);
connect(YubiKey::instance(), SIGNAL(detectComplete()), SLOT(yubikeyDetectComplete()), Qt::QueuedConnection);
connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection);
pollYubikey();
#endif
}
void DatabaseOpenWidget::hideEvent(QHideEvent* event)
{
DialogyWidget::hideEvent(event);
#ifdef WITH_XC_YUBIKEY
// Don't listen to any Yubikey events if we are hidden
disconnect(YubiKey::instance(), 0, this, 0);
#endif
}
void DatabaseOpenWidget::load(const QString& filename)
{
m_filename = filename;
@ -283,10 +294,6 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking)
YkChallengeResponseKey yk(slot, blocking);
// add detected YubiKey to combo box and encode blocking mode in LSB, slot number in second LSB
m_ui->comboChallengeResponse->addItem(yk.getName(), QVariant((slot << 1) | blocking));
m_ui->comboChallengeResponse->setEnabled(true);
m_ui->checkChallengeResponse->setEnabled(true);
m_ui->buttonRedetectYubikey->setEnabled(true);
m_ui->yubikeyProgress->setVisible(false);
if (config()->get("RememberLastKeyFiles").toBool()) {
QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash();
@ -296,6 +303,14 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking)
}
}
void DatabaseOpenWidget::yubikeyDetectComplete()
{
m_ui->comboChallengeResponse->setEnabled(true);
m_ui->checkChallengeResponse->setEnabled(true);
m_ui->buttonRedetectYubikey->setEnabled(true);
m_ui->yubikeyProgress->setVisible(false);
}
void DatabaseOpenWidget::noYubikeyFound()
{
m_ui->buttonRedetectYubikey->setEnabled(true);

View File

@ -51,6 +51,7 @@ signals:
protected:
void showEvent(QShowEvent* event) override;
void hideEvent(QHideEvent* event) override;
CompositeKey databaseKey();
protected slots:
@ -63,6 +64,7 @@ private slots:
void activateChallengeResponse();
void browseKeyFile();
void yubikeyDetected(int slot, bool blocking);
void yubikeyDetectComplete();
void noYubikeyFound();
protected:

View File

@ -25,6 +25,7 @@
#include <ykdef.h>
#include <ykstatus.h>
#include "core/Tools.h"
#include "core/Global.h"
#include "crypto/Random.h"
@ -112,23 +113,36 @@ bool YubiKey::deinit()
void YubiKey::detect()
{
if (init()) {
for (int i = 1; i < 3; i++) {
YubiKey::ChallengeResult result;
QByteArray rand = randomGen()->randomArray(1);
QByteArray resp;
bool found = false;
if (init()) {
YubiKey::ChallengeResult result;
QByteArray rand = randomGen()->randomArray(1);
QByteArray resp;
// Check slot 1 and 2 for Challenge-Response HMAC capability
for (int i = 1; i <= 2; ++i) {
result = challenge(i, false, rand, resp);
if (result == YubiKey::ALREADY_RUNNING) {
emit alreadyRunning();
return;
} else if (result != YubiKey::ERROR) {
emit detected(i, result == YubiKey::WOULDBLOCK);
return;
if (result == ALREADY_RUNNING) {
// Try this slot again after waiting
Tools::sleep(300);
result = challenge(i, false, rand, resp);
}
if (result != ALREADY_RUNNING && result != ERROR) {
emit detected(i, result == WOULDBLOCK);
found = true;
}
// Wait between slots to let the yubikey settle
Tools::sleep(150);
}
}
emit notFound();
if (!found) {
emit notFound();
} else {
emit detectComplete();
}
}
bool YubiKey::getSerial(unsigned int& serial)
@ -160,6 +174,7 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte
}
// yk_challenge_response() insists on 64 byte response buffer */
response.clear();
response.resize(64);
/* The challenge sent to the yubikey should always be 64 bytes for

View File

@ -87,6 +87,11 @@ signals:
*/
void detected(int slot, bool blocking);
/**
* Emitted when detection is complete
*/
void detectComplete();
/**
* Emitted when the YubiKey was challenged and has returned a response.
*/