TestYkChallengeResponseKey.cpp 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright (C) 2014 Kyle Manna <kyle@kylemanna.com>
  3. * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
  4. *
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 or (at your option)
  9. * version 3 of the License.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "TestYkChallengeResponseKey.h"
  20. #include "core/Tools.h"
  21. #include "crypto/Crypto.h"
  22. #include "keys/ChallengeResponseKey.h"
  23. #include <QCryptographicHash>
  24. #include <QSignalSpy>
  25. #include <QTest>
  26. QTEST_GUILESS_MAIN(TestYubiKeyChallengeResponse)
  27. void TestYubiKeyChallengeResponse::initTestCase()
  28. {
  29. // crypto subsystem needs to be initialized for YubiKey testing
  30. QVERIFY(Crypto::init());
  31. if (!YubiKey::instance()->isInitialized()) {
  32. QSKIP("Unable to initialize YubiKey interface.");
  33. }
  34. }
  35. void TestYubiKeyChallengeResponse::testDetectDevices()
  36. {
  37. YubiKey::instance()->findValidKeys();
  38. // Look at the information retrieved from the key(s)
  39. const auto foundKeys = YubiKey::instance()->foundKeys();
  40. for (auto i = foundKeys.cbegin(); i != foundKeys.cend(); ++i) {
  41. const auto& displayName = i.value();
  42. QVERIFY(displayName.contains("Challenge-Response - Slot") || displayName.contains("Configured Slot -"));
  43. QVERIFY(displayName.contains(QString::number(i.key().first)));
  44. QVERIFY(displayName.contains(QString::number(i.key().second)));
  45. }
  46. }
  47. /**
  48. * Secret key for the YubiKey slot used by the unit test is
  49. * 1c e3 0f d7 8d 20 dc fa 40 b5 0c 18 77 9a fb 0f 02 28 8d b7
  50. * This secret can be on either slot but must be passive.
  51. */
  52. void TestYubiKeyChallengeResponse::testKeyChallenge()
  53. {
  54. auto keys = YubiKey::instance()->foundKeys().keys();
  55. if (keys.isEmpty()) {
  56. QSKIP("No YubiKey devices were detected.");
  57. }
  58. // Find a key that is configured in passive mode
  59. bool wouldBlock = false;
  60. YubiKeySlot pKey(0, 0);
  61. for (auto key : keys) {
  62. if (YubiKey::instance()->testChallenge(key, &wouldBlock) && !wouldBlock) {
  63. pKey = key;
  64. break;
  65. }
  66. Tools::wait(100);
  67. }
  68. if (pKey.first == 0) {
  69. /* Testing active mode in unit tests is unreasonable */
  70. QSKIP("No YubiKey contains a slot in passive mode.");
  71. }
  72. QScopedPointer<ChallengeResponseKey> key(new ChallengeResponseKey(pKey));
  73. QByteArray ba("UnitTest");
  74. QVERIFY(key->challenge(ba));
  75. QCOMPARE(key->rawKey().size(), 20);
  76. auto hash = QString(QCryptographicHash::hash(key->rawKey(), QCryptographicHash::Sha256).toHex());
  77. QCOMPARE(hash, QString("2f7802c7112c301303526e7737b54d546c905076dca6e9538edf761a2264cd70"));
  78. }