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(); +} | 
