CC=gcc
AR=ar rcs
CFLAGS=
CPPFLAGS=-std=c99 -O3 -I$(CURDIR)/lib/include -L$(CURDIR)/lib/lib

DEBUG=
ifdef DEBUG
	CPPFLAGS+=-g -O0
endif

CKA=frodo640c
PRGF=hkdf
PRG=prf
AEAD=aes128siv

KEM=frodo640
HKDF=sha256
HMAC=sha256
PRF=sha256
SKE=aes128cbc

objs=obj/sh.o obj/signal.o obj/cka/$(CKA).o obj/prgf/$(PRGF).o obj/prg/$(PRG).o obj/aead/$(AEAD).o
libs=-lbotan-2

ifeq ($(CKA), kem)
	objs+=obj/kem/$(KEM).o
	ifeq ($(KEM), frodo640)
		objs+=lib/lib/libfrodo640.a
	else ifeq ($(KEM), frodo976)
		objs+=lib/lib/libfrodo976.a
	else ifeq ($(KEM), frodo1344)
		objs+=lib/lib/libfrodo1344.a
	endif
endif
ifeq ($(PRGF), hkdf)
	objs+=obj/hkdf/$(HKDF).o
endif
ifeq ($(PRG), prf)
	objs+=obj/prf/$(PRF).o
endif
ifeq ($(AEAD), ske-hmac)
	objs+=obj/ske/$(SKE).o
	objs+=obj/hmac/$(HMAC).o
endif
ifeq ($(HKDF), hmac)
	objs+=obj/hmac/$(HMAC).o
endif

OS=$(shell uname -s)
ARCH=$(shell uname -m)
ifeq ($(OS), Darwin)
	CC=clang
endif

FRODO_GENERIC=
FRODO_OPT_LEVEL=FAST
FRODO_OPT_FLAGS=-mavx2 -maes -msse2
FRODO_OPT_OBJS=lib/libfrodo/objs/aes/aes_ni.o
ifdef FRODO_GENERIC
	FRODO_OPT_LEVEL=FAST_GENERIC
	FRODO_OPT_FLAGS=
	FRODO_OPT_OBJS=
endif

.PHONY: \
	all \
	libbotan libfrodo libs \
	test \
	clean distclean

all: obj/test

obj/cka/frodo%c.o: src/cka/frodo%c.c src/cka/_frodoc.c src/_frodo_patch.c src/_frodo_patch_0.c src/_frodo_patch_1.c src/cka.h src/bytes.h
	@ mkdir -p obj/cka
	$(CC) -c \
		-DNIX \
		-D_AMD64_ \
		-D_$(FRODO_OPT_LEVEL)_ $(FRODO_OPT_FLAGS) \
		-D_AES128_FOR_A_ \
		$(CPPFLAGS) $(CFLAGS) $< -o $@.o
	$(AR) $@ $@.o \
		lib/libfrodo/objs/util.o \
		lib/libfrodo/objs/random/random.o \
		lib/libfrodo/objs/aes/aes.o \
		lib/libfrodo/objs/aes/aes_c.o \
		lib/libfrodo/objs/sha3/fips202.o \
		$(FRODO_OPT_OBJS)
obj/cka/%.o: src/cka/%.c src/cka.h src/bytes.h
	@ mkdir -p obj/cka
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/prgf/%.o: src/prgf/%.c src/prgf.h src/bytes.h
	@ mkdir -p obj/prgf
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/prg/%.o: src/prg/%.c src/prg.h src/bytes.h
	@ mkdir -p obj/prg
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/aead/aes%siv.o: src/aead/aes%siv.c src/aead/_aessiv.c src/prg.h src/bytes.h
	@ mkdir -p obj/aead
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/aead/%.o: src/aead/%.c src/prg.h src/bytes.h
	@ mkdir -p obj/aead
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/kem/frodo%s.o: src/kem/frodo%s.c src/kem/_frodos.c src/_frodo_patch.c src/_frodo_patch_0.c src/kem.h src/bytes.h
	@ mkdir -p obj/kem
	$(CC) -c \
		-DNIX \
		-D_AMD64_ \
		-D_$(FRODO_OPT_LEVEL)_ $(FRODO_OPT_FLAGS) \
		-D_AES128_FOR_A_ \
		$(CPPFLAGS) $(CFLAGS) $< -o $@.o
	$(AR) $@ $@.o \
		lib/libfrodo/objs/util.o \
		lib/libfrodo/objs/random/random.o \
		lib/libfrodo/objs/aes/aes.o \
		lib/libfrodo/objs/aes/aes_c.o \
		lib/libfrodo/objs/sha3/fips202.o \
		$(FRODO_OPT_OBJS)
obj/kem/frodo%.o: src/kem/frodo%.c src/kem/_frodo.c src/kem.h src/bytes.h
	@ mkdir -p obj/kem
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/kem/%.o: src/kem/%.c src/kem.h src/bytes.h
	@ mkdir -p obj/kem
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/hkdf/%.o: src/hkdf/%.c src/hkdf.h src/bytes.h
	@ mkdir -p obj/hkdf
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/hmac/%.o: src/hmac/%.c src/hmac.h src/bytes.h
	@ mkdir -p obj/hmac
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/prf/%.o: src/prf/%.c src/prf.h src/bytes.h
	@ mkdir -p obj/prf
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/ske/aes%cbc.o: src/ske/aes%cbc.c src/ske/_aescbc.c src/ske.h src/bytes.h
	@ mkdir -p obj/ske
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/ske/%.o: src/ske/%.c src/ske.h src/bytes.h
	@ mkdir -p obj/ske
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/%.o: src/%.c src/*.h
	@ mkdir -p obj
	$(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@
obj/test: test.c $(objs)
	@ mkdir -p obj
	$(CC) $(CPPFLAGS) $(CFLAGS) $(libs) $^ -o $@

libbotan:
	@ mkdir -p lib/$@
	git clone https://github.com/randombit/botan.git lib/$@ || (cd lib/$@; git pull)
	cd lib/$@; ./configure.py --prefix=$(CURDIR)/lib --enable-modules=aead,aes,ecdh,ecies,hkdf,hmac,rng,ffi --without-documentation && make && make install && (cd ../include; ln -sf botan-2/botan botan)
	cd lib/$@; ./botan-test

libfrodo:
	@ mkdir -p lib/$@
	git clone https://github.com/Microsoft/PQCrypto-LWEKE.git lib/$@ || (cd lib/$@; git pull)
	cd lib/$@; make clean && make CC=$(CC) ARCH=x64 OPT_LEVEL=$(FRODO_OPT_LEVEL) USE_OPENSSL=FALSE && ( \
		mkdir -p ../include/frodo; \
		cp src/api_frodo640.h ../include/frodo/frodo640.h; \
		cp src/api_frodo976.h ../include/frodo/frodo976.h; \
		cp src/api_frodo1344.h ../include/frodo/frodo1344.h; \
		mkdir -p ../lib; \
		cp frodo640/libfrodo.a ../lib/libfrodo640.a; \
		cp frodo976/libfrodo.a ../lib/libfrodo976.a; \
		cp frodo1344/libfrodo.a ../lib/libfrodo1344.a)
	cd lib/$@; ./frodo640/test_KEM && ./frodo976/test_KEM && ./frodo1344/test_KEM

libs: libbotan libfrodo

test: obj/test
	@ echo === Test with obj/test
	@ LD_LIBRARY_PATH=$(CURDIR)/lib/lib time obj/test
	@ echo === Test succeed

clean:
	rm -rf obj

distclean: clean
	rm -rf lib
