diff options
Diffstat (limited to 'unittest')
m--------- | unittest/Catch | 0 | ||||
-rw-r--r-- | unittest/Makefile | 33 | ||||
l--------- | unittest/build/libnitrokey.so | 1 | ||||
-rw-r--r-- | unittest/test.cc | 80 | ||||
-rw-r--r-- | unittest/test_HOTP.cc | 101 |
5 files changed, 215 insertions, 0 deletions
diff --git a/unittest/Catch b/unittest/Catch new file mode 160000 +Subproject ae5ee2cf63d6d67bd1369b512d2a7b60b571c90 diff --git a/unittest/Makefile b/unittest/Makefile new file mode 100644 index 0000000..aa9d53a --- /dev/null +++ b/unittest/Makefile @@ -0,0 +1,33 @@ +CC = $(PREFIX)-gcc +#CXX = $(PREFIX)-g++ +CXX = clang++-3.6 +LD = $(CXX) + +INCLUDE = -I../include -ICatch/single_include/ +LIB = -L../build +LDLIBS = -lnitrokey +BUILD = build + +CXXFLAGS = -std=c++14 -fPIC + +CXXSOURCES = $(wildcard *.cc) +TARGETS = $(CXXSOURCES:%.cc=$(BUILD)/%) +DEPENDS = $(CXXSOURCES:%.cc=$(BUILD)/%.d) + +$(BUILD)/%.d: %.cc + $(CXX) -M $< -o $@ $(INCLUDE) $(CXXFLAGS) + +$(BUILD)/%: %.cc $(DEPENDS) + $(CXX) $< -o $@ $(INCLUDE) $(LIB) $(CXXFLAGS) $(LDLIBS) + +all: $(TARGETS) + +clean: + rm -f $(TARGETS) + +mrproper: clean + rm -f $(BUILD)/*.d + +.PHONY: all clean mrproper + +include $(wildcard build/*.d) diff --git a/unittest/build/libnitrokey.so b/unittest/build/libnitrokey.so new file mode 120000 index 0000000..69a5e22 --- /dev/null +++ b/unittest/build/libnitrokey.so @@ -0,0 +1 @@ +../../build/libnitrokey.so
\ No newline at end of file diff --git a/unittest/test.cc b/unittest/test.cc new file mode 100644 index 0000000..02f742c --- /dev/null +++ b/unittest/test.cc @@ -0,0 +1,80 @@ +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() +#include "catch.hpp" + +#include <iostream> +#include <string.h> +#include "device_proto.h" +#include "log.h" +#include "stick10_commands.h" + +using namespace std; +using namespace nitrokey::device; +using namespace nitrokey::proto::stick10; +using namespace nitrokey::log; + +std::string getSlotName(Stick10 &stick, int slotNo) { + ReadSlot::CommandTransaction::CommandPayload slot_req; + slot_req.slot_number = slotNo; + auto slot = ReadSlot::CommandTransaction::run(stick, slot_req); + std::string sName(reinterpret_cast<char *>(slot.slot_name)); + return sName; +} + +TEST_CASE("Slot names are correct", "[slotNames]") { + Stick10 stick; + bool connected = stick.connect(); + REQUIRE(connected == true); + + Log::instance().set_loglevel(Loglevel::DEBUG); + + auto resp = GetStatus::CommandTransaction::run(stick); + + FirstAuthenticate::CommandTransaction::CommandPayload authreq; + strcpy((char *)(authreq.card_password), "12345678"); + FirstAuthenticate::CommandTransaction::run(stick, authreq); + + { + EnablePasswordSafe::CommandTransaction::CommandPayload authreq; + strcpy((char *)(authreq.password), "123456"); + EnablePasswordSafe::CommandTransaction::run(stick, authreq); + } + + REQUIRE(getSlotName(stick, 0x20) == std::string("1")); + REQUIRE(getSlotName(stick, 0x21) == std::string("slot2")); + + { + auto resp = GetPasswordRetryCount::CommandTransaction::run(stick); + REQUIRE(resp.password_retry_count == 3); + } + { + auto resp = GetUserPasswordRetryCount::CommandTransaction::run(stick); + REQUIRE(resp.password_retry_count == 3); + } + + { + GetPasswordSafeSlotName::CommandTransaction::CommandPayload slot; + slot.slot_number = 0; + auto resp2 = GetPasswordSafeSlotName::CommandTransaction::run(stick, slot); + std::string sName(reinterpret_cast<char *>(resp2.slot_name)); + REQUIRE(sName == std::string("web1")); + } + + { + GetPasswordSafeSlotPassword::CommandTransaction::CommandPayload slot; + slot.slot_number = 0; + auto resp2 = + GetPasswordSafeSlotPassword::CommandTransaction::run(stick, slot); + std::string sName(reinterpret_cast<char *>(resp2.slot_password)); + REQUIRE(sName == std::string("pass1")); + } + + { + GetPasswordSafeSlotLogin::CommandTransaction::CommandPayload slot; + slot.slot_number = 0; + auto resp2 = GetPasswordSafeSlotLogin::CommandTransaction::run(stick, slot); + std::string sName(reinterpret_cast<char *>(resp2.slot_login)); + REQUIRE(sName == std::string("login1")); + } + + stick.disconnect(); +} diff --git a/unittest/test_HOTP.cc b/unittest/test_HOTP.cc new file mode 100644 index 0000000..b263693 --- /dev/null +++ b/unittest/test_HOTP.cc @@ -0,0 +1,101 @@ +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() +#include "catch.hpp" + +#include <iostream> +//#include <string.h> +#include "device_proto.h" +#include "log.h" +#include "stick10_commands.h" +#include <cstdlib> + +using namespace std; +using namespace nitrokey::device; +using namespace nitrokey::proto::stick10; +using namespace nitrokey::log; + +void hexStringToByte(uint8_t data[], const char* hexString){ + assert(strlen(hexString)%2==0); + char buf[2]; + for(int i=0; i<strlen(hexString); i++){ + buf[i%2] = hexString[i]; + if (i%2==1){ + data[i/2] = strtoul(buf, NULL, 16) & 0xFF; + } + } +}; + +TEST_CASE("test secret", "[functions]") { + uint8_t slot_secret[21]; + slot_secret[20] = 0; + const char* secretHex = "3132333435363738393031323334353637383930"; + hexStringToByte(slot_secret, secretHex); + CAPTURE(slot_secret); + REQUIRE(strcmp("12345678901234567890",reinterpret_cast<char *>(slot_secret) ) == 0 ); +} + +TEST_CASE("Test HOTP codes according to RFC", "[HOTP]") { + Stick10 stick; + bool connected = stick.connect(); + + REQUIRE(connected == true); + + Log::instance().set_loglevel(Loglevel::DEBUG); + + auto resp = GetStatus::CommandTransaction::run(stick); + + const char * temporary_password = "123456789012345678901234"; + { + FirstAuthenticate::CommandTransaction::CommandPayload authreq; + strcpy((char *)(authreq.card_password), "12345678"); + strcpy((char *)(authreq.temporary_password), temporary_password); + FirstAuthenticate::CommandTransaction::run(stick, authreq); + } + + //test according to https://tools.ietf.org/html/rfc4226#page-32 + { + WriteToHOTPSlot::CommandTransaction::CommandPayload hwrite; + hwrite.slot_number = 0x10; + strcpy(reinterpret_cast<char *>(hwrite.slot_name), "rfc4226_lib"); + //strcpy(reinterpret_cast<char *>(hwrite.slot_secret), ""); + const char* secretHex = "3132333435363738393031323334353637383930"; + hexStringToByte(hwrite.slot_secret, secretHex); + //hwrite.slot_config; //TODO check various configs in separate test cases + //strcpy(reinterpret_cast<char *>(hwrite.slot_token_id), ""); + //strcpy(reinterpret_cast<char *>(hwrite.slot_counter), ""); + + //authorize writehotp first + { + Authorize::CommandTransaction::CommandPayload auth; + strcpy((char *)(auth.temporary_password), temporary_password); + auth.crc_to_authorize = WriteToHOTPSlot::CommandTransaction::getCRC(hwrite); + Authorize::CommandTransaction::run(stick, auth); + } + + //run hotp command + WriteToHOTPSlot::CommandTransaction::run(stick, hwrite); + + uint32_t codes[] = { + 755224, 287082, 359152, 969429, 338314, + 254676, 287922, 162583, 399871, 520489 + }; + + for( auto code: codes){ + GetHOTP::CommandTransaction::CommandPayload gh; + gh.slot_number = 0x10; + auto resp = GetHOTP::CommandTransaction::run(stick, gh); + REQUIRE( resp.code == code); + } + //checking slot programmed before with nitro-app + /* + for( auto code: codes){ + GetHOTP::CommandTransaction::CommandPayload gh; + gh.slot_number = 0x12; + auto resp = GetHOTP::CommandTransaction::run(stick, gh); + REQUIRE( resp.code == code); + } + */ + } + + + stick.disconnect(); +} |