diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a0d3790 --- /dev/null +++ b/Makefile @@ -0,0 +1,85 @@ +SRCDIR=. +PKGCONFIG=pkg-config + +SRC:= \ + $(SRCDIR)/crc32.c \ + $(SRCDIR)/device.c \ + $(SRCDIR)/operations.c \ + $(SRCDIR)/dev_commands.c \ + $(SRCDIR)/base32.c \ + $(SRCDIR)/random_data.c \ + $(SRCDIR)/min.c \ + $(SRCDIR)/version.c \ + $(SRCDIR)/return_codes.c \ + $(SRCDIR)/main.c + +SRC += \ + $(SRCDIR)/hidapi/libusb/hid.c + +HEADERS := \ + $(SRCDIR)/crc32.h \ + $(SRCDIR)/structs.h \ + $(SRCDIR)/device.h \ + $(SRCDIR)/operations.h \ + $(SRCDIR)/dev_commands.h \ + $(SRCDIR)/base32.h \ + $(SRCDIR)/command_id.h \ + $(SRCDIR)/random_data.h \ + $(SRCDIR)/min.h \ + $(SRCDIR)/settings.h \ + $(SRCDIR)/version.h \ + $(SRCDIR)/return_codes.h \ + + +OBJS := ${SRC:.c=.o} + +HIDAPI_INC=hidapi +INC:= \ + -I$(SRCDIR) \ + -I$(HIDAPI_INC) \ + -I$(HIDAPI_INC)/hidapi \ + +LIBUSB_FLAGS=$(shell $(PKGCONFIG) --cflags libusb-1.0) +LIBUSB_LIB=$(shell $(PKGCONFIG) --libs libusb-1.0) + +CFLAGS= -Wall -Wextra -fno-guess-branch-probability -Wdate-time -frandom-seed=42 -O2 -gno-record-gcc-switches -DNDEBUG -fdebug-prefix-map=${PWD}=heads -c -std=gnu11 -DNK_REMOVE_PTHREAD $(LIBUSB_FLAGS) + +OUTDIR= +OUT=nitrokey_hotp_verification +OUT2=libremkey_hotp_verification +LDFLAGS=$(LIBUSB_LIB) + +all: $(OUT) $(OUT2) + ls -lh $^ + sha256sum $^ + +clean: + -rm $(OBJS) $(OUT) version.c + +$(OUT2): $(OUT) + cp $< $@ + +$(OUT): $(OBJS) + $(CC) $^ $(LDFLAGS) -o $@ + +%.o: %.c + $(CC) $(CFLAGS) $(INC) -o $@ $< + +GITVERSION=$(shell git describe) +$(SRCDIR)/version.c: $(SRCDIR)/version.c.in + sed "s!@GIT_VERSION_PLACEHOLDER@!$(GITVERSION)!g" < $< >$@ + +.PRECIOUS: %.o + +INSTALL=/usr/local/ +.PHONY: install +install: + cp -v $(OUT) $(OUT2) $(INSTALL)/bin + +.PHONY: github_sha +GVER=$(shell git rev-parse HEAD) +libremkey_url := https://github.com/Nitrokey/nitrokey-hotp-verification/archive/$(GVER).tar.gz +github_sha: + wget -c $(libremkey_url) + sha256sum $(GVER).tar.gz + @echo $(GVER) \ No newline at end of file diff --git a/Makefile-repro.mk b/Makefile-repro.mk index c04906d..58ac730 100644 --- a/Makefile-repro.mk +++ b/Makefile-repro.mk @@ -14,20 +14,23 @@ repro-build-ubuntu: sudo docker build -f Dockerfile.ubuntu . -t nhv-u # BUILDCMD=cmake -DUSE_SYSTEM_HIDAPI=OFF # failing (for tests) -BUILDCMD=cmake -DCMAKE_C_FLAGS=-fdebug-prefix-map=$(PWD)=heads -gno-record-gcc-switches -DADD_GIT_INFO=OFF -DCMAKE_BUILD_TYPE=Release +BUILDCMD=cmake -DCMAKE_C_FLAGS=-fdebug-prefix-map=$(PWD)=heads -gno-record-gcc-switches -DADD_GIT_INFO=OFF -DCMAKE_BUILD_TYPE=Release .. BUILD1=$(BUILDCMD) -DUSE_SYSTEM_HIDAPI=ON BUILD2=$(BUILDCMD) -DUSE_SYSTEM_HIDAPI=OFF #USERNS=bash -c "echo 1 > /proc/sys/kernel/unprivileged_userns_clone" && REPROTEST=env PYTHONIOENCODING=utf-8 reprotest --min-cpus 2 -CMD1=$(USERNS) $(REPROTEST) "cd build && $(BUILD1) .. && make clean && make" build/libremkey_hotp_verification -CMD2=$(USERNS) $(REPROTEST) "cd build && $(BUILD2) .. && make clean && make" build/libremkey_hotp_verification +BINARY=build/libremkey_hotp_verification +BEXEC=make clean && make +CMD1=$(USERNS) $(REPROTEST) "cd build && $(BUILD1) && $(BEXEC)" +CMD2=$(USERNS) $(REPROTEST) "cd build && $(BUILD2) && $(BEXEC)" TEE=| tee -a log.txt repro-run: mkdir -p build + rm -rf ./build/* echo > log.txt - sudo docker run -it --privileged -v $(PWD):/app nhv-u $(CMD1) $(TEE) - sudo docker run -it --privileged -v $(PWD):/app nhv-u $(CMD2) $(TEE) - sudo docker run -it --privileged -v $(PWD):/app nhv-f $(CMD1) $(TEE) - sudo docker run -it --privileged -v $(PWD):/app nhv-f $(CMD2) $(TEE) + sudo docker run -it --privileged -v $(PWD):/app nhv-u $(CMD1) $(BINARY) $(TEE) + sudo docker run -it --privileged -v $(PWD):/app nhv-u $(CMD2) $(BINARY) $(TEE) + sudo docker run -it --privileged -v $(PWD):/app nhv-f $(CMD1) $(BINARY) $(TEE) + sudo docker run -it --privileged -v $(PWD):/app nhv-f $(CMD2) $(BINARY) $(TEE) @echo finished with success grep "./build/libremkey_hotp_verification" log.txt | sort -u diff --git a/README.md b/README.md index 403eaf6..f557d09 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ This tool also reads from `/dev/urandom` to generate session secret for device-a The Nitrokey device needs to support HOTP verification. ## Compilation -This tool uses CMake for compilation. Please run: + +### CMake +This tool uses CMake for compilation as its main driver. Please run: ```bash mkdir build && cd build @@ -44,6 +46,27 @@ Example compilation flags use: cmake .. -DADD_GIT_INFO=OFF -DCMAKE_BUILD_TYPE=Release ``` +### Makefile +To support reproducible build within Heads, additional build method using Gnu Make was added. To run: + +```bash +make +``` + +- At the moment `hidapi` library will always be bundled statically. +- It is possible to provide `libusb` flags with `LIBUSB_FLAGS` and `LIBUSB_LIB`, otherwise it will be taken from the `pkg-config`. +- Cross-compilation can be achieved overwriting standard build variables. +- To disable embedding Git version it suffices to set `GITVERSION` to none. +- Additional helper command was added to quickly compute SHA256 sum for Heads inclusion, and could be executed with `make github_sha`. + + +### Meson +Meson was added as a backup method in case, when build reproducibility could not be achieved with Gnu Makefile. It is not configurable. Usage: +```bash +meson builddir +cd builddir && ninja +``` + ## Usage Before each device-related command a connection attempt will be done. If the Nitrokey Pro will not be detected immediately, the tool will monit for its insertion and will wait for 40 seconds (probing each 0.5s), quitting if connection would not be possible. @@ -164,5 +187,15 @@ Tests could be run selectively - see `--help` switch to learn more. #### Size In a Release build, with statically linked HIDAPI, application takes 50kB of storage (42kB stripped). +#### Build reproducibility +Build reproducibility was tested with Repro-test tool. Docker files for Ubuntu and Fedora are provided for tests on both systems. See https://reproducible-builds.org/ for more details. +Following commands will build Docker environments, execute tool builds and show final SHA256 hashes of the binaries: +```bash +make -f Makefile-repro.mk repro-build +make -f Makefile-repro.mk repro-run +``` + + + ## License Code is licensed under GPLv3, excluding `base32.{h,c}` files. The latter are downloaded from [tpmtopt](https://github.com/osresearch/tpmtotp) project and seem to be licensed under [MIT](https://choosealicense.com/licenses/mit/) license. \ No newline at end of file diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..3cc83f3 --- /dev/null +++ b/meson.build @@ -0,0 +1,58 @@ +project('hotp-verification', 'c', + version : '1.1.0', +) +lusb = dependency('libusb-1.0') + +src = [ +'crc32.c', +'device.c', +'operations.c', +'dev_commands.c', +'base32.c', +'random_data.c', +'min.c', +'version.c', +'return_codes.c', +'main.c', +'hidapi/libusb/hid.c' +] + +version_array = meson.project_version().split('.') +version_major = version_array[0].to_int() +version_minor = version_array[1].to_int() +version_data = configuration_data() +version_data.set('PROJECT_VERSION_MAJOR', version_major) +version_data.set('PROJECT_VERSION_MINOR', version_minor) +# We don't want to substitute it by noop +version_data.set('GIT_VERSION_PLACEHOLDER', '@VCS_TAG@') +version_cc_in = configure_file( + input : 'version.c.in', + output : 'version.c.in', + configuration : version_data, +) +version_cc = vcs_tag( + input : version_cc_in, + output : 'version.c', + fallback : 'v@0@'.format(meson.project_version()), +) + +common_flags = [ +'-DNK_REMOVE_PTHREAD', +'-fdebug-prefix-map=$PWD=heads', +'-gno-record-gcc-switches', +'-DNDEBUG', +'-fno-guess-branch-probability', +'-Wdate-time', +'-frandom-seed=0x42', +'-O0', +] + +incdir = ([ +include_directories('.'), +include_directories('hidapi/hidapi'), +]) + +name1 = 'nitrokey-hotp-verification' +name2 = 'libremkey-hotp-verification' +executable(name1, src, dependencies : lusb, include_directories: incdir, c_args: common_flags) +executable(name2, src, dependencies : lusb, include_directories: incdir, c_args: common_flags) \ No newline at end of file