diff --git a/.clang-format b/.clang-format index ec54747a07154dea4e222ab491cc7428ed74caec..f81879ca378ea41e7167b99de2da3277fe0030c1 100644 --- a/.clang-format +++ b/.clang-format @@ -44,7 +44,7 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 160 +ColumnLimit: 180 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false diff --git a/.gitmodules b/.gitmodules index c7e15672e0e73c9ece5688fa98a2c020101131e8..1f643438b25b103c2353c74bc90a2e433705ad1c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,46 +1,50 @@ -[submodule "ttcn/LibCommon"] - path = ttcn/LibCommon - url = https://forge.etsi.org/rep/LIBS/LibCommon.git -[submodule "ttcn/LibIts"] - path = ttcn/LibIts - url = https://forge.etsi.org/rep/LIBS/LibIts.git - branch = devel -[submodule "ttcn/AtsCAM"] - path = ttcn/AtsCAM - url = https://forge.etsi.org/rep/ITS/ttcn/ats_cam_ts102868-3.git - branch = devel -[submodule "ttcn/AtsDENM"] - path = ttcn/AtsDENM - url = https://forge.etsi.org/rep/ITS/ttcn/ats_denm_ts102869-3.git - branch = devel -[submodule "ttcn/AtsGeoNetworking"] - path = ttcn/AtsGeoNetworking - url = https://forge.etsi.org/rep/ITS/ttcn/ats_gn_ts102871-3.git - branch = devel -[submodule "ttcn/AtsBTP"] - path = ttcn/AtsBTP - url = https://forge.etsi.org/rep/ITS/ttcn/ats_btp_ts102870-3.git - branch = devel -[submodule "ttcn/AtsIPv6OverGeoNetworking"] - path = ttcn/AtsIPv6OverGeoNetworking - url = https://forge.etsi.org/rep/ITS/ttcn/ats_gnipv6_ts102859-3.git - branch = devel -[submodule "ttcn/AtsPki"] - path = ttcn/AtsPki - url = https://forge.etsi.org/rep/ITS/ttcn/ats_pki_ts103525-3.git - branch = devel -[submodule "ttcn/AtsIS"] - path = ttcn/AtsIS - url = https://forge.etsi.org/rep/ITS/ttcn/ats_ts103191-3.git - branch = devel -[submodule "ttcn/AtsSecurity"] - path = ttcn/AtsSecurity - url = https://forge.etsi.org/rep/ITS/ttcn/ats_sec_ts103096-3.git - branch = devel -[submodule "ttcn/modules/titan.TestPorts.Common_Components.Abstract_Socket/module"] - path = ttcn/modules/titan.TestPorts.Common_Components.Abstract_Socket/module - url = https://github.com/eclipse/titan.TestPorts.Common_Components.Abstract_Socket.git +[submodule "ttcn/LibCommon"] + path = ttcn/LibCommon + url = https://forge.etsi.org/rep/LIBS/LibCommon.git +[submodule "ttcn/LibIts"] + path = ttcn/LibIts + url = https://forge.etsi.org/rep/LIBS/LibIts.git + branch = devel2 +[submodule "ttcn/AtsCAM"] + path = ttcn/AtsCAM + url = https://forge.etsi.org/rep/ITS/ttcn/ats_cam_ts102868-3.git + branch = devel2 +[submodule "ttcn/AtsDENM"] + path = ttcn/AtsDENM + url = https://forge.etsi.org/rep/ITS/ttcn/ats_denm_ts102869-3.git + branch = devel2 +[submodule "ttcn/AtsGeoNetworking"] + path = ttcn/AtsGeoNetworking + url = https://forge.etsi.org/rep/ITS/ttcn/ats_gn_ts102871-3.git + branch = devel2 +[submodule "ttcn/AtsBTP"] + path = ttcn/AtsBTP + url = https://forge.etsi.org/rep/ITS/ttcn/ats_btp_ts102870-3.git + branch = devel +[submodule "ttcn/AtsIPv6OverGeoNetworking"] + path = ttcn/AtsIPv6OverGeoNetworking + url = https://forge.etsi.org/rep/ITS/ttcn/ats_gnipv6_ts102859-3.git + branch = devel +[submodule "ttcn/AtsPki"] + path = ttcn/AtsPki + url = https://forge.etsi.org/rep/ITS/ttcn/ats_pki_ts103525-3.git + branch = devel2 +[submodule "ttcn/AtsIS"] + path = ttcn/AtsIS + url = https://forge.etsi.org/rep/ITS/ttcn/ats_ts103191-3.git + branch = devel2 +[submodule "ttcn/AtsSecurity"] + path = ttcn/AtsSecurity + url = https://forge.etsi.org/rep/ITS/ttcn/ats_sec_ts103096-3.git + branch = devel2 +[submodule "ttcn/modules/titan.TestPorts.Common_Components.Abstract_Socket/module"] + path = ttcn/modules/titan.TestPorts.Common_Components.Abstract_Socket/module + url = https://github.com/eclipse/titan.TestPorts.Common_Components.Abstract_Socket.git [submodule "titan-test-system-framework"] path = titan-test-system-framework url = https://labs.etsi.org/rep/cti-tools/titan-test-system-framework.git branch = devel +[submodule "ttcn/AtsMBR"] + path = ttcn/AtsMBR + url = https://forge.etsi.org/rep/ITS/ttcn/mbr_ts_103759.git + branch = devel2 diff --git a/.jenkins.sh b/.jenkins.sh index ee78b865929dc0ff5124b5a389163821b9ba0291..954f778dc90cfd47cee1b34c9674bd4ea324b2d1 100755 --- a/.jenkins.sh +++ b/.jenkins.sh @@ -10,7 +10,7 @@ cd $(dirname $0) run_dir=`pwd` # Docker version 2 -cd ./virtualization/docker +cd ./virtualization/docker-dev ./build.sh #--force-stfubuntu ret_code=`echo $?` @@ -24,7 +24,7 @@ fi if [ "$1" == "--remove" ] then - docker rmi --force etsiforge/etsi-its-ts:latest + docker rmi --force etsiforge/etsi-its-ts-r2:latest fi cd $run_dir diff --git a/Makefile b/Makefile index 1c72c69edc8316a7bb86ea04ed7e2920ca338e3f..c02b0a26b7e86407f4fc2c8c8349d943551c355e 100644 --- a/Makefile +++ b/Makefile @@ -1,149 +1,167 @@ --include config.mk - -ifeq (,$(ATS)) - $(error ATS shall be defined) -endif - -ifeq (,$(TOPDIR)) - TOPDIR := . -endif - -ifeq (,$(TTCN3_DIR)) - $(error TTCN3_DIR shall be defined in config.mk) -endif - -export ASN1C_PATH - -first: all - -define IncludeModule -undefine sources -undefine modules -undefine includes -include $(1)/module.mk -$$(foreach S, $$(sources), $$(eval all_sources += $$(if $$(filter /%, $$(S)), $$(TOPDIR)/$$(S), $(1)/$$(S)))) -$$(foreach I, $$(includes), $$(eval all_includes += $$(if $$(filter /%, $$(I)), $$(TOPDIR)/$$(I), $(1)/$$(I)))) -$$(foreach M, $$(modules), $$(eval $$(call IncludeModule, $$(if $$(filter /%, $$(M)), $$(TOPDIR)/$$(M), $(1)/$$(M))))) -endef - -all_includes := $(TTCN3_DIR)/include $(TTCN3_DIR)/src $(TOPDIR)/ccsrc/Framework /usr/include/jsoncpp -defines += TITAN_RUNTIME_2 _NO_SOFTLINKS_ $(ATS) AS_USE_SSL -libs += $(TTCN3_DIR)/lib/libttcn3-rt2-parallel.a -lstdc++fs - -ifeq (Windows_NT,$(OS)) -# Silence linker warnings. -LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc -defines += WIN32 -libs += $(patsubst %, -L%/lib, $(OPENSSL_DIR)) -all_includes += $(addsuffix /include, $(OPENSSL_DIR)) -libs += $(WPCAP_DLL_PATH) -else -defines += LINUX -libs += -lpcap -lrt -lpthread -endif - -libs += -lssl -lcrypto -lxml2 -ljsoncpp - -$(eval $(call IncludeModule, $(TOPDIR)/ttcn/$(ATS))) - -outdir := $(TOPDIR)/build/$(ATS) -bindir := $(TOPDIR)/bin - -sources := $(sort $(all_sources)) -includes := $(outdir) $(outdir)/.. $(outdir)/../asn1 $(all_includes) $(NPCAP_INCLUDE) - -ifeq (Windows_NT,$(OS)) - EXE=.exe -endif - -ttcn_sources := $(filter %.ttcn , $(sources)) -ttcn3_sources := $(filter %.ttcn3, $(sources)) -asn_sources := $(filter %.asn, $(sources)) -asn1_sources := $(filter %.asn1, $(sources)) - -tt_sources := $(ttcn_sources) $(ttcn3_sources) $(asn_sources) $(asn1_sources) -cc_sources := $(filter %.cc, $(sources)) - -gen_ttcn_sources := $(addprefix $(outdir)/, $(notdir $(patsubst %.ttcn, %.cc, $(ttcn_sources)))) -gen_ttcn_headers := $(addprefix $(outdir)/, $(notdir $(patsubst %.ttcn, %.hh, $(ttcn_sources)))) -gen_ttcn3_sources := $(addprefix $(outdir)/, $(notdir $(patsubst %.ttcn3, %.cc, $(ttcn3_sources)))) -gen_ttcn3_headers := $(addprefix $(outdir)/, $(notdir $(patsubst %.ttcn3, %.hh, $(ttcn3_sources)))) -gen_asn_sources := $(addprefix $(outdir)/, $(notdir $(patsubst %.asn, %.cc, $(asn_sources)))) -gen_asn_headers := $(addprefix $(outdir)/, $(notdir $(patsubst %.asn, %.hh, $(asn_sources)))) -gen_asn1_sources := $(addprefix $(outdir)/, $(notdir $(patsubst %.asn1, %.cc, $(asn1_sources)))) -gen_asn1_headers := $(addprefix $(outdir)/, $(notdir $(patsubst %.asn1, %.hh, $(asn1_sources)))) - -gen_sources := $(gen_ttcn_sources) $(gen_ttcn3_sources) $(gen_asn_sources) $(gen_asn1_sources) -gen_headers := $(gen_ttcn_headers) $(gen_ttcn3_headers) $(gen_asn_headers) $(gen_asn1_headers) - -gen_objects := $(patsubst %.cc, %.o, $(gen_sources)) -cc_objects := $(patsubst %.cc, $(outdir)/%.o, $(cc_sources)) - -.PHONY: all FORCE echo - -all: $(bindir) $(outdir) $(bindir)/$(ATS)$(EXE) - -echo_sources: - @echo -e "$(addsuffix \n,$(all_sources))" - -echo: echo_sources - @echo -e "sources:\n $(addsuffix \n, $(sources))" - @echo -e "gen_sources:\n $(addsuffix \n, $(gen_sources))" - @echo -e "gen_objects:\n $(addsuffix \n, $(gen_objects))" - @echo -e "cc_objects:\n $(addsuffix \n, $(cc_objects))" - @echo -e "includes:\n $(addsuffix \n, $(includes))" - @echo -e "defines: $(addsuffix \n, $(defines))" - -clean: - rm -f $(outdir)/$(ATS)$(EXE) $(gen_objects) $(gen_sources) $(gen_headers) $(cc_objects) $(outdir)/.generate $(outdir)/../libItsAsn.so -# rm -f $(outdir)/asn1/*.so $(outdir)/asn1/*.o $(outdir)/asn1/*.c $(outdir)/asn1/*.h $(outdir)/asn1/Makefile.am.libasncodec - -regen: force_regen $(outdir)/.generate -force_regen: - rm -f $(outdir)/.generate - -t3q: all - @echo -e "Code checking in progress..." - @java -Xmx3g -Xss512m -jar $(T3Q_PATH)/t3q.jar --config $(T3Q_PATH)/$(T3Q_CONFIG) $(tt_sources) > $(outdir)/t3q.out 2>&1 ; cd - - @echo -e "Code checking in done..." - @echo -e "Output file is located here: $(outdir)/t3q.out" - -t3d: all - @echo -e "TTCN-3 doc generation in progress..." - @java -Xmx3g -Xss512m -jar $(T3D_PATH)/t3d.jar --config $(T3D_PATH)/$(T3D_CONFIG) $(tt_sources) > $(outdir)/t3d.out 2>&1 ; cd - - @echo -e "TTCN-3 doc generation done..." - @echo -e "Output file is located here: $(outdir)/t3d.out" - -$(outdir) $(bindir): - mkdir -p $@ - -$(bindir)/$(ATS)$(EXE): $(outdir)/../asn1/libItsAsn.a $(gen_objects) $(cc_objects) - g++ -g -O0 -o $@ $(LDFLAGS) $(gen_objects) $(cc_objects) $(outdir)/../asn1/libItsAsn.a $(libs) - -$(gen_objects) :%.o :%.cc - g++ -g -O0 -c $(addprefix -D, $(defines)) $(addprefix -I, $(includes)) -o $@ $< - -$(cc_objects) : $(outdir)/%.o : %.cc - mkdir -p $(dir $@) - g++ -g -O0 -c $(addprefix -D, $(defines)) $(addprefix -I, $(includes)) -o $@ $< - -#$(gen_sources): -# $(TTCN3_DIR)/bin/compiler -n -e -L -R -U none -o $(outdir) $(tt_sources) - -$(gen_sources): $(outdir)/.generate - -$(outdir)/.generate: Makefile $(tt_sources) - $(TTCN3_DIR)/bin/compiler -w -d -e -f -g -l -L -R -U none -x -X -o $(outdir) $(tt_sources) - touch $@ - -$(bindir)/libItsAsn.so: $(outdir)/asn1/libItsAsn.so - cp -f $< $@ - -$(outdir)/../asn1/libItsAsn.a: FORCE - mkdir -p $(outdir)/../asn1 - $(MAKE) -C $(outdir)/../asn1 -f ../../asn1/Makefile - -$(foreach S, $(ttcn_sources), $(eval $(outdir)/$(notdir $(patsubst %.ttcn, %.cc, $(S))): $(S))) -$(foreach S, $(ttcn3_sources), $(eval $(outdir)/$(notdir $(patsubst %.ttcn3, %.cc, $(S))): $(S))) -$(foreach S, $(asn_sources), $(eval $(outdir)/$(notdir $(patsubst %.asn, %.cc, $(S))): $(S))) -$(foreach S, $(asn1_sources), $(eval $(outdir)/$(notdir $(patsubst %.asn1, %.cc, $(S))): $(S))) +-include config.mk + +ifeq (,$(ATS)) + $(error ATS shall be defined) +endif + +ifeq (,$(TOPDIR)) + TOPDIR := . +endif + +ifeq (,$(TTCN3_DIR)) + $(error TTCN3_DIR shall be defined in config.mk) +endif + +ifeq (,$(ASN1C)) + ifneq (,$(ASN1C_PATH)) + ASN1C := $(ASN1C_PATH)/asn1c/.libs/asn1c -S $(ASN1C_PATH)/skeletons + else + ASN1C := asn1c + endif +endif + +export ASN1C_PATH + +first: all + +define IncludeModule +undefine sources +undefine modules +undefine includes +include $(1)/module.mk +$$(foreach S, $$(sources), $$(eval all_sources += $$(if $$(filter /%, $$(S)), $$(TOPDIR)$$(S), $(1)/$$(S)))) +$$(foreach I, $$(includes), $$(eval all_includes += $$(if $$(filter /%, $$(I)), $$(TOPDIR)$$(I), $(1)/$$(I)))) +$$(foreach M, $$(modules), $$(eval $$(call IncludeModule, $$(if $$(filter /%, $$(M)), $$(TOPDIR)$$(M), $(1)/$$(M))))) +endef + +all_includes := $(TTCN3_DIR)/include $(TTCN3_DIR)/src /usr/include/jsoncpp /usr/include/libxml2 +defines += TITAN_RUNTIME_2 _NO_SOFTLINKS_ $(ATS) AS_USE_SSL _GNU_SOURCE +libs += $(TTCN3_DIR)/lib/libttcn3-rt2-parallel.a -lstdc++fs + +ifeq (Windows_NT,$(OS)) +# Silence linker warnings. +LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc +defines += WIN32 +libs += $(patsubst %, -L%/lib, $(OPENSSL_DIR)) +all_includes += $(addsuffix /include, $(OPENSSL_DIR)) +libs += $(WPCAP_DLL_PATH) +else +defines += LINUX +libs += -lpcap -lrt -lpthread +endif + +libs += -lssl -lcrypto -lxml2 -ljsoncpp + +$(eval $(call IncludeModule, $(TOPDIR)/ttcn/$(ATS))) + +outdir := $(TOPDIR)/build/$(ATS) +bindir := $(TOPDIR)/bin + +sources := $(all_sources) +includes := $(outdir) $(outdir)/.. $(outdir)/asn1 $(all_includes) $(NPCAP_INCLUDE) + +ifeq (Windows_NT,$(OS)) + EXE=.exe +endif + +ttcn_sources := $(filter %.ttcn , $(sources)) +ttcn3_sources := $(filter %.ttcn3, $(sources)) +asn_sources := $(filter %.asn, $(sources)) +asn1_sources := $(filter %.asn1, $(sources)) + +tt_sources := $(ttcn_sources) $(ttcn3_sources) $(asn_sources) $(asn1_sources) +cc_sources := $(filter %.cc, $(sources)) + +gen_ttcn_sources := $(addprefix $(outdir)/, $(notdir $(patsubst %.ttcn, %.cc, $(ttcn_sources)))) +gen_ttcn_headers := $(addprefix $(outdir)/, $(notdir $(patsubst %.ttcn, %.hh, $(ttcn_sources)))) +gen_ttcn3_sources := $(addprefix $(outdir)/, $(notdir $(patsubst %.ttcn3, %.cc, $(ttcn3_sources)))) +gen_ttcn3_headers := $(addprefix $(outdir)/, $(notdir $(patsubst %.ttcn3, %.hh, $(ttcn3_sources)))) +gen_asn_sources := $(addprefix $(outdir)/, $(notdir $(patsubst %.asn, %.cc, $(asn_sources)))) +gen_asn_headers := $(addprefix $(outdir)/, $(notdir $(patsubst %.asn, %.hh, $(asn_sources)))) +gen_asn1_sources := $(addprefix $(outdir)/, $(notdir $(patsubst %.asn1, %.cc, $(asn1_sources)))) +gen_asn1_headers := $(addprefix $(outdir)/, $(notdir $(patsubst %.asn1, %.hh, $(asn1_sources)))) + +gen_sources := $(gen_ttcn_sources) $(gen_ttcn3_sources) $(gen_asn_sources) $(gen_asn1_sources) +gen_headers := $(gen_ttcn_headers) $(gen_ttcn3_headers) $(gen_asn_headers) $(gen_asn1_headers) + +gen_objects := $(patsubst %.cc, %.o, $(gen_sources)) +cc_objects := $(patsubst %.cc, $(outdir)/%.o, $(cc_sources)) + +.PHONY: all FORCE echo + +all: $(bindir) $(outdir) $(bindir)/$(ATS)$(EXE) + +echo_sources: + @echo -e "$(addsuffix \n,$(all_sources))" + +echo: echo_sources + @echo -e "sources:\n $(addsuffix \n, $(sources))" + @echo -e "gen_sources:\n $(addsuffix \n, $(gen_sources))" + @echo -e "gen_objects:\n $(addsuffix \n, $(gen_objects))" + @echo -e "cc_objects:\n $(addsuffix \n, $(cc_objects))" + @echo -e "includes:\n $(addsuffix \n, $(includes))" + @echo -e "defines: $(addsuffix \n, $(defines))" + +clean: + rm -f $(outdir)/$(ATS)$(EXE) $(gen_objects) $(gen_sources) $(gen_headers) $(cc_objects) $(outdir)/.generate $(outdir)/../libItsAsn.so +# rm -f $(outdir)/asn1/*.so $(outdir)/asn1/*.o $(outdir)/asn1/*.c $(outdir)/asn1/*.h $(outdir)/asn1/Makefile.am.libasncodec + +regen: force_regen $(outdir)/.generate +force_regen: + rm -f $(outdir)/.generate + +t3q: all + @echo -e "Code checking in progress..." + @java -Xmx3g -Xss512m -jar $(T3Q_PATH)/t3q.jar --config $(T3Q_PATH)/$(T3Q_CONFIG) $(tt_sources) > $(outdir)/t3q.out 2>&1 ; cd - + @echo -e "Code checking in done..." + @echo -e "Output file is located here: $(outdir)/t3q.out" + +t3d: all + @echo -e "TTCN-3 doc generation in progress..." + @java -Xmx3g -Xss512m -jar $(T3D_PATH)/t3d.jar --config $(T3D_PATH)/$(T3D_CONFIG) $(tt_sources) > $(outdir)/t3d.out 2>&1 ; cd - + @echo -e "TTCN-3 doc generation done..." + @echo -e "Output file is located here: $(outdir)/t3d.out" + +$(outdir) $(outdir)/asn1 $(bindir): + mkdir -p $@ + +$(bindir)/$(ATS)$(EXE): $(outdir)/asn1/libItsAsn.a $(gen_objects) $(cc_objects) + g++ -g -O0 -std=c++17 -o $@ $(LDFLAGS) $(gen_objects) $(cc_objects) $(outdir)/asn1/libItsAsn.a $(libs) + +$(gen_objects) :%.o :%.cc + g++ -g -O0 -std=c++17 -c $(addprefix -D, $(defines)) $(addprefix -I, $(includes)) -o $@ $< + +$(cc_objects) : $(outdir)/%.o : %.cc + mkdir -p $(dir $@) + g++ -g -O0 -std=c++17 -c $(addprefix -D, $(defines)) $(addprefix -I, $(includes)) -o $@ $< + +#$(gen_sources): +# $(TTCN3_DIR)/bin/compiler -n -e -L -R -U none -o $(outdir) $(tt_sources) + +$(gen_sources): $(outdir)/.generate + +$(outdir)/.generate: Makefile $(tt_sources) + $(TTCN3_DIR)/bin/compiler $(TTCN3_COMPILER_OPTIONS) -o $(outdir) $(tt_sources) + touch $@ + +$(bindir)/libItsAsn.so: $(outdir)/asn1/libItsAsn.so + cp -f $< $@ + +$(outdir)/asn1/libItsAsn.a: $(asn_sources) $(asn1_sources) libasn1.mk Makefile + mkdir -p $(outdir)/asn1 + echo TOP_DIR := ../../.. >$(outdir)/asn1/Makefile + echo ASN_PDU := $(pdu) >>$(outdir)/asn1/Makefile + echo ASN_FILES := \\ >>$(outdir)/asn1/Makefile + for n in $(asn_sources) $(asn1_sources); do echo " $$n \\"; done >>$(outdir)/asn1/Makefile + echo >>$(outdir)/asn1/Makefile + cat libasn1.mk >>$(outdir)/asn1/Makefile + $(MAKE) -C $(outdir)/asn1 + touch $@ + +$(foreach S, $(ttcn_sources), $(eval $(outdir)/$(notdir $(patsubst %.ttcn, %.cc, $(S))): $(S))) +$(foreach S, $(ttcn3_sources), $(eval $(outdir)/$(notdir $(patsubst %.ttcn3, %.cc, $(S))): $(S))) +$(foreach S, $(asn_sources), $(eval $(outdir)/$(notdir $(patsubst %.asn, %.cc, $(S))): $(S))) +$(foreach S, $(asn1_sources), $(eval $(outdir)/$(notdir $(patsubst %.asn1, %.cc, $(S))): $(S))) + +$(asn_sources) $(asn1_sources): + diff --git a/README.md b/README.md index 7a5552117448aa9afaf538c16343b40abdb1fa26..29bc9fb41ad4e67e30f8922b973e25e7864e2d04 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## General Information -This repositories contains the test specifications and test adapter code for ETSI ITS protocols testing. +This repositories contains the test specifications and test adapter code for ETSI ITS protocols testing, Release 2. ETSI ITS protocols project supports: - ETSI EN 302 637-2: "Intelligent Transport Systems (ITS); Vehicular Communications; Basic Set of Applications; Part 2: Specification of Cooperative Awareness Basic Service" - ETSI EN 102 637-3: "Intelligent Transport Systems (ITS); Vehicular Communications; Basic Set of Applications; Part 3: Specifications of Decentralized Environmental Notification Basic Service" @@ -29,7 +29,7 @@ https://forge.etsi.org/etsi-software-license ## STFs The following STFs were or are currently involved in the evolutions of the ETSI ITS protocols project: -- STF 405, STF 422, STF 424, STF 455, STF 462, STF 481, STF 484, STF 507, STF 517, STF 525, STF 538, STF 545, STF 594, TTF T002, TTF T011 +- STF 405, STF 422, STF 424, STF 455, STF 462, STF 481, STF 484, STF 507, STF 517, STF 525, STF 538, STF 545, STF 594, TTF T002, TTF T011, TTF T024 ## Installation @@ -209,10 +209,14 @@ Procedure: - Clone the ETSI ITS protocols project into $HOME/dev folder ```sh -$ git clone --recurse-submodules --single-branch https://forge.etsi.org/gitlab/ITS/TS.ITS.git ./TTF011_Its +$ git clone --recurse-submodules --single-branch https://forge.etsi.org/gitlab/ITS/TS.ITS.git +$ cd ${HOME}/dev/TS.ITS/ +$ cp ./ttcn/patch_lib_common/module.mk ./ttcn/LibCommon/ +$ cp ./ttcn/patch_lib_common/ttcn/* ./ttcn/LibCommon/ttcn + ``` -- Update your default environment with the content of the script $HOME/dev/TTF011_Its/scripts/devenv.bash.ubuntu +- Update your default environment with the content of the script $HOME/dev/TS.ITS/scripts/devenv.bash.ubuntu - Switch to the next clause (Usage) @@ -230,7 +234,7 @@ These two files are used create the ETSI ITS project workspace on Eclipse TITAN. NOTE: When the Eclipse TITAN workspace is created, you have to build manually the librairy 'libasn1c.so' following the commands below: ```sh -$ cd /TTF011_Its +$ cd /TS.ITS $ mkdir -p ./bin/asn1 $ cd ./bin/asn1 $ make CC=gcc -f ../../asn1/Makefile @@ -250,7 +254,7 @@ Pre-requisites: - Your are logged as 'etsi' or 'vagrant' user - Procedure using TITAN command line (only): - Open several SSH session (PuTTY...) - - Change to the directory ~/dev/TTF011_Its/ + - Change to the directory ~/dev/TS.ITS/ - Modify the file config.mk according to your system: - On Linux, comment all the lines using the '#' character - On Windows, update the path accordingly @@ -269,7 +273,7 @@ $ make - To run the test suitem, execute the following command: ```sh -$ cd ~/dev/TTF011_Its/scripts +$ cd ~/dev/TS.ITS/scripts $ ../run_all.bash ... ``` @@ -303,21 +307,21 @@ $ make ### Generate the certificates -After applying the previous clause, change to the folder '~/dev/TTF011_Its/data/certificates' and execute 'make' command: +After applying the previous clause, change to the folder '~/dev/TS.ITS/data/certificates' and execute 'make' command: ``` -$ cd ~/dev/TTF011_Its/data/certificates +$ cd ~/dev/TS.ITS/data/certificates $ make ``` -The certificates will be located in the folder '~/dev/TTF011_Its/data/certificates/certificates'. +The certificates will be located in the folder '~/dev/TS.ITS/data/certificates/certificates'. To use this newly generated certificates, you shall update two parameters located in the TTCN-3 file LibItsSecurity_Pixits. These are: -- LibItsSecurity_Pixits.PX_CERTIFICATE_POOL_PATH, which is the path the certificates folder (e.g. LibItsSecurity_Pixits.PX_CERTIFICATE_POOL_PATH := "/home//dev/TTF011_Its/data/certificates") +- LibItsSecurity_Pixits.PX_CERTIFICATE_POOL_PATH, which is the path the certificates folder (e.g. LibItsSecurity_Pixits.PX_CERTIFICATE_POOL_PATH := "/home//dev/TS.ITS/data/certificates") - LibItsSecurity_Pixits.PX_IUT_SEC_CONFIG_NAME, which is the name of the certificates folder (e.g. LibItsSecurity_Pixits.PX_IUT_SEC_CONFIG_NAME := "certificates") ### Modify or create new certificates -The folder '~/dev/TTF011_Its/data/profiles' contains an XML file for each certificate to be generated. +The folder '~/dev/TS.ITS/data/profiles' contains an XML file for each certificate to be generated. This XML file describes the certificate content (e.g. CERT_IUT_A_RCA.xml describes the root certificate for all CERT_IUT_A certificates). By modifying these files, you can change create new certificate with different geographical area, different validity periods or different SSPs. @@ -338,7 +342,7 @@ In this cases, the following parameters shall be modified to match the ITS devic In addition, the Test System shall be configured to support the security modifying the following settings as described below: - device_mode=1 - secured_mode=1 -- sec_db_path=/home//dev/TTF011_Its/data/certificates/certificates +- sec_db_path=/home//dev/TS.ITS/data/certificates/certificates ### ITS Protocol Test suites for Transport layer @@ -351,7 +355,7 @@ In this cases, the following parameters shall be modified to match the ITS devic In addition, the Test System shall be configured to support the security modifying the following settings as described below: - device_mode=1 - secured_mode=1 -- sec_db_path=/home//dev/TTF011_Its/data/certificates/certificates +- sec_db_path=/home//dev/TS.ITS/data/certificates/certificates ### ITS Protocol Test suites for Security diff --git a/asn1/Makefile b/asn1/Makefile deleted file mode 100644 index e2f98809b2be236daa5c295b979980b581a5f282..0000000000000000000000000000000000000000 --- a/asn1/Makefile +++ /dev/null @@ -1,216 +0,0 @@ -########################################################## -# This Makefile is to build the ASN1 library to be used -# for external codec in Titan -# This Makefile is expected that asn1c compiler is -# installed in the PATHs -########################################################## - -# The name of the library -ASN_LIBRARY = libItsAsn.a -# ASN.1 files to be included in the library -ASN_FILES = AtsCAM/lib/asn1/CAM_PDU_Descriptions.asn \ - AtsCAM/lib/asn1/cdd/ITS_Container.asn \ - AtsDENM/lib/asn1/DENM_PDU_Descriptions.asn \ - AtsSecurity/lib/asn1/EtsiTs103097ExtensionModule.asn \ - AtsSecurity/lib/asn1/EtsiTs103097Module.asn \ - AtsSecurity/lib/asn1/ieee1609dot2/Ieee1609Dot2.asn \ - AtsSecurity/lib/asn1/ieee1609dot2/Ieee1609Dot2BaseTypes.asn\ - AtsIS/lib/asn1/IVIM_PDU_Descriptions.asn \ - AtsIS/lib/asn1/MAPEM_PDU_Descriptions.asn \ - AtsIS/lib/asn1/RTCMEM_PDU_Descriptions.asn \ - AtsIS/lib/asn1/SPATEM_PDU_Descriptions.asn \ - AtsIS/lib/asn1/SREM_PDU_Descriptions.asn \ - AtsIS/lib/asn1/SSEM_PDU_Descriptions.asn \ - AtsIS/lib/asn1/iso-patched/EfcDsrcApplication.asn \ - AtsIS/lib/asn1/iso-patched/EfcDsrcGeneric.asn \ - AtsIS/lib/asn1/iso-patched/ElectronicRegistrationIdentificationVehicleDataModule.asn \ - AtsIS/lib/asn1/iso-patched/GDD.asn \ - AtsIS/lib/asn1/iso-patched/DSRC.asn \ - AtsIS/lib/asn1/iso-patched/DSRC_noCircular.asn \ - AtsIS/lib/asn1/iso-patched/REGION.asn \ - AtsIS/lib/asn1/iso-patched/AddGrpC.asn \ - AtsIS/lib/asn1/iso-patched/AddGrpC_noCircular.asn \ - ../build/asn1/ISO_TS_14816/AVIAEINumberingAndDataStructures.asn \ - ../build/asn1/ISO_TS_17419/CITSapplMgmtIDs.asn \ - ../build/asn1/ISO_TS_19321/IVI.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Crl.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2CrlBaseTypes.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1AcaEeInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1AcaLaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1AcaMaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1AcaRaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1Acpc.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1CamRaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1CertManagement.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1EcaEeInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1EeMaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1EeRaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1LaMaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1LaRaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1MaRaInterface.asn \ - AtsPki/lib/asn1/ieee_1609.2.1/Ieee1609Dot2Dot1Protocol.asn - -# ../build/asn1/ISO_TS_19091/ISO-TS-19091-addgrp-C-2018-patched.asn \ -# ../build/asn1/ISO_TS_19091/AddGrpC.asn \ -# ../build/asn1/ISO_TS_19091/AddGrpC_noCircular.asn \ -# ../build/asn1/ISO_TS_19091/DSRC.asn \ -# ../build/asn1/ISO_TS_19091/DSRC_REGION_noCircular.asn \ -# ../build/asn1/ISO_TS_19091/REGION.asn \ - -# AtsPki/lib/asn1/EtsiTs102941BaseTypes.asn \ -# AtsPki/lib/asn1/EtsiTs102941MessagesCa.asn \ -# AtsPki/lib/asn1/EtsiTs102941TrustLists.asn \ -# AtsPki/lib/asn1/EtsiTs102941TypesAuthorization.asn \ -# AtsPki/lib/asn1/EtsiTs102941TypesAuthorizationValidation.asn \ -# AtsPki/lib/asn1/EtsiTs102941TypesCaManagement.asn \ -# AtsPki/lib/asn1/EtsiTs102941TypesEnrolment.asn \ -# AtsPki/lib/asn1/EtsiTs102941TypesLinkCertificate.asn \ - -# PDUs -PDU = CAM DENM MAPEM SPATEM SREM SSEM IVIM RTCMEM EtsiTs103097Data EtsiTs103097Certificate -#EtsiTs102941Data - -#patches -#PATCHES = PsidGroupPermissions.c.diff - -ASN1C:=asn1c -#Override ASN1C instalation path -#ASN1C_PATH = - -ifneq (, $(ASN1C_PATH)) -# OS=$(shell uname) - ifneq (Windows_NT,$(OS)) - ASN1C:=$(ASN1C_PATH)/asn1c/asn1c -S $(ASN1C_PATH)/skeletons - else - ASN1C:=$(ASN1C_PATH)/asn1c/asn1c.exe -S $(ASN1C_PATH)/skeletons - endif -endif - -ifeq (,$(ASN_DIR)) -########################################################## -# Build path for the library -BIN_DIR := . -SCRIPT_DIR := $(dir $(lastword $(MAKEFILE_LIST))) -ASN_DIR := $(dir $(SCRIPT_DIR))../ttcn - -.PHONY: FORCE - -all: $(BIN_DIR)/$(ASN_LIBRARY) -clean: - rm -rf $(BIN_DIR) - -$(BIN_DIR)/$(ASN_LIBRARY): $(BIN_DIR)/Makefile - make -C $(BIN_DIR) all - -$(BIN_DIR): - mkdir -p $@ - -$(BIN_DIR)/Makefile: $(BIN_DIR) $(SCRIPT_DIR)/Makefile - echo SCRIPT_DIR=$(SCRIPT_DIR) > $@ - echo ASN_DIR=$(ASN_DIR) >>$@ - cat $(SCRIPT_DIR)/Makefile >>$@ - -########################################################## -else -########################################################## -# This part is executed within the BIN_DIR directory to -# override variables from the Makefile.am.libasncodec -# generated by asn1c -LIB_MAKEFILE=Makefile.am.libasncodec -include $(LIB_MAKEFILE) -OBJS = ${ASN_MODULE_SRCS:.c=.o} -CONVERTER=converter -ASN_CONVERTER_SOURCES := \ - converter-example.c\ - pdu_collection.c -CONVERTER_OBJS=${ASN_CONVERTER_SOURCES:.c=.o} -CFLAGS += $(ASN_MODULE_CFLAGS) -DPDU=CAM -DASN_PDU_COLLECTION -fPIC -I. -CC = gcc -std=c99 -GEN_EXAMPLE=-no-gen-example -ifeq (yes,$(DEBUG)) - CFLAGS += -g -O0 -DASN_EMIT_DEBUG=1 -endif - -all: Makefile $(ASN_LIBRARY) - -$(LIB_MAKEFILE): $(addprefix $(ASN_DIR)/, $(ASN_FILES)) - $(ASN1C) $(GEN_EXAMPLE) $(addprefix -pdu=,$(PDU)) -fcompound-names $^ - -for n in $(PATCHES); do git apply "$(SCRIPT_DIR)/$$n"; done - -$(CONVERTER): $(ASN_LIBRARY) $(CONVERTER_OBJS) - $(CC) $(CFLAGS) -o $@ $(CONVERTER_OBJS) $(ASN_LIBRARY) $(LIBS) - -$(ASN_LIBRARY): ${ASN_MODULE_SRCS:.c=.o} - ar rcs $@ $^ -# $(CC) $(CFLAGS) -o $@ $^ -shared $(LDFLAGS) $(LIBS) - -.SUFFIXES: -.SUFFIXES: .c .o - -.c.o: - $(CC) $(CFLAGS) -o $@ -c $< - -clean: - rm -f $(CONVERTER) $(ASN_LIBRARY) - rm -f $(OBJS) $(CONVERTER_OBJS) - -regen: clear-asn1c $(LIB_MAKEFILE) -clear-asn1c: - rm -f $(LIB_MAKEFILE) - -Makefile: $(SCRIPT_DIR)/Makefile - echo SCRIPT_DIR=$(SCRIPT_DIR) > $@ - echo ASN_DIR=$(ASN_DIR) >>$@ - cat $< >>$@ -########################################################## - -$(ASN_DIR)/../build/asn1/ISO_TS_14816/AVIAEINumberingAndDataStructures.asn: - mkdir -p "$(dir $@)" - curl 'https://standards.iso.org/iso/14816/ISO14816%20ASN.1%20repository/ISO14816_AVIAEINumberingAndDataStructures.asn' | \ - sed -e 's/IssuerIdentifier/AVIAEIIssuerIdentifier/g' > "$@" - -#../build/asn1/ISO_TS_14906/EfcDsrcApplication.asn: -# mkdir -p "$(dir $@)" -# curl -o "$@" 'https://standards.iso.org/iso/14906/ed-3/en/ISO14906(2018)EfcDsrcApplicationv6.asn' - -#../build/asn1/ISO_TS_14906/EfcDsrcGeneric.asn: -# mkdir -p "$(dir $@) -# curl -o "$@" 'https://standards.iso.org/iso/14906/ed-3/en/ISO14906(2018)EfcDsrcGenericv7.asn' - -$(ASN_DIR)/../build/asn1/ISO_TS_17419/CITSapplMgmtIDs.asn: - mkdir -p "$(dir $@)" - curl -o "$@" 'https://standards.iso.org/iso/ts/17419/TS%2017419%20ASN.1%20repository/TS17419_2014_CITSapplMgmtIDs.asn' - -$(ASN_DIR)/../build/asn1/ISO_TS_19091/ISO-TS-19091-addgrp-C-2018-patched.asn: - mkdir -p "$(dir $@)" - curl 'https://standards.iso.org/iso/ts/19091/ed-2/en/ISO-TS-19091-addgrp-C-2018.asn' | \ - sed -e 's/\bHeadingConfidence\b/HeadingConfidenceDSRC/g' \ - -e 's/\bSpeedConfidence\b/SpeedConfidenceDSRC/g' \ - -e 's/\bHeading\b/HeadingDSRC/g' > "$@" - -$(ASN_DIR)/../build/asn1/ISO_TS_17419/CITSdataDictionary1.asn: - mkdir -p "$(dir $@)" - curl -o "$@" 'https://standards.iso.org/iso/17419/ed-1/en/17419.1.asn' - -$(ASN_DIR)/../build/asn1/ISO_TS_17419/CITSdataDictionary2.asn: - mkdir -p "$(dir $@)" - curl -o "$@" 'https://standards.iso.org/iso/17419/ed-1/en/17419.2.asn' - -#../build/asn1/ISO_TS_19091/AddGrpC.asn: -#../build/asn1/ISO_TS_19091/AddGrpC_noCircular.asn: -#../build/asn1/ISO_TS_19091/DSRC.asn: -#../build/asn1/ISO_TS_19091/DSRC_REGION_noCircular.asn -#../build/asn1/ISO_TS_19091/REGION.asn - -$(ASN_DIR)/../build/asn1/ISO_TS_19321/IVI.asn: - mkdir -p "$(dir $@)" - curl 'https://standards.iso.org/iso/ts/19321/ed-2/en/ISO19321IVIv2.asn' | \ - sed -e 's/\bCITSdataDictionary1\b/CITSapplMgmtIDs/g' \ - -e 's/,\s*\.\.\.\s*,\s*[0-9]\+/,.../g' \ - > "$@" - -#$(ASN_DIR)/../build/asn1/ISO_TS_24534-3/ElectronicRegistrationIdentificationVehicleDataModule.asn: -# mkdir -p "$(dir $@)" -# curl -o "$@" 'https://standards.iso.org/iso/24534/-3/ISO%2024534-3%20ASN.1%20repository/ISO24534-3_ElectronicRegistrationIdentificationVehicleDataModule_ForBallot.asn' - -endif diff --git a/asn1/PsidGroupPermissions.c.diff b/asn1/PsidGroupPermissions.c.diff deleted file mode 100644 index c684a0a478f17bca478225d961496eddf52e2b53..0000000000000000000000000000000000000000 --- a/asn1/PsidGroupPermissions.c.diff +++ /dev/null @@ -1,35 +0,0 @@ ---- PsidGroupPermissions.c-orig 2018-08-23 15:50:25.762030100 +0200 -+++ PsidGroupPermissions.c 2018-09-10 16:47:19.921571200 +0200 -@@ -51,6 +51,22 @@ - *st = 0; - return 0; - } -+static int asn_DFL_5_cmp_0(const void *sptr) { -+ uint8_t def_buf[] = { 0 }; -+ BIT_STRING_t def = { &def_buf[0], 1, 7 }; -+ return BIT_STRING_compare(&asn_DEF_EndEntityType, sptr, &def); -+} -+ -+static int asn_DFL_5_set_0(void **sptr) { -+ BIT_STRING_t * st = *(BIT_STRING_t **)sptr; -+ if (!st) { -+ st = (*sptr = CALLOC(1, sizeof(*st))); -+ if (!st) return -1; -+ } -+ OCTET_STRING_fromBuf((OCTET_STRING_t *)st, "\x0", 1); -+ return 0; -+} -+ - asn_TYPE_member_t asn_MBR_PsidGroupPermissions_1[] = { - { ATF_NOFLAGS, 0, offsetof(struct PsidGroupPermissions, subjectPermissions), - (ASN_TAG_CLASS_CONTEXT | (0 << 2)), -@@ -87,7 +103,8 @@ - &asn_DEF_EndEntityType, - 0, - { 0, 0, 0 }, -- 0, 0, /* No default value */ -+ asn_DFL_5_cmp_0, -+ asn_DFL_5_set_0, - "eeType" - }, - }; diff --git a/ccsrc/Asn1c/asn1_recode_per.cc b/ccsrc/Asn1c/asn1_recoder.cc similarity index 52% rename from ccsrc/Asn1c/asn1_recode_per.cc rename to ccsrc/Asn1c/asn1_recoder.cc index 5259e44101ec304adc23de7c0a7b159f91db6415..ea532a936fce2d081815a502c6091494b8032172 100644 --- a/ccsrc/Asn1c/asn1_recode_per.cc +++ b/ccsrc/Asn1c/asn1_recoder.cc @@ -1,6 +1,6 @@ #include -#include "asn1_recode_per.hh" +#include "asn1_recoder.hh" #include @@ -12,7 +12,7 @@ static int asn1c_collect_encoded_data(const void *buffer, size_t size, void *app } } -int asn1_recode_per::recode(const asn_TYPE_descriptor_s &td, int from, int to, TTCN_Buffer &buf) { +int asn1_recoder::recode(const asn_TYPE_descriptor_s &td, int from, int to, TTCN_Buffer &buf) { int rc = -1; void * ptr = NULL; asn_dec_rval_t rc_d; @@ -30,16 +30,22 @@ int asn1_recode_per::recode(const asn_TYPE_descriptor_s &td, int from, int to, T return rc; } -int asn1_recode_per::ber2per(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf) { return recode(td, (int)ATS_BER, (int)ATS_UNALIGNED_CANONICAL_PER, buf); } +int asn1_recoder::ber2per(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf) +{ + return recode(td, (int)ATS_BER, (int)ATS_UNALIGNED_CANONICAL_PER, buf); +} -int asn1_recode_per::per2ber(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf) { return recode(td, (int)ATS_UNALIGNED_BASIC_PER, (int)ATS_DER, buf); } +int asn1_recoder::per2ber(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf) +{ + return recode(td, (int)ATS_UNALIGNED_BASIC_PER, (int)ATS_DER, buf); +} -/*int asn1_recode_oer::ber2oer(const asn_TYPE_descriptor_s & td, TTCN_Buffer & buf) +int asn1_recoder::ber2oer(const asn_TYPE_descriptor_s & td, TTCN_Buffer & buf) { - return recode(td, (int)ATS_XER, (int)ATS_CANONICAL_OER, buf); + return recode(td, (int)ATS_BER, (int)ATS_CANONICAL_OER, buf); } -int asn1_recode_oer::oer2ber(const asn_TYPE_descriptor_s & td, TTCN_Buffer & buf) +int asn1_recoder::oer2ber(const asn_TYPE_descriptor_s & td, TTCN_Buffer & buf) { - return recodeOer(td, (int)ATS_BASIC_OER, (int)ATS_XER, buf); - }*/ + return recode(td, (int)ATS_BASIC_OER, (int)ATS_BER, buf); +} diff --git a/ccsrc/Asn1c/asn1_recode_per.hh b/ccsrc/Asn1c/asn1_recoder.hh similarity index 88% rename from ccsrc/Asn1c/asn1_recode_per.hh rename to ccsrc/Asn1c/asn1_recoder.hh index b5ac27546ca2567145b4f77c35d174ef0b10197f..7592e23fe023f3c6126942e7a44f542e48b3e266 100644 --- a/ccsrc/Asn1c/asn1_recode_per.hh +++ b/ccsrc/Asn1c/asn1_recoder.hh @@ -19,9 +19,11 @@ class TTCN_Typedescriptor_t; //! Forward declaration of TITAN class struct asn_TYPE_descriptor_s; //! Forward declaration of asn1c class -class asn1_recode_per { +class asn1_recoder { protected: int ber2per(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf); int per2ber(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf); + int ber2oer(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf); + int oer2ber(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf); int recode(const asn_TYPE_descriptor_s &td, int from, int to, TTCN_Buffer &buf); }; // End of class asn1_recode_per diff --git a/ccsrc/Asn1c/module.mk b/ccsrc/Asn1c/module.mk index 055195feb9fafe139c62ccecc3bc1da1600335c6..226091a330be6a418fbdbb17e1ffc9c7f30fd680 100644 --- a/ccsrc/Asn1c/module.mk +++ b/ccsrc/Asn1c/module.mk @@ -1,3 +1,3 @@ -sources := asn1_recode_per.cc +sources := asn1_recoder.cc includes := . diff --git a/ccsrc/Asn1c/oer_codec.hh b/ccsrc/Asn1c/oer_codec.hh new file mode 100644 index 0000000000000000000000000000000000000000..24c14d9b7a7f16a2a7650c0b45b1515305714134 --- /dev/null +++ b/ccsrc/Asn1c/oer_codec.hh @@ -0,0 +1,42 @@ +#pragma once + +#include "params.hh" +#include "asn1_recoder.hh" + +class OCTETSTRING; +class CHARSTRING; +class BITSTRING; + +struct asn_TYPE_descriptor_s; + +template class oer_codec : public asn1_recoder +{ +public: + virtual int encode(const TPDU& msg, BITSTRING& bits) = 0; + virtual int decode(const BITSTRING& bits, TPDU& msg) = 0; + +protected: + inline int _decode (const TTCN_Typedescriptor_t& ttcn, const asn_TYPE_descriptor_s & td, const BITSTRING& p_data, TPDU& msg) { + TTCN_Buffer buf(bit2oct(p_data)); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + int rc = oer2xer (td, buf); + if (rc > 0) { + msg.decode(ttcn, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL); + rc = buf.get_len(); + } + return rc; + } + inline int _encode (const TTCN_Typedescriptor_t& ttcn, const asn_TYPE_descriptor_s & td, const TPDU& msg, BITSTRING& p_data) { + int rc = -1; + TTCN_Buffer buf; + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + msg.encode(ttcn, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER); + if (buf.get_len() > 0) { + rc = xer2oer (td, buf); + if (rc > 0) { + p_data = oct2bit(OCTETSTRING(buf.get_len(), buf.get_data())); + } + } + return rc; + } +}; diff --git a/ccsrc/Asn1c/per_codec.hh b/ccsrc/Asn1c/per_codec.hh new file mode 100644 index 0000000000000000000000000000000000000000..0ffc5e1dea6098a5ed9a34c6eea0cb454d5c6048 --- /dev/null +++ b/ccsrc/Asn1c/per_codec.hh @@ -0,0 +1,80 @@ +/*! + * \file per_codec.hh + * \brief Header file for TITAN message to ASN.1 PER message codec. + * \author ETSI STF525 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "params.hh" +#include "asn1_recoder.hh" + +class BITSTRING; //! Forward declaration of TITAN class +class TTCN_Typedescriptor_t; //! Forward declaration of TITAN class + +struct asn_TYPE_descriptor_s; //! Declare asn1c class + +/*! + * \class per_codec + * \brief This class provides the interface for all ASN.1 PER codecs. + * \remark This class uses asn1c external tool + */ +template +class per_codec : public asn1_recoder +{ +public: //! \publicsection + /*! + * \fn int encode(const TPDU& p_message, BITSTRING& p_bitstring); + * \brief Encode TITAN message into ASN.1 PER message + * \param[in] p_message The PDU message to encode + * \param[out] p_bitstring The encoded PDU message in bit string format + * \pure + */ + virtual int encode(const TPDU& p_message, BITSTRING& p_bitstring) = 0; + /*! + * \fn int decode(const BITSTRING& p_bitstring, TPDU& p_message); + * \brief Decode ASN.1 PER message into TITAN message + * \param[in] p_bitstring The network message in bit string format to decode + * \param[out] p_message The PDU message + * \pure + */ + virtual int decode(const BITSTRING& p_bitstring, TPDU& p_message) = 0; + +protected: //! \protectedsection + int _decode (const TTCN_Typedescriptor_t& ttcn, const asn_TYPE_descriptor_s & td, const BITSTRING& p_data, TPDU& msg); + int _encode (const TTCN_Typedescriptor_t& ttcn, const asn_TYPE_descriptor_s & td, const TPDU& msg, BITSTRING& p_data); +}; // End of class per_codec + +#include + +template +int per_codec::_decode (const TTCN_Typedescriptor_t& ttcn, const asn_TYPE_descriptor_s & td, const BITSTRING& p_data, TPDU& msg) { + TTCN_Buffer buf(bit2oct(p_data)); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + int rc = per2ber (td, buf); + if (rc > 0) { + msg.decode(ttcn, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL); + rc = buf.get_len(); + } + return rc; +} + +template +int per_codec::_encode (const TTCN_Typedescriptor_t& ttcn, const asn_TYPE_descriptor_s & td, const TPDU& msg, BITSTRING& p_data) { + int rc = -1; + TTCN_Buffer buf; + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + msg.encode(ttcn, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER); + if (buf.get_len() > 0) { + rc = ber2per (td, buf); + if (rc > 0) { + p_data = oct2bit(OCTETSTRING(buf.get_len(), buf.get_data())); + } + } + return rc; +} + diff --git a/ccsrc/EncDec/LibItsMbr_Encdec.cc b/ccsrc/EncDec/LibItsMbr_Encdec.cc new file mode 100644 index 0000000000000000000000000000000000000000..084f3e0dffdfbe8f0f8536dd5101d935c1215aea --- /dev/null +++ b/ccsrc/EncDec/LibItsMbr_Encdec.cc @@ -0,0 +1,36 @@ +#include "LibItsMbr_EncdecDeclarations.hh" + +#include "etsi_ts103759_data_codec.hh" + +#include "loggers.hh" + +namespace LibItsMbr__EncdecDeclarations { + + BITSTRING fx__enc__EtsiTs103759Data(const EtsiTs103759Core::EtsiTs103759Data &p_etsi_ts_103759_data) { + loggers::get_instance().log_msg(">>> fx__enc__EtsiTs103759Data: ", p_etsi_ts_103759_data); + + etsi_ts103759_data_codec codec; + OCTETSTRING os; + if (codec.encode(p_etsi_ts_103759_data, os) == -1) { + loggers::get_instance().warning("fx__enc__EtsiTs103759Data: -1 result code was returned"); + return int2bit(0, 1); + } + + return oct2bit(os); + } + + INTEGER fx__dec__EtsiTs103759Data(BITSTRING &b, EtsiTs103759Core::EtsiTs103759Data &p_etsi_ts_103759_data) { + loggers::get_instance().log_msg(">>> fx__dec__EtsiTs103759Data: ", b); + + etsi_ts103759_data_codec codec; + OCTETSTRING is = bit2oct(b); + if (codec.decode(is, p_etsi_ts_103759_data) == -1) { + loggers::get_instance().warning("fx__dec__EtsiTs103759Data: -1 result code was returned"); + return -1; + } + + return 0; + } + + +} // End of namespace LibItsMbr__EncdecDeclarations diff --git a/ccsrc/EncDec/module.mk b/ccsrc/EncDec/module.mk index 578e439de2cbcb2caf3940a46dba64693772211e..18f4be8446a7fc09944f81103133812b2263259d 100644 --- a/ccsrc/EncDec/module.mk +++ b/ccsrc/EncDec/module.mk @@ -29,7 +29,8 @@ sources += \ LibItsSremSsem_Encdec.cc \ LibItsRtcmem_Encdec.cc \ LibItsIvim_Encdec.cc \ - LibItsPki_Encdec.cc + LibItsPki_Encdec.cc \ + LibItsMbr_Encdec.cc endif @@ -55,3 +56,10 @@ sources += \ LibItsPki_Encdec.cc \ LibItsCam_Encdec.cc endif + +ifeq (AtsMBR, $(ATS)) +sources += \ + LibItsBtp_Encdec.cc \ + LibItsMbr_Encdec.cc \ + LibItsCam_Encdec.cc +endif diff --git a/ccsrc/Externals/AtsRSUsSimulator_externals.cc b/ccsrc/Externals/AtsRSUsSimulator_externals.cc index 67006b719259198476d41260b72f9fc00a404fde..e4272fe962fa7be5ec7742cc597889864ad5e615 100644 --- a/ccsrc/Externals/AtsRSUsSimulator_externals.cc +++ b/ccsrc/Externals/AtsRSUsSimulator_externals.cc @@ -1,5 +1,8 @@ #include "ItsRSUsSimulator_Functions.hh" +#include "loggers.hh" +#include "geospacial.hh" + namespace ItsRSUsSimulator__Functions { void fx__computePositionFromRotation(const INTEGER &p__refLatitude, const INTEGER &p__refLongitude, const INTEGER &p__cenLatitude, const INTEGER &p__cenLongitude, const INTEGER &p__rotation, INTEGER &p__latitude, INTEGER &p__longitude) { @@ -8,4 +11,20 @@ namespace ItsRSUsSimulator__Functions { p__longitude = p__cenLongitude; } + void fx__computeIncPosition(const INTEGER &p__refLatitude, const INTEGER &p__refLongitude, const FLOAT& p__dx, const FLOAT& p__dy, INTEGER &p__new__latitude, INTEGER &p__new__longitude) { + // Assume that As long as p__dx and p__dy are small compared to the radius of the earth and reference position is not too close to the pole + // http://www.edwilliams.org/avform147.htm#Intro + loggers::get_instance().log_msg(">>> fx__computeIncPosition: p__refLatitude=", p__refLatitude); + loggers::get_instance().log_msg(">>> fx__computeIncPosition: p__refLongitude=", p__refLongitude); + + //loggers::get_instance().log("fx__computeIncPosition: lat='%f'", static_cast(p__refLatitude) + (p__dy / R) * (180 / PI)); + //loggers::get_instance().log("fx__computeIncPosition: long='%f'", static_cast(p__refLongitude) + (p__dx / R) * (180 / PI) / cos(static_cast(p__refLatitude) * PI / 180)); + p__new__latitude = p__refLatitude + 1;//static_cast(static_cast(p__refLatitude) + (p__dy / R) * (180 / PI)); + p__new__longitude = p__refLongitude + 1;//static_cast(static_cast(p__refLongitude) + (p__dx / R) * (180 / PI) / cos(static_cast(p__refLatitude) * PI / 180)); + + loggers::get_instance().log_msg("<<< fx__computeIncPosition: p__refLatitude=", p__new__latitude); + loggers::get_instance().log_msg("<<< fx__computeIncPosition: p__refLongitude=", p__new__longitude); + + } + } // namespace ItsRSUsSimulator__Functions diff --git a/ccsrc/Externals/LibItsMbr_externals.cc b/ccsrc/Externals/LibItsMbr_externals.cc new file mode 100644 index 0000000000000000000000000000000000000000..3e114b43e6cccbfc28935b18efa05d95b2ce0632 --- /dev/null +++ b/ccsrc/Externals/LibItsMbr_externals.cc @@ -0,0 +1,18 @@ +/*! + * \file LibItsMbr_externals.cc + * \brief Source file for PKI externl functions. + * \author ETSI STF594 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ + +//#include "LibItsMbr_Functions.hh" + +#include "loggers.hh" + +namespace LibItsMbr__Functions { + +} // End of namespace LibItsMbr__Functions diff --git a/ccsrc/Externals/LibItsPki_externals.cc b/ccsrc/Externals/LibItsPki_externals.cc index 91aa8222f6193b465a269b564dd1af2be054256d..bfa9bb881352a46ede6e66dbecc864b8be73aae6 100644 --- a/ccsrc/Externals/LibItsPki_externals.cc +++ b/ccsrc/Externals/LibItsPki_externals.cc @@ -1,18 +1,18 @@ -/*! - * \file LibItsPki_externals.cc - * \brief Source file for PKI externl functions. - * \author ETSI STF594 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ - -#include "LibItsPki_Functions.hh" - -#include "loggers.hh" - -namespace LibItsPki__Functions { - -} // End of namespace LibItsPki__Functions +/*! + * \file LibItsPki_externals.cc + * \brief Source file for PKI externl functions. + * \author ETSI STF594 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ + +#include "LibItsPki_Functions.hh" + +#include "loggers.hh" + +namespace LibItsPki__Functions { + +} // End of namespace LibItsPki__Functions diff --git a/ccsrc/Externals/LibItsSecurity_externals.cc b/ccsrc/Externals/LibItsSecurity_externals.cc index 36d0f670dd81e1b87b4c6ab3033f8c27bf6d53fe..e71475070481ba15e6c4761eafeb7a75259535de 100644 --- a/ccsrc/Externals/LibItsSecurity_externals.cc +++ b/ccsrc/Externals/LibItsSecurity_externals.cc @@ -1,1666 +1,2231 @@ -/*! - * \file LibItsSecurity_externals.cc - * \brief Source file for Security externl functions. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#include - -#include "LibItsCommon_Functions.hh" -#include "LibItsSecurity_Functions.hh" - -#include "hmac.hh" -#include "sha256.hh" -#include "sha384.hh" - -#include "security_ecc.hh" - -#include "security_services.hh" - -#include "geospacial.hh" - -#include -#include - -#include "loggers.hh" - -namespace LibItsSecurity__Functions { - - static std::unique_ptr g(new geospacial); - - // FIXME Unify code with security_services - - /** - * \fn OCTETSTRING fx_hashWithSha256(const OCTETSTRING& p__toBeHashedData); - * \brief Produces a 256-bit (32-bytes) hash value - * \param[in] p__toBeHashedData The data to be used to calculate the hash value - * \return The hash value - */ - OCTETSTRING fx__hashWithSha256(const OCTETSTRING &p__toBeHashedData) { - loggers::get_instance().log_msg(">>> fx__hashWithSha256: p__toBeHashedData= ", p__toBeHashedData); - - sha256 hash; - OCTETSTRING hashData; - hash.generate(p__toBeHashedData, hashData); - loggers::get_instance().log_msg("fx__hashWithSha256: hashData= ", hashData); - return hashData; - } // End of function fx__hashWithSha256 - - /** - * \fn OCTETSTRING fx_hashWithSha384(const OCTETSTRING& p__toBeHashedData); - * \brief Produces a 384-bit (48-bytes) hash value - * \param[in] p__toBeHashedData Data to be used to calculate the hash value - * \return The hash value - */ - OCTETSTRING fx__hashWithSha384(const OCTETSTRING &p__toBeHashedData) { - sha384 hash; - OCTETSTRING hashData; - hash.generate(p__toBeHashedData, hashData); - loggers::get_instance().log_msg("fx__hashWithSha384: hashData= ", hashData); - return hashData; - } // End of function fx__hashWithSha384 - - /** - * \fn OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); - * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 - * \param[in] p__toBeSignedSecuredMessage The data to be signed - * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate - * \param[in] p__privateKey The private key - * \return The signature value - */ - OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__privateKey) { - loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: data=", p__toBeSignedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: issuer=", p__certificateIssuer); - loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: private key=", p__privateKey); - - // Sanity checks - if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) { - loggers::get_instance().log("fx__signWithEcdsaNistp256WithSha256: Wrong parameters"); - return OCTETSTRING(0, nullptr); - } - - // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha256 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeSignedSecuredMessage, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha256_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Data input) || Hash (Signer identifier input)=", hashData1); - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Calculate the signature - security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashData, r_sig, s_sig) == 0) { - OCTETSTRING os = r_sig + s_sig; - loggers::get_instance().log_msg("r_sig= ", r_sig); - loggers::get_instance().log_msg("s_sig= ", s_sig); - loggers::get_instance().log_msg("sig= ", os); - return os; - } - - return OCTETSTRING(0, nullptr); - } - - /** - * \fn OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); - * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on raw data - * \param[in] p__toBeSignedSecuredMessage The data to be signed - * \param[in] p__privateKey The private key - * \return The signature value - */ - OCTETSTRING fx__test__signWithEcdsaNistp256WithSha256(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__privateKey) { - loggers::get_instance().log_msg(">>> fx__test__signWithEcdsaNistp256WithSha256: data=", p__toBeSignedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__test__signWithEcdsaNistp256WithSha256: private key=", p__privateKey); - - // Sanity checks - if (p__privateKey.lengthof() != 32) { - loggers::get_instance().log("fx__test__signWithEcdsaNistp256WithSha256: Wrong parameters"); - return OCTETSTRING(0, nullptr); - } - - // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha256 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeSignedSecuredMessage, hashData1); - loggers::get_instance().log_msg("fx__test__signWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); - // Calculate the signature - security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashData1, r_sig, s_sig) == 0) { - OCTETSTRING os = r_sig + s_sig; - loggers::get_instance().log_msg("r_sig= ", r_sig); - loggers::get_instance().log_msg("s_sig= ", s_sig); - loggers::get_instance().log_msg("sig= ", os); - return os; - } - - return OCTETSTRING(0, nullptr); - } - - /** - * \fn OCTETSTRING fx__signWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); - * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 - * \param[in] p__toBeSignedSecuredMessage The data to be signed - * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate - * \param[in] p__privateKey The private key - * \return The signature value - */ - OCTETSTRING fx__signWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__privateKey) { - loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp256r1WithSha256: data=", p__toBeSignedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp256r1WithSha256: issuer=", p__certificateIssuer); - loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp256r1WithSha256: private key=", p__privateKey); - - // Sanity checks - if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) { - loggers::get_instance().log("fx__signWithEcdsaBrainpoolp256r1WithSha256: Wrong parameters"); - return OCTETSTRING(0, nullptr); - } - - // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha256 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeSignedSecuredMessage, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha256_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Calculate the signature - security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__privateKey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashData, r_sig, s_sig) == 0) { - OCTETSTRING os = r_sig + s_sig; - loggers::get_instance().log_msg("r_sig= ", r_sig); - loggers::get_instance().log_msg("s_sig= ", s_sig); - loggers::get_instance().log_msg("sig= ", os); - return os; - } - - return OCTETSTRING(0, nullptr); - } - - /** - * \fn OCTETSTRING fx__signWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); - * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 - * \param[in] p__toBeSignedSecuredMessage The data to be signed - * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate - * \param[in] p__privateKey The private key - * \return The signature value - */ - OCTETSTRING fx__signWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__privateKey) { - loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp384r1WithSha384: data=", p__toBeSignedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp384r1WithSha384: issuer=", p__certificateIssuer); - loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp384r1WithSha384: private key=", p__privateKey); - - // Sanity checks - if ((p__certificateIssuer.lengthof() != 48) || (p__privateKey.lengthof() != 48)) { - loggers::get_instance().log("fx__signWithEcdsaBrainpoolp384r1WithSha384: Wrong parameters"); - return OCTETSTRING(0, nullptr); - } - - // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha384 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeSignedSecuredMessage, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha384_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Calculate the signature - security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__privateKey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashData, r_sig, s_sig) == 0) { - OCTETSTRING os = r_sig + s_sig; - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: r_sig= ", r_sig); - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: s_sig= ", s_sig); - loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: sig= ", os); - return os; - } - - return OCTETSTRING(0, nullptr); - } - - /** - * \fn OCTETSTRING fx__signWithEcdsaNistp384WithSha384(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); - * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 - * \param[in] p__toBeSignedSecuredMessage The data to be signed - * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate - * \param[in] p__privateKey The private key - * \return The signature value - */ - OCTETSTRING fx__signWithEcdsaNistp384WithSha384(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__privateKey) { - loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp384WithSha384: data=", p__toBeSignedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp384WithSha384: issuer=", p__certificateIssuer); - loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp384WithSha384: private key=", p__privateKey); - - // Sanity checks - if ((p__certificateIssuer.lengthof() != 48) || (p__privateKey.lengthof() != 48)) { - loggers::get_instance().log("fx__signWithEcdsaNistp384WithSha384: Wrong parameters"); - return OCTETSTRING(0, nullptr); - } - - // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha384 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeSignedSecuredMessage, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha384_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Calculate the signature - security_ecc k(ec_elliptic_curves::nist_p_384, p__privateKey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashData, r_sig, s_sig) == 0) { - OCTETSTRING os = r_sig + s_sig; - loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: r_sig= ", r_sig); - loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: s_sig= ", s_sig); - loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: sig= ", os); - return os; - } - - return OCTETSTRING(0, nullptr); - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& - * p__ecdsaNistp256PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData The - * data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] - * p__signature The signature \param[in] p__ecdsaNistp256PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false - * otherwise - */ - BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaNistp256PublicKeyCompressed, - const INTEGER &p__compressedMode) { - // Sanity checks - if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyCompressed.lengthof() != 32)) { - loggers::get_instance().log("fx__verifyWithEcdsaNistp256WithSha256: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha256 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha256_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Check the signature - security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyCompressed, - (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - if (k.sign_verif(hashData, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__ecdsaNistp256PublicKeyCompressed); - * \brief Verify the signature of the specified data based on raw data - * \param[in] p__toBeVerifiedData The data to be verified - * \param[in] p__signature The signature - * \param[in] p__ecdsaNistp256PublicKeyCompressed The compressed public key (x coordinate only) - * \return true on success, false otherwise - */ - BOOLEAN fx__test__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__signature, - const OCTETSTRING &p__ecdsaNistp256PublicKeyCompressed, const INTEGER &p__compressedMode) { - // Sanity checks - if ((p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyCompressed.lengthof() != 32)) { - loggers::get_instance().log("fx__test__verifyWithEcdsaNistp256WithSha256: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha256 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - loggers::get_instance().log_msg("fx__test__verifyWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); - // Check the signature - security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyCompressed, - (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - if (k.sign_verif(hashData1, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& - * p__ecdsaNistp256PublicKeyX, const OCTETSTRING& p__ecdsaNistp256PublicKeyY); \brief Verify the signature of the specified data based on standard IEEE 1609.2 - * \param[in] p__toBeVerifiedData The data to be verified - * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate - * \param[in] p__signature The signature - * \param[in] p__ecdsaNistp256PublicKeyX The public key (x coordinate) - * \param[in] p__ecdsaNistp256PublicKeyY The public key (y coordinate) - * \return true on success, false otherwise - */ - BOOLEAN fx__verifyWithEcdsaNistp256WithSha256__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaNistp256PublicKeyX, - const OCTETSTRING &p__ecdsaNistp256PublicKeyY) { - // Sanity checks - if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyX.lengthof() != 32) || - (p__ecdsaNistp256PublicKeyY.lengthof() != 32)) { - loggers::get_instance().log("fx__verifyWithEcdsaNistp256WithSha256__1: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha256 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha256_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Check the signature - security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyX, p__ecdsaNistp256PublicKeyY); - // security_ecc k(ec_elliptic_curves::nist_p_256); - if (k.sign_verif(hashData, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& - * p__ecdsaBrainpoolp256PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData - * The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] - * p__signature The signature \param[in] p__ecdsaBrainpoolp256PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false - * otherwise - */ - BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaBrainpoolp256PublicKeyCompressed, - const INTEGER &p__compressedMode) { - // Sanity checks - if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaBrainpoolp256PublicKeyCompressed.lengthof() != 32)) { - loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha256 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha256_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Check the signature - security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__ecdsaBrainpoolp256PublicKeyCompressed, - (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - if (k.sign_verif(hashData, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& - * p__ecdsaBrainpoolp256PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyY); \brief Verify the signature of the specified data based on standard - * IEEE 1609.2 \param[in] p__toBeVerifiedData The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in - * case of self signed certificate \param[in] p__signature The signature \param[in] p__ecdsaBrainpoolp256PublicKeyX The public key (x coordinate) \param[in] - * p__ecdsaBrainpoolp256PublicKeyY The public key (y coordinate) \return true on success, false otherwise - */ - BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaBrainpoolp256PublicKeyX, - const OCTETSTRING &p__ecdsaBrainpoolp256PublicKeyY) { - // Sanity checks - if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaBrainpoolp256PublicKeyX.lengthof() != 32) || - (p__ecdsaBrainpoolp256PublicKeyY.lengthof() != 32)) { - loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha256 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha256_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Check the signature - security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__ecdsaBrainpoolp256PublicKeyX, p__ecdsaBrainpoolp256PublicKeyY); - if (k.sign_verif(hashData, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& - * p__ecdsaBrainpoolp384PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData - * The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] - * p__signature The signature \param[in] p__ecdsaBrainpoolp384PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false - * otherwise - */ - BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaBrainpoolp384PublicKeyCompressed, - const INTEGER &p__compressedMode) { - // Sanity checks - if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaBrainpoolp384PublicKeyCompressed.lengthof() != 48)) { - loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha384 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha384_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Check the signature - security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__ecdsaBrainpoolp384PublicKeyCompressed, - (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - if (k.sign_verif(hashData, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& - * p__ecdsaBrainpoolp384PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY); \brief Verify the signature of the specified data based on standard - * IEEE 1609.2 \param[in] p__toBeVerifiedData The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in - * case of self signed certificate \param[in] p__signature The signature \param[in] p__ecdsaBrainpoolp384PublicKeyX The public key (x coordinate) \param[in] - * p__ecdsaBrainpoolp384PublicKeyY The public key (y coordinate) \return true on success, false otherwise - */ - BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaBrainpoolp384PublicKeyX, - const OCTETSTRING &p__ecdsaBrainpoolp384PublicKeyY) { - // Sanity checks - if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaBrainpoolp384PublicKeyX.lengthof() != 48) || - (p__ecdsaBrainpoolp384PublicKeyY.lengthof() != 48)) { - loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp384r1WithSha384__1: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha384 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha384_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Check the signature - security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__ecdsaBrainpoolp384PublicKeyX, p__ecdsaBrainpoolp384PublicKeyY); - if (k.sign_verif(hashData, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaNistp384WithSha384(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& - * p__ecdsaBrainpoolp384PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData - * The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] - * p__signature The signature \param[in] p__ecdsaBrainpoolp384PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false - * otherwise - */ - BOOLEAN fx__verifyWithEcdsaNistp384WithSha384(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaNistp384PublicKeyCompressed, - const INTEGER &p__compressedMode) { - // Sanity checks - if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaNistp384PublicKeyCompressed.lengthof() != 48)) { - loggers::get_instance().log("fx__verifyWithEcdsaNistp384WithSha384: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha384 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha384_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Check the signature - security_ecc k(ec_elliptic_curves::nist_p_384, p__ecdsaNistp384PublicKeyCompressed, - (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - if (k.sign_verif(hashData, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& - * p__ecdsaBrainpoolp384PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY); \brief Verify the signature of the specified data based on standard - * IEEE 1609.2 \param[in] p__toBeVerifiedData The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in - * case of self signed certificate \param[in] p__signature The signature \param[in] p__ecdsaBrainpoolp384PublicKeyX The public key (x coordinate) \param[in] - * p__ecdsaBrainpoolp384PublicKeyY The public key (y coordinate) \return true on success, false otherwise - */ - BOOLEAN fx__verifyWithEcdsaNistp384WithSha384__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, - const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaNistp384PublicKeyX, - const OCTETSTRING &p__ecdsaNistp384PublicKeyY) { - // Sanity checks - if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaNistp384PublicKeyX.lengthof() != 48) || - (p__ecdsaNistp384PublicKeyY.lengthof() != 48)) { - loggers::get_instance().log("fx__verifyWithEcdsaNistp384WithSha384__1: Wrong parameters"); - return FALSE; - } - - // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - sha384 hash; - OCTETSTRING hashData1; // Hash (Data input) - hash.generate(p__toBeVerifiedData, hashData1); - OCTETSTRING hashData2; // Hash (Signer identifier input) - if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) - hashData2 = p__certificateIssuer; - } else { - hashData2 = hash.get_sha384_empty_string(); // Hash of empty string - } - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384__1: Hash (Data input)=", hashData1); - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384__1: Hash (Signer identifier input)=", hashData2); - hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) - OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - hash.generate(hashData1, hashData); - loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); - // Check the signature - security_ecc k(ec_elliptic_curves::nist_p_384, p__ecdsaNistp384PublicKeyX, p__ecdsaNistp384PublicKeyY); - if (k.sign_verif(hashData, p__signature) == 0) { - return TRUE; - } - - return FALSE; - } - - /** - * \fn OCTETSTRING fx__hmac__sha256(const OCTETSTRING& p__k, const OCTETSTRING& p__m); - * \brief Generate a HMAC-SHA256 value based on the provided secret key - * \param[in] p__k The secret key used for the HMAC calculation - * \param[in] p__m The message - * \return The HMAC value resized to 16-byte - */ - OCTETSTRING fx__hmac__sha256(const OCTETSTRING &p__k, const OCTETSTRING &p__m) { - loggers::get_instance().log_msg(">>> fx__hmac__sha256: p__k=", p__k); - loggers::get_instance().log_msg(">>> fx__hmac__sha256: p__m=", p__m); - - hmac h(hash_algorithms::sha_256); // TODO Use ec_encryption_algorithm - OCTETSTRING t; - if (h.generate(p__m, p__k, t) == -1) { - loggers::get_instance().warning("fx__hmac__sha256: Failed to generate HMAC"); - return OCTETSTRING(0, nullptr); - } - - loggers::get_instance().log_msg("<<< fx__hmac__sha256: HMAC: ", t); - return t; - } - - /** - * \fn OCTETSTRING fx__encrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt); - * \brief Encrypt the message using AES 128 CCM algorithm - * \param[in] p__k The symmetric encryption key - * \param[in] p__n The initial vector, nonce vector - * \param[in] p__pt The message to encrypt - * \return The encrypted message concatenated to the AES 128 CCM tag - */ - OCTETSTRING fx__encrypt__aes__128__ccm__test(const OCTETSTRING &p__k, const OCTETSTRING &p__n, const OCTETSTRING &p__pt) { - loggers::get_instance().log(">>> fx__encrypt__aes__128__ccm__test"); - - security_ecc ec(ec_elliptic_curves::nist_p_256); - OCTETSTRING enc_message; - if (ec.encrypt(encryption_algotithm::aes_128_ccm, p__k, p__n, p__pt, enc_message) == -1) { - loggers::get_instance().warning("fx__encrypt__aes__128__ccm__test: Failed to encrypt message"); - return OCTETSTRING(0, nullptr); - } - OCTETSTRING os(enc_message + ec.tag()); - loggers::get_instance().log_msg("fx__encrypt__aes__128__ccm__test: encrypted message: ", os); - - return os; - } - - /** - * \fn OCTETSTRING fx__encrypt__aes__128__gcm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt); - * \brief Encrypt the message using AES 128 GCM algorithm - * \param[in] p__k The symmetric encryption key - * \param[in] p__n The initial vector, nonce vector - * \param[in] p__pt The message to encrypt - * \return The encrypted message concatenated to the AES 128 CCM tag - */ - OCTETSTRING fx__encrypt__aes__128__gcm__test(const OCTETSTRING &p__k, const OCTETSTRING &p__n, const OCTETSTRING &p__pt) { - loggers::get_instance().log(">>> fx__encrypt__aes__128__gcm__test"); - - security_ecc ec(ec_elliptic_curves::nist_p_256); - OCTETSTRING enc_message; - if (ec.encrypt(encryption_algotithm::aes_128_gcm, p__k, p__n, p__pt, enc_message) == -1) { - loggers::get_instance().warning("fx__encrypt__aes__128__gcm__test: Failed to encrypt message"); - return OCTETSTRING(0, nullptr); - } - OCTETSTRING os(enc_message + ec.tag()); - loggers::get_instance().log_msg("fx__encrypt__aes__128__gcm__test: encrypted message: ", os); - - return os; - } - - /** - * \fn OCTETSTRING fx__decrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__ct); - * \brief Encrypt the message using AES 128 CCM algorithm - * \param[in] p__k The symmetric encryption key - * \param[in] p__n The initial vector, nonce vector - * \param[in] p__ct The encrypted message concatenated to the AES 128 CCM tag - * \return The original message - */ - OCTETSTRING fx__decrypt__aes__128__ccm__test(const OCTETSTRING &p__k, const OCTETSTRING &p__n, const OCTETSTRING &p__ct) { - loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__k: ", p__k); - loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__n: ", p__n); - loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__ct: ", p__ct); - - security_ecc ec(ec_elliptic_curves::nist_p_256); - // Extract the tag - OCTETSTRING tag(16, p__ct.lengthof() - 16 + static_cast(p__ct)); - loggers::get_instance().log_msg("fx__decrypt__aes__128__ccm__test: tag: ", tag); - // Remove the tag from the end of the encrypted message - OCTETSTRING ct(p__ct.lengthof() - 16, static_cast(p__ct)); - loggers::get_instance().log_msg("fx__decrypt__aes__128__ccm__test: ct: ", ct); - - OCTETSTRING message; - if (ec.decrypt(encryption_algotithm::aes_128_ccm, p__k, p__n, tag, ct, message) == -1) { - loggers::get_instance().warning("fx__decrypt__aes__128__ccm__test: Failed to decrypt message"); - return OCTETSTRING(0, nullptr); - } - loggers::get_instance().log_to_hexa("fx__decrypt__aes__128__ccm__test: decrypted message: ", message); - - return message; - } - - /** - * \fn OCTETSTRING fx__encryptWithEciesNistp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyX, const - * OCTETSTRING& p__recipientsPublicKeyY, OCTETSTRING& p__publicEphemeralKeyX, OCTETSTRING& p__publicEphemeralKeyY, OCTETSTRING& p__encrypted__sym__key, - * OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce); \brief Encrypt the message using ECIES algorithm to encrypt AES 128 CCM symmetric key, as - * defined in IEEE Std 1609.2-2017 \param[in] p__toBeEncryptedSecuredMessage The message to be encrypted \param[in] p__recipientsPublicKeyCompressed The - * Recipient's compressed public key \param[in] p__compressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise \param[out] - * p__publicEphemeralKeyCompressed The public ephemeral compressed key \param[out] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of - * Y-coordinate is 0, 1 otherwise \param[out] p__encrypted__sym__key The encrypted AES 128 symmetric key \param[out] p__authentication__vector The tag of the - * encrypted AES 128 symmetric key \param[out] p__nonce The nonce vector \return The original message \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key - * encryption algorithms: ECIES \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ \see - * http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf - */ - // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function - OCTETSTRING fx__encryptWithEciesNistp256WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, const OCTETSTRING &p__recipientsPublicKeyCompressed, - const INTEGER &p__compressedMode, const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyCompressed, - INTEGER &p__ephemeralCompressedMode, OCTETSTRING &p__aes__sym__key, OCTETSTRING &p__encrypted__sym__key, - OCTETSTRING &p__authentication__vector, OCTETSTRING &p__nonce) { - loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed); - loggers::get_instance().log(">>> fx__encryptWithEciesNistp256WithSha256: p__compressedMode: %d", static_cast(p__compressedMode)); - loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__salt: ", p__salt); - - // 1. Generate new Private/Public Ephemeral key - std::unique_ptr ec; - ec.reset(new security_ecc(ec_elliptic_curves::nist_p_256)); - if (ec->generate() == -1) { - loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to generate ephemeral keys"); - return OCTETSTRING(0, nullptr); - } - // 2. Generate and derive shared secret based on recipient's private keys - security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__recipientsPublicKeyCompressed, - (static_cast(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - if (ec->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { - loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to generate and derive secret key"); - return OCTETSTRING(0, nullptr); - } - - // Set the AES symmetric key - loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: AES symmetric key: ", ec->symmetric_encryption_key()); - p__aes__sym__key = ec->symmetric_encryption_key(); - loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__aes__sym__key: ", p__aes__sym__key); - // Set the encrypted symmetric key - loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: Encrypted symmetric key: ", ec->encrypted_symmetric_key()); - p__encrypted__sym__key = ec->encrypted_symmetric_key(); - loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); - // Set the tag of the symmetric key encryption - p__authentication__vector = ec->tag(); - loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector); - // Set ephemeral public keys - p__publicEphemeralKeyCompressed = ec->public_key_compressed(); - loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed); - p__ephemeralCompressedMode = (ec->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1; - loggers::get_instance().log("fx__encryptWithEciesNistp256WithSha256: Ephemeral public compressed mode: %d: ", (int)p__ephemeralCompressedMode); - // 3. Retrieve AES 128 parameters - p__nonce = ec->nonce(); - loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce); - // 4. Encrypt the data using AES-128 CCM - OCTETSTRING enc_message; - if (ec->encrypt(encryption_algotithm::aes_128_ccm, ec->symmetric_encryption_key(), ec->nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { - loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to encrypt message"); - return OCTETSTRING(0, nullptr); - } - enc_message += ec->tag(); - loggers::get_instance().log_to_hexa("fx__encryptWithEciesNistp256WithSha256: enc message||Tag: ", enc_message); - - return enc_message; - } - - /** - * @desc Test function for ECIES NIST P-256 Encryption with SHA-256 - * @remark For the purpose of testing, the content of p__toBeEncryptedSecuredMessage is the AES 128 symmetric key to be encrypted - */ - OCTETSTRING fx__test__encryptWithEciesNistp256WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, const OCTETSTRING &p__privateEphemeralKey, - const OCTETSTRING &p__recipientPublicKeyX, const OCTETSTRING &p__recipientPublicKeyY, - const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyX, OCTETSTRING &p__publicEphemeralKeyY, - OCTETSTRING &p__aes__sym__key, OCTETSTRING &p__encrypted__sym__key, - OCTETSTRING &p__authentication__vector, OCTETSTRING &p__nonce) { - - // 1. Generate new ephemeral Private/Public keys - security_ecc ec(ec_elliptic_curves::nist_p_256, p__privateEphemeralKey); - p__publicEphemeralKeyX = ec.public_key_x(); - p__publicEphemeralKeyY = ec.public_key_y(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Vx=", p__publicEphemeralKeyX); - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Vy=", p__publicEphemeralKeyY); - - // 2. Generate and derive shared secret - security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__recipientPublicKeyX, p__recipientPublicKeyY); - ec.symmetric_encryption_key(p__toBeEncryptedSecuredMessage); - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: ", ec.encrypted_symmetric_key()); - if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { - loggers::get_instance().warning("fx__test__encryptWithEciesNistp256WithSha256: Failed to generate and derive secret key"); - return OCTETSTRING(0, nullptr); - } - - // Set the AES symmetric key - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: AES symmetric key: ", ec.symmetric_encryption_key()); - p__aes__sym__key = ec.symmetric_encryption_key(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__aes__sym__key: ", p__aes__sym__key); - // Set the encrypted symmetric key - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Encrypted symmetric key: ", ec.encrypted_symmetric_key()); - p__encrypted__sym__key = ec.encrypted_symmetric_key(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); - // Set the tag of the symmetric key encryption - p__authentication__vector = ec.tag(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector); - // 3. Retrieve AES 128 parameters - p__nonce = ec.nonce(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce); - // 4. Encrypt the data using AES-128 CCM - OCTETSTRING enc_message; - if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { - loggers::get_instance().warning("fx__test__encryptWithEciesNistp256WithSha256: Failed to encrypt message"); - return OCTETSTRING(0, nullptr); - } - enc_message += ec.tag(); - loggers::get_instance().log_to_hexa("fx__test__encryptWithEciesNistp256WithSha256: enc message||Tag: ", enc_message); - - return enc_message; - } - - /** - * \fn OCTETSTRING fx__decryptWithEciesNistp256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const - * OCTETSTRING& p__publicEphemeralKeyX, const OCTETSTRING& p__publicEphemeralKeyY, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& - * p__authentication__vector, const OCTETSTRING& p__nonce); \brief Decrypt the message using ECIES algorithm to decrypt AES 128 CCM symmetric key, as defined - * in IEEE Std 1609.2-2017 \param[in] p__encryptedSecuredMessage The encrypted message \param[in] p__privateEncKey The private encryption key \param[in] - * p__publicEphemeralKeyCompressed The public ephemeral compressed key \param[in] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of - * Y-coordinate is 0, 1 otherwise \param[in] p__encrypted__sym__key The encrypted AES 128 symmetric key \param[in] p__authentication__vector The tag of the - * encrypted AES 128 symmetric key \param[in] p__nonce The nonce vector \return The original message \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key - * encryption algorithms: ECIES \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ \see - * http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf - */ - // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function - OCTETSTRING fx__decryptWithEciesNistp256WithSha256(const OCTETSTRING &p__encryptedSecuredMessage, const OCTETSTRING &p__privateEncKey, - const OCTETSTRING &p__publicEphemeralKeyCompressed, const INTEGER &p__ephemeralCompressedMode, - const OCTETSTRING &p__encrypted__sym__key, const OCTETSTRING &p__authentication__vector, - const OCTETSTRING &p__nonce, const OCTETSTRING &p__salt, OCTETSTRING &p__aes__sym__enc__key) { - loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__privateEncKey: ", p__privateEncKey); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__publicEphemeralKeyCompressed: ", p__publicEphemeralKeyCompressed); - loggers::get_instance().log(">>> fx__decryptWithEciesNistp256WithSha256: p__ephemeralCompressedMode: %d", static_cast(p__ephemeralCompressedMode)); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__salt", p__salt); - - // 1. Create security_ecc instance based on recipient's private key - security_ecc ec(ec_elliptic_curves::nist_p_256, p__privateEncKey); - security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__publicEphemeralKeyCompressed, - (static_cast(p__ephemeralCompressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - - // 2. Generate the shared secret value based on public ephemeral keys will be required - if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__encrypted__sym__key, - p__nonce, p__authentication__vector, p__salt) == -1) { - loggers::get_instance().warning("fx__decryptWithEciesNistp256WithSha256: Failed to generate shared secret"); - return OCTETSTRING(0, nullptr); - } - - // Decrypt the message - OCTETSTRING enc_message(p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof(), - static_cast(p__encryptedSecuredMessage)); // Extract the encrypted message - loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: enc_message: ", enc_message); // Extract the ctag value - OCTETSTRING tag(ec.tag().lengthof(), - static_cast(p__encryptedSecuredMessage) + p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof()); - loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: tag: ", tag); - OCTETSTRING message; - if (ec.decrypt(tag, enc_message, message) == -1) { - loggers::get_instance().warning("fx__decryptWithEciesNistp256WithSha256: Failed to generate shared secret"); - return OCTETSTRING(0, nullptr); - } - loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: dec message: ", message); - p__aes__sym__enc__key = ec.symmetric_encryption_key(); - loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: AES 128 encryption key: ", p__aes__sym__enc__key); - - return message; - } - - OCTETSTRING fx__encryptWithEciesBrainpoolp256r1WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, - const OCTETSTRING &p__recipientsPublicKeyCompressed, const INTEGER &p__compressedMode, - const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyCompressed, - INTEGER &p__ephemeralCompressedMode, OCTETSTRING &p__aes__sym__key, - OCTETSTRING &p__encrypted__sym__key, OCTETSTRING &p__authentication__vector, - OCTETSTRING &p__nonce) { - loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed); - loggers::get_instance().log(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__compressedMode: %d", static_cast(p__compressedMode)); - loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__salt: ", p__salt); - - // 1. Generate new Private/Public Ephemeral key - std::unique_ptr ec; - ec.reset(new security_ecc(ec_elliptic_curves::brainpool_p_256_r1)); - if (ec->generate() == -1) { - loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate ephemeral keys"); - return OCTETSTRING(0, nullptr); - } - // 2. Generate and derive shared secret based on recipient's private keys - security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientsPublicKeyCompressed, - (static_cast(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - if (ec->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { - loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate and derive secret key"); - return OCTETSTRING(0, nullptr); - } - - // Set the AES symmetric key - loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: AES symmetric key: ", ec->symmetric_encryption_key()); - p__aes__sym__key = ec->symmetric_encryption_key(); - loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__aes__sym__key: ", p__aes__sym__key); - // Set the encrypted symmetric key - loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: Encrypted symmetric key: ", ec->encrypted_symmetric_key()); - p__encrypted__sym__key = ec->encrypted_symmetric_key(); - loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); - // Set the tag of the symmetric key encryption - p__authentication__vector = ec->tag(); - loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__authentication__vector: ", p__authentication__vector); - // Set ephemeral public keys - p__publicEphemeralKeyCompressed = ec->public_key_compressed(); - loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed); - p__ephemeralCompressedMode = (ec->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1; - loggers::get_instance().log("fx__encryptWithEciesBrainpoolp256r1WithSha256: Ephemeral public compressed mode: %d: ", (int)p__ephemeralCompressedMode); - // 3. Retrieve AES 128 parameters - p__nonce = ec->nonce(); - loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__nonce: ", p__nonce); - // 4. Encrypt the data using AES-128 CCM - OCTETSTRING enc_message; - if (ec->encrypt(encryption_algotithm::aes_128_ccm, ec->symmetric_encryption_key(), ec->nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { - loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to encrypt message"); - return OCTETSTRING(0, nullptr); - } - enc_message += ec->tag(); - loggers::get_instance().log_to_hexa("fx__encryptWithEciesBrainpoolp256r1WithSha256: enc message||Tag: ", enc_message); - - return enc_message; - } - - /** - * @desc Test function for ECIES BRAINPOOL P-256r1 Encryption with SHA-256 - * @remark For the purpose of testing, the content of p__toBeEncryptedSecuredMessage is the AES 128 symmetric key to be encrypted - */ - OCTETSTRING fx__test__encryptWithEciesBrainpoolp256r1WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, const OCTETSTRING &p__privateEphemeralKey, - const OCTETSTRING &p__recipientPublicKeyX, const OCTETSTRING &p__recipientPublicKeyY, - const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyX, - OCTETSTRING &p__publicEphemeralKeyY, OCTETSTRING &p__aes__sym__key, - OCTETSTRING &p__encrypted__sym__key, OCTETSTRING &p__authentication__vector, - OCTETSTRING &p__nonce) { - - // 1. Generate new ephemeral Private/Public keys - security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1, p__privateEphemeralKey); - p__publicEphemeralKeyX = ec.public_key_x(); - p__publicEphemeralKeyY = ec.public_key_y(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Vx=", p__publicEphemeralKeyX); - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Vy=", p__publicEphemeralKeyY); - - // 2. Generate and derive shared secret - security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientPublicKeyX, p__recipientPublicKeyY); - ec.symmetric_encryption_key(p__toBeEncryptedSecuredMessage); - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: ", ec.encrypted_symmetric_key()); - if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { - loggers::get_instance().warning("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate and derive secret key"); - return OCTETSTRING(0, nullptr); - } - - // Set the AES symmetric key - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: AES symmetric key: ", ec.symmetric_encryption_key()); - p__aes__sym__key = ec.symmetric_encryption_key(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__aes__sym__key: ", p__aes__sym__key); - // Set the encrypted symmetric key - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Encrypted symmetric key: ", ec.encrypted_symmetric_key()); - p__encrypted__sym__key = ec.encrypted_symmetric_key(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); - // Set the tag of the symmetric key encryption - p__authentication__vector = ec.tag(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__authentication__vector: ", p__authentication__vector); - // 3. Retrieve AES 128 parameters - p__nonce = ec.nonce(); - loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__nonce: ", p__nonce); - // 4. Encrypt the data using AES-128 CCM - OCTETSTRING enc_message; - if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { - loggers::get_instance().warning("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Failed to encrypt message"); - return OCTETSTRING(0, nullptr); - } - enc_message += ec.tag(); - loggers::get_instance().log_to_hexa("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: enc message||Tag: ", enc_message); - - return enc_message; - } - - OCTETSTRING fx__decryptWithEciesBrainpoolp256r1WithSha256(const OCTETSTRING &p__encryptedSecuredMessage, const OCTETSTRING &p__privateEncKey, - const OCTETSTRING &p__publicEphemeralKeyCompressed, const INTEGER &p__ephemeralCompressedMode, - const OCTETSTRING &p__encrypted__sym__key, const OCTETSTRING &p__authentication__vector, - const OCTETSTRING &p__nonce, const OCTETSTRING &p__salt, OCTETSTRING &p__aes__sym__enc__key) { - loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__privateEncKey: ", p__privateEncKey); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__publicEphemeralKeyCompressed: ", p__publicEphemeralKeyCompressed); - loggers::get_instance().log(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__ephemeralCompressedMode: %d", - static_cast(p__ephemeralCompressedMode)); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__nonce: ", p__nonce); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__authentication__vector: ", p__authentication__vector); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); - loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__salt", p__salt); - - // 1. Create security_ecc instance based on public ephemeral keys - security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1, p__privateEncKey); - security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__publicEphemeralKeyCompressed, - (static_cast(p__ephemeralCompressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); - - // 2. Generate the shared secret value based on public ephemeral keys will be required - if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__encrypted__sym__key, - p__nonce, p__authentication__vector, OCTETSTRING(0, nullptr)) == -1) { - loggers::get_instance().warning("fx__decryptWithEciesBrainpoolp256r1WithSha256: Failed to generate shared secret"); - return OCTETSTRING(0, nullptr); - } - - // Decrypt the message - OCTETSTRING enc_message(p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof(), - static_cast(p__encryptedSecuredMessage)); // Extract the encrypted message - loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256r1WithSha256: enc_message: ", enc_message); // Extract the ctag value - OCTETSTRING tag(ec.tag().lengthof(), - static_cast(p__encryptedSecuredMessage) + p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof()); - loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256r1WithSha256: tag: ", tag); - OCTETSTRING message; - if (ec.decrypt(tag, enc_message, message) == -1) { - loggers::get_instance().warning("fx__decryptWithEciesBrainpoolp256r1WithSha256: Failed to generate shared secret"); - return OCTETSTRING(0, nullptr); - } - loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256r1WithSha256: dec message: ", message); - p__aes__sym__enc__key = ec.symmetric_encryption_key(); - loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256r1WithSha256: AES 128 encryption key: ", p__aes__sym__enc__key); - - return message; - } - - /** - * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. - * This function should not be used by the ATS - * \param p_privateKey The new private key value - * \param p_publicKeyX The new public key value (x coordinate) - * \param p_publicKeyX The new public key value (y coordinate) - * \return true on success, false otherwise - fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; - */ - BOOLEAN fx__generateKeyPair__nistp256(OCTETSTRING &p__privateKey, OCTETSTRING &p__publicKeyX, OCTETSTRING &p__publicKeyY, OCTETSTRING &p__publicKeyCompressed, - INTEGER &p__compressedMode) { - security_ecc k(ec_elliptic_curves::nist_p_256); - if (k.generate() != 0) { - p__privateKey = OCTETSTRING(0, nullptr); - p__publicKeyX = OCTETSTRING(0, nullptr); - p__publicKeyY = OCTETSTRING(0, nullptr); - p__publicKeyCompressed = OCTETSTRING(0, nullptr); - return FALSE; - } - // Sanity checks - if (k.private_key().lengthof() != 32) { - loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid private key size"); - return FALSE; - } - if (k.public_key_x().lengthof() != 32) { - loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public key X-coordonate size"); - return FALSE; - } - if (k.public_key_y().lengthof() != 32) { - loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public key Y-coordonate size"); - return FALSE; - } - if (k.public_key_compressed().lengthof() != 32) { - loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public compressed key size"); - return FALSE; - } - p__privateKey = k.private_key(); - p__publicKeyX = k.public_key_x(); - p__publicKeyY = k.public_key_y(); - p__publicKeyCompressed = k.public_key_compressed(); - p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); - - return TRUE; - } - - /** - * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. - * This function should not be used by the ATS - * \param p_privateKey The new private key value - * \param p_publicKeyX The new public key value (x coordinate) - * \param p_publicKeyX The new public key value (y coordinate) - * \return true on success, false otherwise - fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; - */ - BOOLEAN fx__generateKeyPair__brainpoolp256r1(OCTETSTRING &p__privateKey, OCTETSTRING &p__publicKeyX, OCTETSTRING &p__publicKeyY, - OCTETSTRING &p__publicKeyCompressed, INTEGER &p__compressedMode) { - security_ecc k(ec_elliptic_curves::brainpool_p_256_r1); - if (k.generate() != 0) { - p__privateKey = OCTETSTRING(0, nullptr); - p__publicKeyX = OCTETSTRING(0, nullptr); - p__publicKeyY = OCTETSTRING(0, nullptr); - p__publicKeyCompressed = OCTETSTRING(0, nullptr); - return FALSE; - } - - // Sanity checks - if (k.private_key().lengthof() != 32) { - loggers::get_instance().error("fx__generateKeyPair__brainpoolp256r1: Invalid private key size"); - return FALSE; - } - if (k.public_key_x().lengthof() != 32) { - loggers::get_instance().error("fx__generateKeyPair__brainpoolp256r1: Invalid public key X-coordonate size"); - return FALSE; - } - if (k.public_key_y().lengthof() != 32) { - loggers::get_instance().error("fx__generateKeyPair__brainpoolp256r1: Invalid public key Y-coordonate size"); - return FALSE; - } - if (k.public_key_compressed().lengthof() != 32) { - loggers::get_instance().error("fx__generateKeyPair__brainpoolp256r1: Invalid public compressed key size"); - return FALSE; - } - p__privateKey = k.private_key(); - p__publicKeyX = k.public_key_x(); - p__publicKeyY = k.public_key_y(); - p__publicKeyCompressed = k.public_key_compressed(); - p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); - - return TRUE; - } - - /** - * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. - * This function should not be used by the ATS - * \param p_privateKey The new private key value - * \param p_publicKeyX The new public key value (x coordinate) - * \param p_publicKeyX The new public key value (y coordinate) - * \return true on success, false otherwise - fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; - */ - BOOLEAN fx__generateKeyPair__brainpoolp384r1(OCTETSTRING &p__privateKey, OCTETSTRING &p__publicKeyX, OCTETSTRING &p__publicKeyY, - OCTETSTRING &p__publicKeyCompressed, INTEGER &p__compressedMode) { - security_ecc k(ec_elliptic_curves::brainpool_p_384_r1); - if (k.generate() != 0) { - p__privateKey = OCTETSTRING(0, nullptr); - p__publicKeyX = OCTETSTRING(0, nullptr); - p__publicKeyY = OCTETSTRING(0, nullptr); - p__publicKeyCompressed = OCTETSTRING(0, nullptr); - return FALSE; - } - - // Sanity checks - if (k.private_key().lengthof() != 48) { - loggers::get_instance().error("fx__generateKeyPair__brainpoolp384r1: Invalid private key size"); - return FALSE; - } - if (k.public_key_x().lengthof() != 48) { - loggers::get_instance().error("fx__generateKeyPair__brainpoolp384r1: Invalid public key X-coordonate size"); - return FALSE; - } - if (k.public_key_y().lengthof() != 48) { - loggers::get_instance().error("fx__generateKeyPair__brainpoolp384r1: Invalid public key Y-coordonate size"); - return FALSE; - } - if (k.public_key_compressed().lengthof() != 48) { - loggers::get_instance().error("fx__generateKeyPair__brainpoolp384r1: Invalid public compressed key size"); - return FALSE; - } - p__privateKey = k.private_key(); - p__publicKeyX = k.public_key_x(); - p__publicKeyY = k.public_key_y(); - p__publicKeyCompressed = k.public_key_compressed(); - p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); - - return TRUE; - } - - BOOLEAN fx__get__uncompressed__key__nistp256(const OCTETSTRING &p__privateKey, const OCTETSTRING &p__publicKeyCompressed, const INTEGER &p__compressedMode, - OCTETSTRING &p__publicKeyY) { - security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey); - - // Sanity checks - if (k.private_key().lengthof() != 32) { - loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid private key size"); - return FALSE; - } - if (k.public_key_x().lengthof() != 32) { - loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public key X-coordonate size"); - return FALSE; - } - if (k.public_key_y().lengthof() != 32) { - loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public key Y-coordonate size"); - return FALSE; - } - if (k.public_key_compressed().lengthof() != 32) { - loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public compressed key size"); - return FALSE; - } - // if (p__compressedMode != INTEGER((int)k.public_key_compressed_mode())) { - // loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public compressed mode"); - // return FALSE; - // } - // if (p__publicKeyCompressed != k.public_key_compressed()) { - // loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public compressed key value"); - // return FALSE; - // } - - p__publicKeyY = k.public_key_y(); - - return TRUE; - } - - BOOLEAN fx__get__uncompressed__key__brainpoolp256r1(const OCTETSTRING &p__privateKey, const OCTETSTRING &p__publicKeyCompressed, - const INTEGER &p__compressedMode, OCTETSTRING &p__publicKeyY) { - security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__privateKey); - - // Sanity checks - if (k.private_key().lengthof() != 32) { - loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid private key size"); - return FALSE; - } - if (k.public_key_x().lengthof() != 32) { - loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public key X-coordonate size"); - return FALSE; - } - if (k.public_key_y().lengthof() != 32) { - loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public key Y-coordonate size"); - return FALSE; - } - if (k.public_key_compressed().lengthof() != 32) { - loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public compressed key size"); - return FALSE; - } - // if (p__compressedMode != INTEGER((int)k.public_key_compressed_mode())) { - // loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public compressed mode"); - // return FALSE; - // } - // if (p__publicKeyCompressed != k.public_key_compressed()) { - // loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public compressed key value"); - // return FALSE; - // } - - p__publicKeyY = k.public_key_y(); - - return TRUE; - } - - BOOLEAN fx__get__uncompressed__key__brainpoolp384r1(const OCTETSTRING &p__privateKey, const OCTETSTRING &p__publicKeyCompressed, - const INTEGER &p__compressedMode, OCTETSTRING &p__publicKeyY) { - security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__privateKey); - - // Sanity checks - if (k.private_key().lengthof() != 48) { - loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid private key size"); - return FALSE; - } - if (k.public_key_x().lengthof() != 48) { - loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public key X-coordonate size"); - return FALSE; - } - if (k.public_key_y().lengthof() != 48) { - loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public key Y-coordonate size"); - return FALSE; - } - if (k.public_key_compressed().lengthof() != 48) { - loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public compressed key size"); - return FALSE; - } - // if (p__compressedMode != INTEGER((int)k.public_key_compressed_mode())) { - // loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public compressed mode"); - // return FALSE; - // } - // if (p__publicKeyCompressed != k.public_key_compressed()) { - // loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public compressed key value"); - // return FALSE; - // } - - p__publicKeyY = k.public_key_y(); - - return TRUE; - } - - // group encryption - - // group certificatesLoader - - /** - * \brief Load in memory cache the certificates available in the specified directory - * \param p_rootDirectory Root directory to access to the certificates identified by the certificate ID - * \param p_configId A configuration identifier - * @remark This method SHALL be call before any usage of certificates - * \return true on success, false otherwise - fx_loadCertificates(in charstring p_rootDirectory, in charstring p_configId) return boolean; - */ - BOOLEAN fx__loadCertificates(const CHARSTRING &p__rootDirectory, const CHARSTRING &p__configId) { - loggers::get_instance().log(">>> fx__loadCertificates: '%s', '%s'", static_cast(p__rootDirectory), static_cast(p__configId)); - - std::string str(static_cast(p__rootDirectory)); - if (p__configId.lengthof() != 0) { - str += "/"; - str += std::string(static_cast(p__configId)); - } - params_its params; - params.insert(std::pair(std::string("sec_db_path"), str)); - if (security_services::get_instance().setup(params) == -1) { - return FALSE; - } - - return TRUE; - } - - BOOLEAN fx__store__certificate(const CHARSTRING &p__cert__id, const OCTETSTRING &p__cert, const OCTETSTRING &p__private__key, - const OCTETSTRING &p__public__key__x, const OCTETSTRING &p__public__key__y, const OCTETSTRING &p__public__key__compressed, - const INTEGER &p__public__key__compressed__mode, const OCTETSTRING &p__hash, const OCTETSTRING &p__hash__256, - const OCTETSTRING &p__hashid8, const OCTETSTRING &p__issuer, const OCTETSTRING_template &p__private__enc__key, - const OCTETSTRING_template &p__public__enc__key__x, const OCTETSTRING_template &p__public__enc__key__y, - const OCTETSTRING_template &p__public__enc__compressed__key, const INTEGER_template &p__public__enc__key__compressed__mode) { - loggers::get_instance().log(">>> fx__store__certificate: '%s'", static_cast(p__cert__id)); - - int result; - if (!p__private__enc__key.is_omit()) { - const OCTETSTRING private_enc_key = p__private__enc__key.valueof(); - const OCTETSTRING public_enc_key_x = p__public__enc__key__x.valueof(); - const OCTETSTRING public_enc_key_y = p__public__enc__key__y.valueof(); - result = security_services::get_instance().store_certificate( - p__cert__id, p__cert, p__private__key, p__public__key__x, p__public__key__y, p__public__key__compressed, p__public__key__compressed__mode, p__hash, - p__hash__256, p__hashid8, p__issuer, p__private__enc__key.valueof(), p__public__enc__key__x.valueof(), p__public__enc__key__y.valueof(), - p__public__enc__compressed__key.valueof(), p__public__enc__key__compressed__mode.valueof()); - } else { - result = security_services::get_instance().store_certificate( - p__cert__id, p__cert, p__private__key, p__public__key__x, p__public__key__y, p__public__key__compressed, p__public__key__compressed__mode, p__hash, - p__hash__256, p__hashid8, p__issuer, OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), INTEGER(-1)); - } - - return (result == 0); - } - - /** - * \brief Unload from memory cache the certificates - * \return true on success, false otherwise - */ - BOOLEAN fx__unloadCertificates() { return TRUE; } - - /** - * \brief Read the specified certificate - * \param p_certificate_id the certificate identifier - * \param p_certificate the expected certificate - * \return true on success, false otherwise - */ - BOOLEAN fx__readCertificate(const CHARSTRING &p__certificateId, OCTETSTRING &p__certificate) { - loggers::get_instance().log(">>> fx__readCertificate: '%s'", static_cast(p__certificateId)); - - if (security_services::get_instance().read_certificate(p__certificateId, p__certificate) == -1) { - return FALSE; - } - - return TRUE; - } - - BOOLEAN fx__readCertificateFromDigest(const OCTETSTRING &p__digest, CHARSTRING &p__certificateId) { - loggers::get_instance().log_msg(">>> fx__readCertificateFromDigest: ", p__digest); - - if (security_services::get_instance().read_certificate_from_digest(p__digest, p__certificateId) == -1) { - return FALSE; - } - loggers::get_instance().log_msg("fx__readCertificateFromDigest: ", p__certificateId); - - return TRUE; - } - - BOOLEAN fx__readCertificateFromHashedId3(const OCTETSTRING &p__digest, CHARSTRING &p__certificateId) { - loggers::get_instance().log_msg(">>> fx__readCertificateFromHashedId3: ", p__digest); - - if (security_services::get_instance().read_certificate_from_hashed_id3(p__digest, p__certificateId) == -1) { - return FALSE; - } - loggers::get_instance().log_msg("fx__readCertificateFromHashedId3: ", p__certificateId); - - return TRUE; - } - - /** - * \brief Read the specified certificate digest - * \param p_certificate_id the certificate identifier - * \param p_digest the expected certificate - * \return true on success, false otherwise - */ - BOOLEAN fx__readCertificateDigest(const CHARSTRING &p__certificateId, OCTETSTRING &p__digest) { - loggers::get_instance().log(">>> fx__readCertificateDigest: '%s'", static_cast(p__certificateId)); - - if (security_services::get_instance().read_certificate_digest(p__certificateId, p__digest) == -1) { - return FALSE; - } - - return TRUE; - } - - /** - * \brief Read the whole-hash of the certificate - * \param p_certificate_id the certificate identifier - * \param p_hash the expected certificate - * \return true on success, false otherwise - */ - BOOLEAN fx__readCertificateHash(const CHARSTRING &p__certificateId, OCTETSTRING &p__hash) { - loggers::get_instance().log(">>> fx__readCertificateHash: '%s'", static_cast(p__certificateId)); - - if (security_services::get_instance().read_certificate_hash(p__certificateId, p__hash) == -1) { - return FALSE; - } - - return TRUE; - } - - /** - * \brief Read the whole-hash of the certificate using SHA 256 - * \param p_certificate_id the certificate identifier - * \param p_hash the expected certificate - * \return true on success, false otherwise - */ - BOOLEAN fx__readCertificateHash256(const CHARSTRING &p__certificateId, OCTETSTRING &p__hash) { - loggers::get_instance().log(">>> fx__readCertificateHash256: '%s'", static_cast(p__certificateId)); - - if (security_services::get_instance().read_certificate_hash_sha_256(p__certificateId, p__hash) == -1) { - return FALSE; - } - - return TRUE; - } - - /** - * \brief Read the private keys for the specified certificate - * \param p_certificate_id the keys identifier - * \param p_signingPrivateKey the signing private key - * \return true on success, false otherwise - */ - BOOLEAN fx__readSigningKey(const CHARSTRING &p__certificateId, OCTETSTRING &p__signingPrivateKey) { - loggers::get_instance().log(">>> fx__readSigningKey: '%s'", static_cast(p__certificateId)); - - if (security_services::get_instance().read_private_key(p__certificateId, p__signingPrivateKey) == -1) { - return FALSE; - } - - return TRUE; - } - - /** - * \brief Read the private keys for the specified certificate - * \param p_keysId the keys identifier - * \param p_encryptPrivateKey the encrypt private key - * \return true on success, false otherwise - fx_readEncryptingKey(in charstring p_keysId, out Oct32 p_encryptingPrivateKey) return boolean; - */ - BOOLEAN fx__readEncryptingKey(const CHARSTRING &p__certificateId, OCTETSTRING &p__encryptingPrivateKey) { - loggers::get_instance().log(">>> fx__readSigningKey: '%s'", static_cast(p__certificateId)); - - if (security_services::get_instance().read_private_enc_key(p__certificateId, p__encryptingPrivateKey) == -1) { - return FALSE; - } - - return TRUE; - } - - // group geospacial - - /* * \brief Check that given polygon doesn't have neither self-intersections nor holes. - * \param p_region Polygonal Region - * \return true on success, false otherwise - * @verdict Unchanged - fx_isValidPolygonalRegion(in PolygonalRegion p_region) return boolean; - */ - BOOLEAN fx__isValidPolygonalRegion(const Ieee1609Dot2BaseTypes::PolygonalRegion &p__region) { return TRUE; } - - /* * \brief Check if a polygonal region is inside another one - * \param p_parent The main polygonal region - * \param p_region The polygonal region to be included - * \return true on success, false otherwise - * @verdict Unchanged - fx_isPolygonalRegionInside(in PolygonalRegion p_parent, in PolygonalRegion p_region) return boolean; - */ - BOOLEAN fx__isPolygonalRegionInside(const Ieee1609Dot2BaseTypes::PolygonalRegion &p__parent, const Ieee1609Dot2BaseTypes::PolygonalRegion &p__region) { - return TRUE; - } - - /* * \brief Check that the location is inside a circular region - * \param p_region The circular region to consider - * \param p_location The device location - * \return true on success, false otherwise - * @verdict Unchanged - fx_isLocationInsideCircularRegion(in CircularRegion p_region, in ThreeDLocation p_location) return boolean; - */ - BOOLEAN fx__isLocationInsideCircularRegion(const Ieee1609Dot2BaseTypes::CircularRegion &p__region, const Ieee1609Dot2BaseTypes::ThreeDLocation &p__location) { - return TRUE; - } - - /* * \brief Check that the location is inside a rectangular region - * \param p_region The rectangular region to consider - * \param p_location The device location - * \return true on success, false otherwise - * @verdict Unchanged - fx_isLocationInsideRectangularRegion(in SequenceOfRectangularRegion p_region, in ThreeDLocation p_location) return boolean; - */ - BOOLEAN fx__isLocationInsideRectangularRegion(const Ieee1609Dot2BaseTypes::SequenceOfRectangularRegion &p__region, - const Ieee1609Dot2BaseTypes::ThreeDLocation & p__location) { - return TRUE; - } - - /* * \brief Check that the location is inside a polygonal region - * \param p_region The polygonal region to consider - * \param p_location The device location - * \return true on success, false otherwise - * @verdict Unchanged - fx_isLocationInsidePolygonalRegion(in PolygonalRegion p_region, in ThreeDLocation p_location) return boolean; - */ - BOOLEAN fx__isLocationInsidePolygonalRegion(const Ieee1609Dot2BaseTypes::PolygonalRegion &p__region, - const Ieee1609Dot2BaseTypes::ThreeDLocation & p__location) { - return TRUE; - } - - /* * \brief Check if the location is inside an identified region - * \param p_region The identified region to consider - * \param p_location The device location - * \return true on success, false otherwise - * @verdict Unchanged - fx_isLocationInsideIdentifiedRegion(in IdentifiedRegion p_region, in ThreeDLocation p_location) return boolean; - */ - BOOLEAN fx__isLocationInsideIdentifiedRegion(const Ieee1609Dot2BaseTypes::IdentifiedRegion &p__region, - const Ieee1609Dot2BaseTypes::ThreeDLocation & p__location) { - return TRUE; - } - - /* * \brief Check if the location is inside an undefined region - * \param p_region The identified region to consider - * \param p_location The device location - * \return true on success, false otherwise - * @verdict Unchanged - fx_isLocationInsideOtherRegion(in octetstring p_region, in ThreeDLocation p_location) return boolean; - */ - BOOLEAN fx__isLocationInsideOtherRegion(const OCTETSTRING &p_region, const Ieee1609Dot2BaseTypes::ThreeDLocation &p_location) { return TRUE; } - - /** - * \brief Check that p_circular_region_1 circular region is included into p_circular_region_2 circular region - * \param p_circular_region_1 Circular region 1 - * \param p_circular_region_2 Circular region 2 - * \return true on success, false otherwise - fx_areCirclesInside(in CircularRegion p_circular_region_1, in CircularRegion p_circular_region_2) return boolean; - */ - BOOLEAN fx__areCirclesInside(const Ieee1609Dot2BaseTypes::CircularRegion &p_circular_region_1, - const Ieee1609Dot2BaseTypes::CircularRegion &p_circular_region_2) { - // Compute distance between the 2 radius - FLOAT d = LibItsCommon__Functions::fx__computeDistance(p_circular_region_1.center().latitude(), p_circular_region_1.center().longitude(), - p_circular_region_2.center().latitude(), p_circular_region_2.center().longitude()); - if ((float)abs(p_circular_region_1.radius() - p_circular_region_2.radius()) > (float)d) { - return FALSE; - } - return TRUE; - } - - /* * \brief Check that p_rectanglar_region_1 rectangular region is included into p_rectanglar_region_2 rectangular region - * \param p_rectanglar_region_1 Rectangular region 1 - * \param p_rectanglar_region_2 Rectangular region 2 - * \return true on success, false otherwise - fx_areRectanglesInside(in SequenceOfRectangularRegion p_rectanglar_region_1, in SequenceOfRectangularRegion p_rectanglar_region_2) return boolean; - */ - BOOLEAN fx__areRectanglesInside(const Ieee1609Dot2BaseTypes::SequenceOfRectangularRegion &p_rectanglar_region_1, - const Ieee1609Dot2BaseTypes::SequenceOfRectangularRegion &p_rectanglar_region_2) { - - return TRUE; - } - - /* * \brief Check that p_polygonal_region_1 polygonal region is included into p_polygonal_region_2 polygonal region - * \param p_polygonal_region_1 Polygonal region 1 - * \param p_polygonal_region_2 Polygonal region 2 - * \return true on success, false otherwise - fx_arePolygonsInside(in PolygonalRegion p_polygonal_region_1, in PolygonalRegion p_polygonal_region_2) return boolean; - */ - BOOLEAN fx__arePolygonsInside(const Ieee1609Dot2BaseTypes::PolygonalRegion &p_polygonal_region_1, - const Ieee1609Dot2BaseTypes::PolygonalRegion &p_polygonal_region_2) { - return TRUE; - } - - /** - * \brief Convert a spacial coordinate from DMS to DMS - * \param p_degrees The degrees (D) - * \param p_minutes The minutes (M) - * \param p_seconds The seconds (S) - * \param p_latlon The latitude/longitude: (N|S|E|W) - * \return The decimal coordinate on success, 0.0, otherwise - * @verdict Unchanged - fx_dms2dd(in Int p_degrees, in Int p_minutes, in float p_seconds, in Oct1 p_latlon) return float; - */ - FLOAT fx__dms2dd(const INTEGER &p__degrees, const INTEGER &p__minutes, const FLOAT &p__seconds, const OCTETSTRING &p__latlon) { return 0.0; } - - FLOAT fx__int2ddlat(const INTEGER &p__latitude) { return (float)((float)p__latitude / 10000000.0); } - - FLOAT fx__int2ddlon(const INTEGER &p__longitude) { return (float)((float)p__longitude / 1000000.0); } - -} // namespace LibItsSecurity__Functions +/*! + * \file LibItsSecurity_externals.cc + * \brief Source file for Security externl functions. + * \author ETSI STF525 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "LibItsCommon_Functions.hh" +#include "LibItsSecurity_Functions.hh" + +#include "hmac.hh" +#include "sha256.hh" +#include "sha384.hh" +//#include "sm3.hh" + +#include "security_ecc.hh" + +#include "security_services_its.hh" + +#include "geospacial.hh" + +#include +#include + +#include "loggers.hh" + +#include "params_its.hh" + +namespace LibItsSecurity__Functions { + + static unsigned char sm3_empty_string[32] = { 0x1A,0xB2,0x1D,0x83,0x55,0xCF,0xA1,0x7F,0x8E,0x61,0x19,0x48,0x31,0xE8,0x1A,0x8F,0x22,0xBE,0xC8,0xC7,0x28,0xFE,0xFB,0x74,0x7E,0xD0,0x35,0xEB,0x50,0x82,0xAA,0x2B }; + + static std::unique_ptr g(new geospacial); + + // FIXME Unify code with security_services_its + + /** + * \fn OCTETSTRING fx_hashWithSha256(const OCTETSTRING& p__toBeHashedData); + * \brief Produces a 256-bit (32-bytes) hash value + * \param[in] p__toBeHashedData The data to be used to calculate the hash value + * \return The hash value + */ + OCTETSTRING fx__hashWithSha256(const OCTETSTRING &p__toBeHashedData) { + loggers::get_instance().log_msg(">>> fx__hashWithSha256: p__toBeHashedData= ", p__toBeHashedData); + + sha256 hash; + OCTETSTRING hashData; + hash.generate(p__toBeHashedData, hashData); + loggers::get_instance().log_msg("fx__hashWithSha256: hashData= ", hashData); + return hashData; + } // End of function fx__hashWithSha256 + + /** + * \fn OCTETSTRING fx_hashWithSha384(const OCTETSTRING& p__toBeHashedData); + * \brief Produces a 384-bit (48-bytes) hash value + * \param[in] p__toBeHashedData Data to be used to calculate the hash value + * \return The hash value + */ + OCTETSTRING fx__hashWithSha384(const OCTETSTRING &p__toBeHashedData) { + sha384 hash; + OCTETSTRING hashData; + hash.generate(p__toBeHashedData, hashData); + loggers::get_instance().log_msg("fx__hashWithSha384: hashData= ", hashData); + return hashData; + } // End of function fx__hashWithSha384 + + /** + * \fn OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 + * \param[in] p__toBeSignedSecuredMessage The data to be signed + * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate + * \param[in] p__privateKey The private key + * \return The signature value + */ + OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__privateKey) { + loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: data=", p__toBeSignedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: issuer=", p__certificateIssuer); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp256WithSha256: private key=", p__privateKey); + + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) { + loggers::get_instance().log("fx__signWithEcdsaNistp256WithSha256: Wrong parameters"); + return OCTETSTRING(0, nullptr); + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeSignedSecuredMessage, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash (Data input) || Hash (Signer identifier input)=", hashData1); + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__signWithEcdsaNistp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Calculate the signature + security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashData, r_sig, s_sig) == 0) { + OCTETSTRING os = r_sig + s_sig; + loggers::get_instance().log_msg("r_sig= ", r_sig); + loggers::get_instance().log_msg("s_sig= ", s_sig); + loggers::get_instance().log_msg("sig= ", os); + return os; + } + + return OCTETSTRING(0, nullptr); + } + + /** + * \fn OCTETSTRING fx__signWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on raw data + * \param[in] p__toBeSignedSecuredMessage The data to be signed + * \param[in] p__privateKey The private key + * \return The signature value + */ + OCTETSTRING fx__test__signWithEcdsaNistp256WithSha256(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__privateKey) { + loggers::get_instance().log_msg(">>> fx__test__signWithEcdsaNistp256WithSha256: data=", p__toBeSignedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__test__signWithEcdsaNistp256WithSha256: private key=", p__privateKey); + + // Sanity checks + if (p__privateKey.lengthof() != 32) { + loggers::get_instance().log("fx__test__signWithEcdsaNistp256WithSha256: Wrong parameters"); + return OCTETSTRING(0, nullptr); + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeSignedSecuredMessage, hashData1); + loggers::get_instance().log_msg("fx__test__signWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); + // Calculate the signature + security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashData1, r_sig, s_sig) == 0) { + OCTETSTRING os = r_sig + s_sig; + loggers::get_instance().log_msg("r_sig= ", r_sig); + loggers::get_instance().log_msg("s_sig= ", s_sig); + loggers::get_instance().log_msg("sig= ", os); + return os; + } + + return OCTETSTRING(0, nullptr); + } + + /** + * \fn OCTETSTRING fx__signWithEcdsaSm2WithSm3(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 + * \param[in] p__toBeSignedSecuredMessage The data to be signed + * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate + * \param[in] p__privateKey The private key + * \return The signature value + */ + OCTETSTRING fx__signWithEcdsaSm2WithSm3(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__privateKey) { + loggers::get_instance().log_msg(">>> fx__signWithEcdsaSm2WithSm3: data=", p__toBeSignedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaSm2WithSm3: issuer=", p__certificateIssuer); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaSm2WithSm3: private key=", p__privateKey); + + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) { + loggers::get_instance().log("fx__signWithEcdsaSm2WithSm3: Wrong parameters"); + return OCTETSTRING(0, nullptr); + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeSignedSecuredMessage, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__signWithEcdsaSm2WithSm3: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__signWithEcdsaSm2WithSm3: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("fx__signWithEcdsaSm2WithSm3: Hash (Data input) || Hash (Signer identifier input)=", hashData1); + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__signWithEcdsaSm2WithSm3: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + + // Setup INTLa and IDa - IEEE 1609.2 Clause 5.3.1.3 SM + OCTETSTRING entl_a; // IEEE 1609.2 Clause 5.3.1.3 SM2 + OCTETSTRING id_a; // IEEE 1609.2 Clause 5.3.1.3 SM2 + if (p__certificateIssuer != int2oct(0, 32)) { + entl_a = int2oct(16, 2); // IEEE 1609.2 Clause 5.3.1.3 SM2 + id_a = p__certificateIssuer; + } else { + entl_a = int2oct(128, 2); // IEEE 1609.2 Clause 5.3.1.3 SM2 + id_a = OCTETSTRING(32, sm3_empty_string); // Sm3 hash of empty string + } + // Calculate the signature + security_ecc k(ec_elliptic_curves::sm2_p_256, p__privateKey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashData1, entl_a, id_a, r_sig, s_sig) == 0) { + OCTETSTRING os = r_sig + s_sig; + loggers::get_instance().log_msg("r_sig= ", r_sig); + loggers::get_instance().log_msg("s_sig= ", s_sig); + loggers::get_instance().log_msg("sig= ", os); + return os; + } + + return OCTETSTRING(0, nullptr); +} + + /** + * \fn OCTETSTRING fx__signWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 + * \param[in] p__toBeSignedSecuredMessage The data to be signed + * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate + * \param[in] p__privateKey The private key + * \return The signature value + */ + OCTETSTRING fx__signWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__privateKey) { + loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp256r1WithSha256: data=", p__toBeSignedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp256r1WithSha256: issuer=", p__certificateIssuer); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp256r1WithSha256: private key=", p__privateKey); + + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__privateKey.lengthof() != 32)) { + loggers::get_instance().log("fx__signWithEcdsaBrainpoolp256r1WithSha256: Wrong parameters"); + return OCTETSTRING(0, nullptr); + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeSignedSecuredMessage, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp256r1WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Calculate the signature + security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__privateKey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashData, r_sig, s_sig) == 0) { + OCTETSTRING os = r_sig + s_sig; + loggers::get_instance().log_msg("r_sig= ", r_sig); + loggers::get_instance().log_msg("s_sig= ", s_sig); + loggers::get_instance().log_msg("sig= ", os); + return os; + } + + return OCTETSTRING(0, nullptr); + } + + /** + * \fn OCTETSTRING fx__signWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 + * \param[in] p__toBeSignedSecuredMessage The data to be signed + * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate + * \param[in] p__privateKey The private key + * \return The signature value + */ + OCTETSTRING fx__signWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__privateKey) { + loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp384r1WithSha384: data=", p__toBeSignedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp384r1WithSha384: issuer=", p__certificateIssuer); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaBrainpoolp384r1WithSha384: private key=", p__privateKey); + + // Sanity checks + if ((p__certificateIssuer.lengthof() != 48) || (p__privateKey.lengthof() != 48)) { + loggers::get_instance().log("fx__signWithEcdsaBrainpoolp384r1WithSha384: Wrong parameters"); + return OCTETSTRING(0, nullptr); + } + + // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha384 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeSignedSecuredMessage, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha384_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Calculate the signature + security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__privateKey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashData, r_sig, s_sig) == 0) { + OCTETSTRING os = r_sig + s_sig; + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: r_sig= ", r_sig); + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: s_sig= ", s_sig); + loggers::get_instance().log_msg("fx__signWithEcdsaBrainpoolp384r1WithSha384: sig= ", os); + return os; + } + + return OCTETSTRING(0, nullptr); + } + + /** + * \fn OCTETSTRING fx__signWithEcdsaNistp384WithSha384(const OCTETSTRING& p__toBeSignedSecuredMessage, const OCTETSTRING& p__privateKey); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 + * \param[in] p__toBeSignedSecuredMessage The data to be signed + * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate + * \param[in] p__privateKey The private key + * \return The signature value + */ + OCTETSTRING fx__signWithEcdsaNistp384WithSha384(const OCTETSTRING &p__toBeSignedSecuredMessage, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__privateKey) { + loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp384WithSha384: data=", p__toBeSignedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp384WithSha384: issuer=", p__certificateIssuer); + loggers::get_instance().log_msg(">>> fx__signWithEcdsaNistp384WithSha384: private key=", p__privateKey); + + // Sanity checks + if ((p__certificateIssuer.lengthof() != 48) || (p__privateKey.lengthof() != 48)) { + loggers::get_instance().log("fx__signWithEcdsaNistp384WithSha384: Wrong parameters"); + return OCTETSTRING(0, nullptr); + } + + // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha384 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeSignedSecuredMessage, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha384_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Calculate the signature + security_ecc k(ec_elliptic_curves::nist_p_384, p__privateKey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashData, r_sig, s_sig) == 0) { + OCTETSTRING os = r_sig + s_sig; + loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: r_sig= ", r_sig); + loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: s_sig= ", s_sig); + loggers::get_instance().log_msg("fx__signWithEcdsaNistp384WithSha384: sig= ", os); + return os; + } + + return OCTETSTRING(0, nullptr); + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaNistp256PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData The + * data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] + * p__signature The signature \param[in] p__ecdsaNistp256PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false + * otherwise + */ + BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaNistp256PublicKeyCompressed, + const INTEGER &p__compressedMode) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyCompressed.lengthof() != 32)) { + loggers::get_instance().log("fx__verifyWithEcdsaNistp256WithSha256: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyCompressed, + (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__ecdsaNistp256PublicKeyCompressed); + * \brief Verify the signature of the specified data based on raw data + * \param[in] p__toBeVerifiedData The data to be verified + * \param[in] p__signature The signature + * \param[in] p__ecdsaNistp256PublicKeyCompressed The compressed public key (x coordinate only) + * \return true on success, false otherwise + */ + BOOLEAN fx__test__verifyWithEcdsaNistp256WithSha256(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__signature, + const OCTETSTRING &p__ecdsaNistp256PublicKeyCompressed, const INTEGER &p__compressedMode) { + // Sanity checks + if ((p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyCompressed.lengthof() != 32)) { + loggers::get_instance().log("fx__test__verifyWithEcdsaNistp256WithSha256: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + loggers::get_instance().log_msg("fx__test__verifyWithEcdsaNistp256WithSha256: Hash (Data input)=", hashData1); + // Check the signature + security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyCompressed, + (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (k.sign_verif(hashData1, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaNistp256WithSha256_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaNistp256PublicKeyX, const OCTETSTRING& p__ecdsaNistp256PublicKeyY); \brief Verify the signature of the specified data based on standard IEEE 1609.2 + * \param[in] p__toBeVerifiedData The data to be verified + * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate + * \param[in] p__signature The signature + * \param[in] p__ecdsaNistp256PublicKeyX The public key (x coordinate) + * \param[in] p__ecdsaNistp256PublicKeyY The public key (y coordinate) + * \return true on success, false otherwise + */ + BOOLEAN fx__verifyWithEcdsaNistp256WithSha256__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaNistp256PublicKeyX, + const OCTETSTRING &p__ecdsaNistp256PublicKeyY) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaNistp256PublicKeyX.lengthof() != 32) || + (p__ecdsaNistp256PublicKeyY.lengthof() != 32)) { + loggers::get_instance().log("fx__verifyWithEcdsaNistp256WithSha256__1: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp256WithSha256__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::nist_p_256, p__ecdsaNistp256PublicKeyX, p__ecdsaNistp256PublicKeyY); + // security_ecc k(ec_elliptic_curves::nist_p_256); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaSm2WithSm3(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaSm2p256PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData The + * data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] + * p__signature The signature \param[in] p__ecdsaSm2p256PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false + * otherwise + */ + BOOLEAN fx__verifyWithEcdsaSm2WithSm3(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaSm2p256PublicKeyCompressed, + const INTEGER &p__compressedMode) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaSm2p256PublicKeyCompressed.lengthof() != 32)) { + loggers::get_instance().log("fx__verifyWithEcdsaSm2WithSm3: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaSm2WithSm3: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaSm2WithSm3: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaSm2WithSm3: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::sm2_p_256, p__ecdsaSm2p256PublicKeyCompressed, + (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaSm2WithSm3_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaSm2p256PublicKeyX, const OCTETSTRING& p__ecdsaSm2p256PublicKeyY); \brief Verify the signature of the specified data based on standard IEEE 1609.2 + * \param[in] p__toBeVerifiedData The data to be verified + * \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate + * \param[in] p__signature The signature + * \param[in] p__ecdsaSm2p256PublicKeyX The public key (x coordinate) + * \param[in] p__ecdsaSm2p256PublicKeyY The public key (y coordinate) + * \return true on success, false otherwise + */ + BOOLEAN fx__verifyWithEcdsaSm2WithSm3__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaSm2p256PublicKeyX, + const OCTETSTRING &p__ecdsaSm2p256PublicKeyY) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaSm2p256PublicKeyX.lengthof() != 32) || + (p__ecdsaSm2p256PublicKeyY.lengthof() != 32)) { + loggers::get_instance().log("fx__verifyWithEcdsaSm2WithSm3__1: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaSm2WithSm3__1: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaSm2WithSm3__1: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaSm2WithSm3__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::sm2_p_256, p__ecdsaSm2p256PublicKeyX, p__ecdsaSm2p256PublicKeyY); + // security_ecc k(ec_elliptic_curves::sm2_p_256); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaBrainpoolp256PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData + * The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] + * p__signature The signature \param[in] p__ecdsaBrainpoolp256PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false + * otherwise + */ + BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaBrainpoolp256PublicKeyCompressed, + const INTEGER &p__compressedMode) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaBrainpoolp256PublicKeyCompressed.lengthof() != 32)) { + loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__ecdsaBrainpoolp256PublicKeyCompressed, + (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaBrainpoolp256PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyY); \brief Verify the signature of the specified data based on standard + * IEEE 1609.2 \param[in] p__toBeVerifiedData The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in + * case of self signed certificate \param[in] p__signature The signature \param[in] p__ecdsaBrainpoolp256PublicKeyX The public key (x coordinate) \param[in] + * p__ecdsaBrainpoolp256PublicKeyY The public key (y coordinate) \return true on success, false otherwise + */ + BOOLEAN fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaBrainpoolp256PublicKeyX, + const OCTETSTRING &p__ecdsaBrainpoolp256PublicKeyY) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 32) || (p__signature.lengthof() != 64) || (p__ecdsaBrainpoolp256PublicKeyX.lengthof() != 32) || + (p__ecdsaBrainpoolp256PublicKeyY.lengthof() != 32)) { + loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA256 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha256 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha256_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp256r1WithSha256__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__ecdsaBrainpoolp256PublicKeyX, p__ecdsaBrainpoolp256PublicKeyY); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaBrainpoolp384PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData + * The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] + * p__signature The signature \param[in] p__ecdsaBrainpoolp384PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false + * otherwise + */ + BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaBrainpoolp384PublicKeyCompressed, + const INTEGER &p__compressedMode) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaBrainpoolp384PublicKeyCompressed.lengthof() != 48)) { + loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha384 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha384_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__ecdsaBrainpoolp384PublicKeyCompressed, + (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaBrainpoolp384PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY); \brief Verify the signature of the specified data based on standard + * IEEE 1609.2 \param[in] p__toBeVerifiedData The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in + * case of self signed certificate \param[in] p__signature The signature \param[in] p__ecdsaBrainpoolp384PublicKeyX The public key (x coordinate) \param[in] + * p__ecdsaBrainpoolp384PublicKeyY The public key (y coordinate) \return true on success, false otherwise + */ + BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaBrainpoolp384PublicKeyX, + const OCTETSTRING &p__ecdsaBrainpoolp384PublicKeyY) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaBrainpoolp384PublicKeyX.lengthof() != 48) || + (p__ecdsaBrainpoolp384PublicKeyY.lengthof() != 48)) { + loggers::get_instance().log("fx__verifyWithEcdsaBrainpoolp384r1WithSha384__1: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha384 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha384_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaBrainpoolp384r1WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__ecdsaBrainpoolp384PublicKeyX, p__ecdsaBrainpoolp384PublicKeyY); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaNistp384WithSha384(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaBrainpoolp384PublicKeyCompressed); \brief Verify the signature of the specified data based on standard IEEE 1609.2 \param[in] p__toBeVerifiedData + * The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate \param[in] + * p__signature The signature \param[in] p__ecdsaBrainpoolp384PublicKeyCompressed The compressed public key (x coordinate only) \return true on success, false + * otherwise + */ + BOOLEAN fx__verifyWithEcdsaNistp384WithSha384(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaNistp384PublicKeyCompressed, + const INTEGER &p__compressedMode) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaNistp384PublicKeyCompressed.lengthof() != 48)) { + loggers::get_instance().log("fx__verifyWithEcdsaNistp384WithSha384: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha384 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 48)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha384_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::nist_p_384, p__ecdsaNistp384PublicKeyCompressed, + (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn BOOLEAN fx__verifyWithEcdsaBrainpoolp384r1WithSha384_1(const OCTETSTRING& p__toBeVerifiedData, const OCTETSTRING& p__signature, const OCTETSTRING& + * p__ecdsaBrainpoolp384PublicKeyX, const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY); \brief Verify the signature of the specified data based on standard + * IEEE 1609.2 \param[in] p__toBeVerifiedData The data to be verified \param[in] p__certificateIssuer The whole-hash issuer certificate or int2oct(0, 32) in + * case of self signed certificate \param[in] p__signature The signature \param[in] p__ecdsaBrainpoolp384PublicKeyX The public key (x coordinate) \param[in] + * p__ecdsaBrainpoolp384PublicKeyY The public key (y coordinate) \return true on success, false otherwise + */ + BOOLEAN fx__verifyWithEcdsaNistp384WithSha384__1(const OCTETSTRING &p__toBeVerifiedData, const OCTETSTRING &p__certificateIssuer, + const OCTETSTRING &p__signature, const OCTETSTRING &p__ecdsaNistp384PublicKeyX, + const OCTETSTRING &p__ecdsaNistp384PublicKeyY) { + // Sanity checks + if ((p__certificateIssuer.lengthof() != 48) || (p__signature.lengthof() != 96) || (p__ecdsaNistp384PublicKeyX.lengthof() != 48) || + (p__ecdsaNistp384PublicKeyY.lengthof() != 48)) { + loggers::get_instance().log("fx__verifyWithEcdsaNistp384WithSha384__1: Wrong parameters"); + return FALSE; + } + + // Calculate the SHA384 of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + sha384 hash; + OCTETSTRING hashData1; // Hash (Data input) + hash.generate(p__toBeVerifiedData, hashData1); + OCTETSTRING hashData2; // Hash (Signer identifier input) + if (p__certificateIssuer != int2oct(0, 32)) { // || Hash (Signer identifier input) + hashData2 = p__certificateIssuer; + } else { + hashData2 = hash.get_sha384_empty_string(); // Hash of empty string + } + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384__1: Hash (Data input)=", hashData1); + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384__1: Hash (Signer identifier input)=", hashData2); + hashData1 += hashData2; // Hash (Data input) || Hash (Signer identifier input) + OCTETSTRING hashData; // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + hash.generate(hashData1, hashData); + loggers::get_instance().log_msg("fx__verifyWithEcdsaNistp384WithSha384__1: Hash ( Hash (Data input) || Hash (Signer identifier input) )=", hashData); + // Check the signature + security_ecc k(ec_elliptic_curves::nist_p_384, p__ecdsaNistp384PublicKeyX, p__ecdsaNistp384PublicKeyY); + if (k.sign_verif(hashData, p__signature) == 0) { + return TRUE; + } + + return FALSE; + } + + /** + * \fn OCTETSTRING fx__hmac__sha256(const OCTETSTRING& p__k, const OCTETSTRING& p__m); + * \brief Generate a HMAC-SHA256 value based on the provided secret key + * \param[in] p__k The secret key used for the HMAC calculation + * \param[in] p__m The message + * \return The HMAC value resized to 16-byte + */ + OCTETSTRING fx__hmac__sha256(const OCTETSTRING &p__k, const OCTETSTRING &p__m) { + loggers::get_instance().log_msg(">>> fx__hmac__sha256: p__k=", p__k); + loggers::get_instance().log_msg(">>> fx__hmac__sha256: p__m=", p__m); + + hmac h(hash_algorithms::sha_256); // TODO Use ec_encryption_algorithm + OCTETSTRING t; + if (h.generate(p__m, p__k, t) == -1) { + loggers::get_instance().warning("fx__hmac__sha256: Failed to generate HMAC"); + return OCTETSTRING(0, nullptr); + } + + loggers::get_instance().log_msg("<<< fx__hmac__sha256: HMAC: ", t); + return t; + } + + /** + * \fn OCTETSTRING fx__encrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt); + * \brief Encrypt the message using AES 128 CCM algorithm + * \param[in] p__k The symmetric encryption key + * \param[in] p__n The initial vector, nonce vector + * \param[in] p__pt The message to encrypt + * \return The encrypted message concatenated to the AES 128 CCM tag + */ + OCTETSTRING fx__encrypt__aes__128__ccm__test(const OCTETSTRING &p__k, const OCTETSTRING &p__n, const OCTETSTRING &p__pt) { + loggers::get_instance().log(">>> fx__encrypt__aes__128__ccm__test"); + + security_ecc ec(ec_elliptic_curves::nist_p_256); + OCTETSTRING enc_message; + if (ec.encrypt(encryption_algotithm::aes_128_ccm, p__k, p__n, p__pt, enc_message) == -1) { + loggers::get_instance().warning("fx__encrypt__aes__128__ccm__test: Failed to encrypt message"); + return OCTETSTRING(0, nullptr); + } + OCTETSTRING os(enc_message + ec.tag()); + loggers::get_instance().log_msg("fx__encrypt__aes__128__ccm__test: encrypted message: ", os); + + return os; + } + + /** + * \fn OCTETSTRING fx__encrypt__aes__128__gcm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__pt); + * \brief Encrypt the message using AES 128 GCM algorithm + * \param[in] p__k The symmetric encryption key + * \param[in] p__n The initial vector, nonce vector + * \param[in] p__pt The message to encrypt + * \return The encrypted message concatenated to the AES 128 CCM tag + */ + OCTETSTRING fx__encrypt__aes__128__gcm__test(const OCTETSTRING &p__k, const OCTETSTRING &p__n, const OCTETSTRING &p__pt) { + loggers::get_instance().log(">>> fx__encrypt__aes__128__gcm__test"); + + security_ecc ec(ec_elliptic_curves::nist_p_256); + OCTETSTRING enc_message; + if (ec.encrypt(encryption_algotithm::aes_128_gcm, p__k, p__n, p__pt, enc_message) == -1) { + loggers::get_instance().warning("fx__encrypt__aes__128__gcm__test: Failed to encrypt message"); + return OCTETSTRING(0, nullptr); + } + OCTETSTRING os(enc_message + ec.tag()); + loggers::get_instance().log_msg("fx__encrypt__aes__128__gcm__test: encrypted message: ", os); + + return os; + } + + /** + * \fn OCTETSTRING fx__decrypt__aes__128__ccm__test(const OCTETSTRING& p__k, const OCTETSTRING& p__n, const OCTETSTRING& p__ct); + * \brief Encrypt the message using AES 128 CCM algorithm + * \param[in] p__k The symmetric encryption key + * \param[in] p__n The initial vector, nonce vector + * \param[in] p__ct The encrypted message concatenated to the AES 128 CCM tag + * \return The original message + */ + OCTETSTRING fx__decrypt__aes__128__ccm__test(const OCTETSTRING &p__k, const OCTETSTRING &p__n, const OCTETSTRING &p__ct) { + loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__k: ", p__k); + loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__n: ", p__n); + loggers::get_instance().log_msg(">>> fx__decrypt__aes__128__ccm__test: p__ct: ", p__ct); + + security_ecc ec(ec_elliptic_curves::nist_p_256); + // Extract the tag + OCTETSTRING tag(16, p__ct.lengthof() - 16 + static_cast(p__ct)); + loggers::get_instance().log_msg("fx__decrypt__aes__128__ccm__test: tag: ", tag); + // Remove the tag from the end of the encrypted message + OCTETSTRING ct(p__ct.lengthof() - 16, static_cast(p__ct)); + loggers::get_instance().log_msg("fx__decrypt__aes__128__ccm__test: ct: ", ct); + + OCTETSTRING message; + if (ec.decrypt(encryption_algotithm::aes_128_ccm, p__k, p__n, tag, ct, message) == -1) { + loggers::get_instance().warning("fx__decrypt__aes__128__ccm__test: Failed to decrypt message"); + return OCTETSTRING(0, nullptr); + } + loggers::get_instance().log_to_hexa("fx__decrypt__aes__128__ccm__test: decrypted message: ", message); + + return message; + } + + /** + * \fn OCTETSTRING fx__encryptWithEciesNistp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyX, const + * OCTETSTRING& p__recipientsPublicKeyY, OCTETSTRING& p__publicEphemeralKeyX, OCTETSTRING& p__publicEphemeralKeyY, OCTETSTRING& p__encrypted__sym__key, + * OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce); \brief Encrypt the message using ECIES algorithm to encrypt AES 128 CCM symmetric key, as + * defined in IEEE Std 1609.2-2017 \param[in] p__toBeEncryptedSecuredMessage The message to be encrypted \param[in] p__recipientsPublicKeyCompressed The + * Recipient's compressed public key \param[in] p__compressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise \param[out] + * p__publicEphemeralKeyCompressed The public ephemeral compressed key \param[out] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of + * Y-coordinate is 0, 1 otherwise \param[out] p__encrypted__sym__key The encrypted AES 128 symmetric key \param[out] p__authentication__vector The tag of the + * encrypted AES 128 symmetric key \param[out] p__nonce The nonce vector \return The original message \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key + * encryption algorithms: ECIES \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ \see + * http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf + */ + // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function + OCTETSTRING fx__encryptWithEciesNistp256WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, const OCTETSTRING &p__recipientsPublicKeyCompressed, + const INTEGER &p__compressedMode, const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyCompressed, + INTEGER &p__ephemeralCompressedMode, OCTETSTRING &p__aes__sym__key, OCTETSTRING &p__encrypted__sym__key, + OCTETSTRING &p__authentication__vector, OCTETSTRING &p__nonce) { + loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed); + loggers::get_instance().log(">>> fx__encryptWithEciesNistp256WithSha256: p__compressedMode: %d", static_cast(p__compressedMode)); + loggers::get_instance().log_msg(">>> fx__encryptWithEciesNistp256WithSha256: p__salt: ", p__salt); + + // 1. Generate new Private/Public Ephemeral key + std::unique_ptr ec; + ec.reset(new security_ecc(ec_elliptic_curves::nist_p_256)); + if (ec->generate() == -1) { + loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to generate ephemeral keys"); + return OCTETSTRING(0, nullptr); + } + // 2. Generate and derive shared secret based on recipient's private keys + security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__recipientsPublicKeyCompressed, + (static_cast(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (ec->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { + loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to generate and derive secret key"); + return OCTETSTRING(0, nullptr); + } + + // Set the AES symmetric key + loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: AES symmetric key: ", ec->symmetric_encryption_key()); + p__aes__sym__key = ec->symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__aes__sym__key: ", p__aes__sym__key); + // Set the encrypted symmetric key + loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: Encrypted symmetric key: ", ec->encrypted_symmetric_key()); + p__encrypted__sym__key = ec->encrypted_symmetric_key(); + loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + // Set the tag of the symmetric key encryption + p__authentication__vector = ec->tag(); + loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector); + // Set ephemeral public keys + p__publicEphemeralKeyCompressed = ec->public_key_compressed(); + loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed); + p__ephemeralCompressedMode = (ec->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1; + loggers::get_instance().log("fx__encryptWithEciesNistp256WithSha256: Ephemeral public compressed mode: %d: ", (int)p__ephemeralCompressedMode); + // 3. Retrieve AES 128 parameters + p__nonce = ec->nonce(); + loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce); + // 4. Encrypt the data using AES-128 CCM + OCTETSTRING enc_message; + if (ec->encrypt(encryption_algotithm::aes_128_ccm, ec->symmetric_encryption_key(), ec->nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { + loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to encrypt message"); + return OCTETSTRING(0, nullptr); + } + enc_message += ec->tag(); + loggers::get_instance().log_to_hexa("fx__encryptWithEciesNistp256WithSha256: enc message||Tag: ", enc_message); + + return enc_message; + } + + /** + * @desc Test function for ECIES NIST P-256 Encryption with SHA-256 + * @remark For the purpose of testing, the content of p__toBeEncryptedSecuredMessage is the AES 128 symmetric key to be encrypted + */ + OCTETSTRING fx__test__encryptWithEciesNistp256WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, const OCTETSTRING &p__privateEphemeralKey, + const OCTETSTRING &p__recipientPublicKeyX, const OCTETSTRING &p__recipientPublicKeyY, + const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyX, OCTETSTRING &p__publicEphemeralKeyY, + OCTETSTRING &p__aes__sym__key, OCTETSTRING &p__encrypted__sym__key, + OCTETSTRING &p__authentication__vector, OCTETSTRING &p__nonce) { + + // 1. Generate new ephemeral Private/Public keys + security_ecc ec(ec_elliptic_curves::nist_p_256, p__privateEphemeralKey); + p__publicEphemeralKeyX = ec.public_key_x(); + p__publicEphemeralKeyY = ec.public_key_y(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Vx=", p__publicEphemeralKeyX); + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Vy=", p__publicEphemeralKeyY); + + // 2. Generate and derive shared secret + security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__recipientPublicKeyX, p__recipientPublicKeyY); + ec.symmetric_encryption_key(p__toBeEncryptedSecuredMessage); + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: ", ec.encrypted_symmetric_key()); + if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { + loggers::get_instance().warning("fx__test__encryptWithEciesNistp256WithSha256: Failed to generate and derive secret key"); + return OCTETSTRING(0, nullptr); + } + + // Set the AES symmetric key + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: AES symmetric key: ", ec.symmetric_encryption_key()); + p__aes__sym__key = ec.symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__aes__sym__key: ", p__aes__sym__key); + // Set the encrypted symmetric key + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: Encrypted symmetric key: ", ec.encrypted_symmetric_key()); + p__encrypted__sym__key = ec.encrypted_symmetric_key(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + // Set the tag of the symmetric key encryption + p__authentication__vector = ec.tag(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector); + // 3. Retrieve AES 128 parameters + p__nonce = ec.nonce(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce); + // 4. Encrypt the data using AES-128 CCM + OCTETSTRING enc_message; + if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { + loggers::get_instance().warning("fx__test__encryptWithEciesNistp256WithSha256: Failed to encrypt message"); + return OCTETSTRING(0, nullptr); + } + enc_message += ec.tag(); + loggers::get_instance().log_to_hexa("fx__test__encryptWithEciesNistp256WithSha256: enc message||Tag: ", enc_message); + + return enc_message; + } + + /** + * \fn OCTETSTRING fx__decryptWithEciesNistp256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const + * OCTETSTRING& p__publicEphemeralKeyX, const OCTETSTRING& p__publicEphemeralKeyY, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& + * p__authentication__vector, const OCTETSTRING& p__nonce); \brief Decrypt the message using ECIES algorithm to decrypt AES 128 CCM symmetric key, as defined + * in IEEE Std 1609.2-2017 \param[in] p__encryptedSecuredMessage The encrypted message \param[in] p__privateEncKey The private encryption key \param[in] + * p__publicEphemeralKeyCompressed The public ephemeral compressed key \param[in] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of + * Y-coordinate is 0, 1 otherwise \param[in] p__encrypted__sym__key The encrypted AES 128 symmetric key \param[in] p__authentication__vector The tag of the + * encrypted AES 128 symmetric key \param[in] p__nonce The nonce vector \return The original message \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key + * encryption algorithms: ECIES \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ \see + * http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf + */ + // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function + OCTETSTRING fx__decryptWithEciesNistp256WithSha256(const OCTETSTRING &p__encryptedSecuredMessage, const OCTETSTRING &p__privateEncKey, + const OCTETSTRING &p__publicEphemeralKeyCompressed, const INTEGER &p__ephemeralCompressedMode, + const OCTETSTRING &p__encrypted__sym__key, const OCTETSTRING &p__authentication__vector, + const OCTETSTRING &p__nonce, const OCTETSTRING &p__salt, OCTETSTRING &p__aes__sym__enc__key) { + loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__privateEncKey: ", p__privateEncKey); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__publicEphemeralKeyCompressed: ", p__publicEphemeralKeyCompressed); + loggers::get_instance().log(">>> fx__decryptWithEciesNistp256WithSha256: p__ephemeralCompressedMode: %d", static_cast(p__ephemeralCompressedMode)); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__nonce: ", p__nonce); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__authentication__vector: ", p__authentication__vector); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesNistp256WithSha256: p__salt", p__salt); + + // 1. Create security_ecc instance based on recipient's private key + security_ecc ec(ec_elliptic_curves::nist_p_256, p__privateEncKey); + security_ecc ec_comp(ec_elliptic_curves::nist_p_256, p__publicEphemeralKeyCompressed, + (static_cast(p__ephemeralCompressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + + // 2. Generate the shared secret value based on public ephemeral keys will be required + if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__encrypted__sym__key, + p__nonce, p__authentication__vector, p__salt) == -1) { + loggers::get_instance().warning("fx__decryptWithEciesNistp256WithSha256: Failed to generate shared secret"); + return OCTETSTRING(0, nullptr); + } + + // Decrypt the message + OCTETSTRING enc_message(p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof(), + static_cast(p__encryptedSecuredMessage)); // Extract the encrypted message + loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: enc_message: ", enc_message); // Extract the ctag value + OCTETSTRING tag(ec.tag().lengthof(), + static_cast(p__encryptedSecuredMessage) + p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof()); + loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: tag: ", tag); + OCTETSTRING message; + if (ec.decrypt(tag, enc_message, message) == -1) { + loggers::get_instance().warning("fx__decryptWithEciesNistp256WithSha256: Failed to generate shared secret"); + return OCTETSTRING(0, nullptr); + } + loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: dec message: ", message); + p__aes__sym__enc__key = ec.symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__decryptWithEciesNistp256WithSha256: AES 128 encryption key: ", p__aes__sym__enc__key); + + return message; + } + + + + + + + + + + + + + + + + + + + + + + + + + + /** + * \fn OCTETSTRING fx__encryptWithEciesSm2p256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyX, const + * OCTETSTRING& p__recipientsPublicKeyY, OCTETSTRING& p__publicEphemeralKeyX, OCTETSTRING& p__publicEphemeralKeyY, OCTETSTRING& p__encrypted__sym__key, + * OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce); \brief Encrypt the message using ECIES algorithm to encrypt AES 128 CCM symmetric key, as + * defined in IEEE Std 1609.2-2017 \param[in] p__toBeEncryptedSecuredMessage The message to be encrypted \param[in] p__recipientsPublicKeyCompressed The + * Recipient's compressed public key \param[in] p__compressedMode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise \param[out] + * p__publicEphemeralKeyCompressed The public ephemeral compressed key \param[out] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of + * Y-coordinate is 0, 1 otherwise \param[out] p__encrypted__sym__key The encrypted AES 128 symmetric key \param[out] p__authentication__vector The tag of the + * encrypted AES 128 symmetric key \param[out] p__nonce The nonce vector \return The original message \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key + * encryption algorithms: ECIES \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ \see + * http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf + */ + // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function + OCTETSTRING fx__encryptWithEciesSm2p256WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, const OCTETSTRING &p__recipientsPublicKeyCompressed, + const INTEGER &p__compressedMode, const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyCompressed, + INTEGER &p__ephemeralCompressedMode, OCTETSTRING &p__aes__sym__key, OCTETSTRING &p__encrypted__sym__key, + OCTETSTRING &p__authentication__vector, OCTETSTRING &p__nonce) { + loggers::get_instance().log_msg(">>> fx__encryptWithEciesSm2p256WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__encryptWithEciesSm2p256WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed); + loggers::get_instance().log(">>> fx__encryptWithEciesSm2p256WithSha256: p__compressedMode: %d", static_cast(p__compressedMode)); + loggers::get_instance().log_msg(">>> fx__encryptWithEciesSm2p256WithSha256: p__salt: ", p__salt); + + // 1. Generate new Private/Public Ephemeral key + std::unique_ptr ec; + ec.reset(new security_ecc(ec_elliptic_curves::sm2_p_256)); + if (ec->generate() == -1) { + loggers::get_instance().warning("fx__encryptWithEciesSm2p256WithSha256: Failed to generate ephemeral keys"); + return OCTETSTRING(0, nullptr); + } + // 2. Generate and derive shared secret based on recipient's private keys + security_ecc ec_comp(ec_elliptic_curves::sm2_p_256, p__recipientsPublicKeyCompressed, + (static_cast(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (ec->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { + loggers::get_instance().warning("fx__encryptWithEciesSm2p256WithSha256: Failed to generate and derive secret key"); + return OCTETSTRING(0, nullptr); + } + + // Set the AES symmetric key + loggers::get_instance().log_msg("fx__encryptWithEciesSm2p256WithSha256: AES symmetric key: ", ec->symmetric_encryption_key()); + p__aes__sym__key = ec->symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__encryptWithEciesSm2p256WithSha256: p__aes__sym__key: ", p__aes__sym__key); + // Set the encrypted symmetric key + loggers::get_instance().log_msg("fx__encryptWithEciesSm2p256WithSha256: Encrypted symmetric key: ", ec->encrypted_symmetric_key()); + p__encrypted__sym__key = ec->encrypted_symmetric_key(); + loggers::get_instance().log_msg("fx__encryptWithEciesSm2p256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + // Set the tag of the symmetric key encryption + p__authentication__vector = ec->tag(); + loggers::get_instance().log_msg("fx__encryptWithEciesSm2p256WithSha256: p__authentication__vector: ", p__authentication__vector); + // Set ephemeral public keys + p__publicEphemeralKeyCompressed = ec->public_key_compressed(); + loggers::get_instance().log_msg("fx__encryptWithEciesSm2p256WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed); + p__ephemeralCompressedMode = (ec->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1; + loggers::get_instance().log("fx__encryptWithEciesSm2p256WithSha256: Ephemeral public compressed mode: %d: ", (int)p__ephemeralCompressedMode); + // 3. Retrieve AES 128 parameters + p__nonce = ec->nonce(); + loggers::get_instance().log_msg("fx__encryptWithEciesSm2p256WithSha256: p__nonce: ", p__nonce); + // 4. Encrypt the data using AES-128 CCM + OCTETSTRING enc_message; + if (ec->encrypt(encryption_algotithm::aes_128_ccm, ec->symmetric_encryption_key(), ec->nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { + loggers::get_instance().warning("fx__encryptWithEciesSm2p256WithSha256: Failed to encrypt message"); + return OCTETSTRING(0, nullptr); + } + enc_message += ec->tag(); + loggers::get_instance().log_to_hexa("fx__encryptWithEciesSm2p256WithSha256: enc message||Tag: ", enc_message); + + return enc_message; + } + + /** + * @desc Test function for ECIES NIST P-256 Encryption with SHA-256 + * @remark For the purpose of testing, the content of p__toBeEncryptedSecuredMessage is the AES 128 symmetric key to be encrypted + */ + OCTETSTRING fx__test__encryptWithEciesSm2p256WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, const OCTETSTRING &p__privateEphemeralKey, + const OCTETSTRING &p__recipientPublicKeyX, const OCTETSTRING &p__recipientPublicKeyY, + const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyX, OCTETSTRING &p__publicEphemeralKeyY, + OCTETSTRING &p__aes__sym__key, OCTETSTRING &p__encrypted__sym__key, + OCTETSTRING &p__authentication__vector, OCTETSTRING &p__nonce) { + + // 1. Generate new ephemeral Private/Public keys + security_ecc ec(ec_elliptic_curves::sm2_p_256, p__privateEphemeralKey); + p__publicEphemeralKeyX = ec.public_key_x(); + p__publicEphemeralKeyY = ec.public_key_y(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: Vx=", p__publicEphemeralKeyX); + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: Vy=", p__publicEphemeralKeyY); + + // 2. Generate and derive shared secret + security_ecc ec_comp(ec_elliptic_curves::sm2_p_256, p__recipientPublicKeyX, p__recipientPublicKeyY); + ec.symmetric_encryption_key(p__toBeEncryptedSecuredMessage); + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: ", ec.encrypted_symmetric_key()); + if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { + loggers::get_instance().warning("fx__test__encryptWithEciesSm2p256WithSha256: Failed to generate and derive secret key"); + return OCTETSTRING(0, nullptr); + } + + // Set the AES symmetric key + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: AES symmetric key: ", ec.symmetric_encryption_key()); + p__aes__sym__key = ec.symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: p__aes__sym__key: ", p__aes__sym__key); + // Set the encrypted symmetric key + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: Encrypted symmetric key: ", ec.encrypted_symmetric_key()); + p__encrypted__sym__key = ec.encrypted_symmetric_key(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + // Set the tag of the symmetric key encryption + p__authentication__vector = ec.tag(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: p__authentication__vector: ", p__authentication__vector); + // 3. Retrieve AES 128 parameters + p__nonce = ec.nonce(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesSm2p256WithSha256: p__nonce: ", p__nonce); + // 4. Encrypt the data using AES-128 CCM + OCTETSTRING enc_message; + if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { + loggers::get_instance().warning("fx__test__encryptWithEciesSm2p256WithSha256: Failed to encrypt message"); + return OCTETSTRING(0, nullptr); + } + enc_message += ec.tag(); + loggers::get_instance().log_to_hexa("fx__test__encryptWithEciesSm2p256WithSha256: enc message||Tag: ", enc_message); + + return enc_message; + } + + /** + * \fn OCTETSTRING fx__decryptWithEciesSm2p256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const + * OCTETSTRING& p__publicEphemeralKeyX, const OCTETSTRING& p__publicEphemeralKeyY, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& + * p__authentication__vector, const OCTETSTRING& p__nonce); \brief Decrypt the message using ECIES algorithm to decrypt AES 128 CCM symmetric key, as defined + * in IEEE Std 1609.2-2017 \param[in] p__encryptedSecuredMessage The encrypted message \param[in] p__privateEncKey The private encryption key \param[in] + * p__publicEphemeralKeyCompressed The public ephemeral compressed key \param[in] p__ephemeralCompressedMode The compressed mode, 0 if the latest bit of + * Y-coordinate is 0, 1 otherwise \param[in] p__encrypted__sym__key The encrypted AES 128 symmetric key \param[in] p__authentication__vector The tag of the + * encrypted AES 128 symmetric key \param[in] p__nonce The nonce vector \return The original message \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key + * encryption algorithms: ECIES \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ \see + * http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf + */ + // TODO Use common function for both fx__encryptWithEciesxxx and fx__decryptWithEciesxxx function + OCTETSTRING fx__decryptWithEciesSm2p256WithSha256(const OCTETSTRING &p__encryptedSecuredMessage, const OCTETSTRING &p__privateEncKey, + const OCTETSTRING &p__publicEphemeralKeyCompressed, const INTEGER &p__ephemeralCompressedMode, + const OCTETSTRING &p__encrypted__sym__key, const OCTETSTRING &p__authentication__vector, + const OCTETSTRING &p__nonce, const OCTETSTRING &p__salt, OCTETSTRING &p__aes__sym__enc__key) { + loggers::get_instance().log_msg(">>> fx__decryptWithEciesSm2p256WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesSm2p256WithSha256: p__privateEncKey: ", p__privateEncKey); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesSm2p256WithSha256: p__publicEphemeralKeyCompressed: ", p__publicEphemeralKeyCompressed); + loggers::get_instance().log(">>> fx__decryptWithEciesSm2p256WithSha256: p__ephemeralCompressedMode: %d", static_cast(p__ephemeralCompressedMode)); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesSm2p256WithSha256: p__nonce: ", p__nonce); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesSm2p256WithSha256: p__authentication__vector: ", p__authentication__vector); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesSm2p256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesSm2p256WithSha256: p__salt", p__salt); + + // 1. Create security_ecc instance based on recipient's private key + security_ecc ec(ec_elliptic_curves::sm2_p_256, p__privateEncKey); + security_ecc ec_comp(ec_elliptic_curves::sm2_p_256, p__publicEphemeralKeyCompressed, + (static_cast(p__ephemeralCompressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + + // 2. Generate the shared secret value based on public ephemeral keys will be required + if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__encrypted__sym__key, + p__nonce, p__authentication__vector, p__salt) == -1) { + loggers::get_instance().warning("fx__decryptWithEciesSm2p256WithSha256: Failed to generate shared secret"); + return OCTETSTRING(0, nullptr); + } + + // Decrypt the message + OCTETSTRING enc_message(p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof(), + static_cast(p__encryptedSecuredMessage)); // Extract the encrypted message + loggers::get_instance().log_msg("fx__decryptWithEciesSm2p256WithSha256: enc_message: ", enc_message); // Extract the ctag value + OCTETSTRING tag(ec.tag().lengthof(), + static_cast(p__encryptedSecuredMessage) + p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof()); + loggers::get_instance().log_msg("fx__decryptWithEciesSm2p256WithSha256: tag: ", tag); + OCTETSTRING message; + if (ec.decrypt(tag, enc_message, message) == -1) { + loggers::get_instance().warning("fx__decryptWithEciesSm2p256WithSha256: Failed to generate shared secret"); + return OCTETSTRING(0, nullptr); + } + loggers::get_instance().log_msg("fx__decryptWithEciesSm2p256WithSha256: dec message: ", message); + p__aes__sym__enc__key = ec.symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__decryptWithEciesSm2p256WithSha256: AES 128 encryption key: ", p__aes__sym__enc__key); + + return message; + } + + + + + + + + + + + + + + + + + + + + + + OCTETSTRING fx__encryptWithEciesBrainpoolp256r1WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, + const OCTETSTRING &p__recipientsPublicKeyCompressed, const INTEGER &p__compressedMode, + const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyCompressed, + INTEGER &p__ephemeralCompressedMode, OCTETSTRING &p__aes__sym__key, + OCTETSTRING &p__encrypted__sym__key, OCTETSTRING &p__authentication__vector, + OCTETSTRING &p__nonce) { + loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed); + loggers::get_instance().log(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__compressedMode: %d", static_cast(p__compressedMode)); + loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256r1WithSha256: p__salt: ", p__salt); + + // 1. Generate new Private/Public Ephemeral key + std::unique_ptr ec; + ec.reset(new security_ecc(ec_elliptic_curves::brainpool_p_256_r1)); + if (ec->generate() == -1) { + loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate ephemeral keys"); + return OCTETSTRING(0, nullptr); + } + // 2. Generate and derive shared secret based on recipient's private keys + security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientsPublicKeyCompressed, + (static_cast(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (ec->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { + loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate and derive secret key"); + return OCTETSTRING(0, nullptr); + } + + // Set the AES symmetric key + loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: AES symmetric key: ", ec->symmetric_encryption_key()); + p__aes__sym__key = ec->symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__aes__sym__key: ", p__aes__sym__key); + // Set the encrypted symmetric key + loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: Encrypted symmetric key: ", ec->encrypted_symmetric_key()); + p__encrypted__sym__key = ec->encrypted_symmetric_key(); + loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + // Set the tag of the symmetric key encryption + p__authentication__vector = ec->tag(); + loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__authentication__vector: ", p__authentication__vector); + // Set ephemeral public keys + p__publicEphemeralKeyCompressed = ec->public_key_compressed(); + loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed); + p__ephemeralCompressedMode = (ec->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1; + loggers::get_instance().log("fx__encryptWithEciesBrainpoolp256r1WithSha256: Ephemeral public compressed mode: %d: ", (int)p__ephemeralCompressedMode); + // 3. Retrieve AES 128 parameters + p__nonce = ec->nonce(); + loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256r1WithSha256: p__nonce: ", p__nonce); + // 4. Encrypt the data using AES-128 CCM + OCTETSTRING enc_message; + if (ec->encrypt(encryption_algotithm::aes_128_ccm, ec->symmetric_encryption_key(), ec->nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { + loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256r1WithSha256: Failed to encrypt message"); + return OCTETSTRING(0, nullptr); + } + enc_message += ec->tag(); + loggers::get_instance().log_to_hexa("fx__encryptWithEciesBrainpoolp256r1WithSha256: enc message||Tag: ", enc_message); + + return enc_message; + } + + /** + * @desc Test function for ECIES BRAINPOOL P-256r1 Encryption with SHA-256 + * @remark For the purpose of testing, the content of p__toBeEncryptedSecuredMessage is the AES 128 symmetric key to be encrypted + */ + OCTETSTRING fx__test__encryptWithEciesBrainpoolp256r1WithSha256(const OCTETSTRING &p__toBeEncryptedSecuredMessage, const OCTETSTRING &p__privateEphemeralKey, + const OCTETSTRING &p__recipientPublicKeyX, const OCTETSTRING &p__recipientPublicKeyY, + const OCTETSTRING &p__salt, OCTETSTRING &p__publicEphemeralKeyX, + OCTETSTRING &p__publicEphemeralKeyY, OCTETSTRING &p__aes__sym__key, + OCTETSTRING &p__encrypted__sym__key, OCTETSTRING &p__authentication__vector, + OCTETSTRING &p__nonce) { + + // 1. Generate new ephemeral Private/Public keys + security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1, p__privateEphemeralKey); + p__publicEphemeralKeyX = ec.public_key_x(); + p__publicEphemeralKeyY = ec.public_key_y(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Vx=", p__publicEphemeralKeyX); + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Vy=", p__publicEphemeralKeyY); + + // 2. Generate and derive shared secret + security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientPublicKeyX, p__recipientPublicKeyY); + ec.symmetric_encryption_key(p__toBeEncryptedSecuredMessage); + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: ", ec.encrypted_symmetric_key()); + if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) { + loggers::get_instance().warning("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Failed to generate and derive secret key"); + return OCTETSTRING(0, nullptr); + } + + // Set the AES symmetric key + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: AES symmetric key: ", ec.symmetric_encryption_key()); + p__aes__sym__key = ec.symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__aes__sym__key: ", p__aes__sym__key); + // Set the encrypted symmetric key + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Encrypted symmetric key: ", ec.encrypted_symmetric_key()); + p__encrypted__sym__key = ec.encrypted_symmetric_key(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + // Set the tag of the symmetric key encryption + p__authentication__vector = ec.tag(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__authentication__vector: ", p__authentication__vector); + // 3. Retrieve AES 128 parameters + p__nonce = ec.nonce(); + loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: p__nonce: ", p__nonce); + // 4. Encrypt the data using AES-128 CCM + OCTETSTRING enc_message; + if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) { + loggers::get_instance().warning("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: Failed to encrypt message"); + return OCTETSTRING(0, nullptr); + } + enc_message += ec.tag(); + loggers::get_instance().log_to_hexa("fx__test__encryptWithEciesBrainpoolp256r1WithSha256: enc message||Tag: ", enc_message); + + return enc_message; + } + + OCTETSTRING fx__decryptWithEciesBrainpoolp256r1WithSha256(const OCTETSTRING &p__encryptedSecuredMessage, const OCTETSTRING &p__privateEncKey, + const OCTETSTRING &p__publicEphemeralKeyCompressed, const INTEGER &p__ephemeralCompressedMode, + const OCTETSTRING &p__encrypted__sym__key, const OCTETSTRING &p__authentication__vector, + const OCTETSTRING &p__nonce, const OCTETSTRING &p__salt, OCTETSTRING &p__aes__sym__enc__key) { + loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__privateEncKey: ", p__privateEncKey); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__publicEphemeralKeyCompressed: ", p__publicEphemeralKeyCompressed); + loggers::get_instance().log(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__ephemeralCompressedMode: %d", + static_cast(p__ephemeralCompressedMode)); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__nonce: ", p__nonce); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__authentication__vector: ", p__authentication__vector); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key); + loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256r1WithSha256: p__salt", p__salt); + + // 1. Create security_ecc instance based on public ephemeral keys + security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1, p__privateEncKey); + security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__publicEphemeralKeyCompressed, + (static_cast(p__ephemeralCompressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + + // 2. Generate the shared secret value based on public ephemeral keys will be required + if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__encrypted__sym__key, + p__nonce, p__authentication__vector, OCTETSTRING(0, nullptr)) == -1) { + loggers::get_instance().warning("fx__decryptWithEciesBrainpoolp256r1WithSha256: Failed to generate shared secret"); + return OCTETSTRING(0, nullptr); + } + + // Decrypt the message + OCTETSTRING enc_message(p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof(), + static_cast(p__encryptedSecuredMessage)); // Extract the encrypted message + loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256r1WithSha256: enc_message: ", enc_message); // Extract the ctag value + OCTETSTRING tag(ec.tag().lengthof(), + static_cast(p__encryptedSecuredMessage) + p__encryptedSecuredMessage.lengthof() - ec.tag().lengthof()); + loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256r1WithSha256: tag: ", tag); + OCTETSTRING message; + if (ec.decrypt(tag, enc_message, message) == -1) { + loggers::get_instance().warning("fx__decryptWithEciesBrainpoolp256r1WithSha256: Failed to generate shared secret"); + return OCTETSTRING(0, nullptr); + } + loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256r1WithSha256: dec message: ", message); + p__aes__sym__enc__key = ec.symmetric_encryption_key(); + loggers::get_instance().log_msg("fx__decryptWithEciesBrainpoolp256r1WithSha256: AES 128 encryption key: ", p__aes__sym__enc__key); + + return message; + } + + /** + * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. + * This function should not be used by the ATS + * \param p_privateKey The new private key value + * \param p_publicKeyX The new public key value (x coordinate) + * \param p_publicKeyX The new public key value (y coordinate) + * \return true on success, false otherwise + fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; + */ + BOOLEAN fx__generateKeyPair__nistp256(OCTETSTRING &p__privateKey, OCTETSTRING &p__publicKeyX, OCTETSTRING &p__publicKeyY, OCTETSTRING &p__publicKeyCompressed, + INTEGER &p__compressedMode) { + security_ecc k(ec_elliptic_curves::nist_p_256); + if (k.generate() != 0) { + p__privateKey = OCTETSTRING(0, nullptr); + p__publicKeyX = OCTETSTRING(0, nullptr); + p__publicKeyY = OCTETSTRING(0, nullptr); + p__publicKeyCompressed = OCTETSTRING(0, nullptr); + return FALSE; + } + // Sanity checks + if (k.private_key().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__nistp256: Invalid public compressed key size"); + return FALSE; + } + p__privateKey = k.private_key(); + p__publicKeyX = k.public_key_x(); + p__publicKeyY = k.public_key_y(); + p__publicKeyCompressed = k.public_key_compressed(); + p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); + + return TRUE; + } + + /** + * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. + * This function should not be used by the ATS + * \param p_privateKey The new private key value + * \param p_publicKeyX The new public key value (x coordinate) + * \param p_publicKeyX The new public key value (y coordinate) + * \return true on success, false otherwise + fx_generateKeyPair_nistp384(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; + */ + BOOLEAN fx__generateKeyPair__nistp384(OCTETSTRING &p__privateKey, OCTETSTRING &p__publicKeyX, OCTETSTRING &p__publicKeyY, OCTETSTRING &p__publicKeyCompressed, + INTEGER &p__compressedMode) { + security_ecc k(ec_elliptic_curves::nist_p_384); + if (k.generate() != 0) { + p__privateKey = OCTETSTRING(0, nullptr); + p__publicKeyX = OCTETSTRING(0, nullptr); + p__publicKeyY = OCTETSTRING(0, nullptr); + p__publicKeyCompressed = OCTETSTRING(0, nullptr); + return FALSE; + } + // Sanity checks + if (k.private_key().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__nistp384: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__nistp384: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__nistp384: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__nistp384: Invalid public compressed key size"); + return FALSE; + } + p__privateKey = k.private_key(); + p__publicKeyX = k.public_key_x(); + p__publicKeyY = k.public_key_y(); + p__publicKeyCompressed = k.public_key_compressed(); + p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); + + return TRUE; + } + + /** + * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. + * This function should not be used by the ATS + * \param p_privateKey The new private key value + * \param p_publicKeyX The new public key value (x coordinate) + * \param p_publicKeyX The new public key value (y coordinate) + * \return true on success, false otherwise + fx_generateKeyPair_sm2p256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; + */ + BOOLEAN fx__generateKeyPair__sm2p256(OCTETSTRING &p__privateKey, OCTETSTRING &p__publicKeyX, OCTETSTRING &p__publicKeyY, OCTETSTRING &p__publicKeyCompressed, + INTEGER &p__compressedMode) { + security_ecc k(ec_elliptic_curves::sm2_p_256); + if (k.generate() != 0) { + p__privateKey = OCTETSTRING(0, nullptr); + p__publicKeyX = OCTETSTRING(0, nullptr); + p__publicKeyY = OCTETSTRING(0, nullptr); + p__publicKeyCompressed = OCTETSTRING(0, nullptr); + return FALSE; + } + // Sanity checks + if (k.private_key().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__sm2p256: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__sm2p256: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__sm2p256: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__sm2p256: Invalid public compressed key size"); + return FALSE; + } + p__privateKey = k.private_key(); + p__publicKeyX = k.public_key_x(); + p__publicKeyY = k.public_key_y(); + p__publicKeyCompressed = k.public_key_compressed(); + p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); + + return TRUE; + } + + /** + * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. + * This function should not be used by the ATS + * \param p_privateKey The new private key value + * \param p_publicKeyX The new public key value (x coordinate) + * \param p_publicKeyX The new public key value (y coordinate) + * \return true on success, false otherwise + fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; + */ + BOOLEAN fx__generateKeyPair__brainpoolp256r1(OCTETSTRING &p__privateKey, OCTETSTRING &p__publicKeyX, OCTETSTRING &p__publicKeyY, + OCTETSTRING &p__publicKeyCompressed, INTEGER &p__compressedMode) { + security_ecc k(ec_elliptic_curves::brainpool_p_256_r1); + if (k.generate() != 0) { + p__privateKey = OCTETSTRING(0, nullptr); + p__publicKeyX = OCTETSTRING(0, nullptr); + p__publicKeyY = OCTETSTRING(0, nullptr); + p__publicKeyCompressed = OCTETSTRING(0, nullptr); + return FALSE; + } + + // Sanity checks + if (k.private_key().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__brainpoolp256r1: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__brainpoolp256r1: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__brainpoolp256r1: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 32) { + loggers::get_instance().error("fx__generateKeyPair__brainpoolp256r1: Invalid public compressed key size"); + return FALSE; + } + p__privateKey = k.private_key(); + p__publicKeyX = k.public_key_x(); + p__publicKeyY = k.public_key_y(); + p__publicKeyCompressed = k.public_key_compressed(); + p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); + + return TRUE; + } + + /** + * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. + * This function should not be used by the ATS + * \param p_privateKey The new private key value + * \param p_publicKeyX The new public key value (x coordinate) + * \param p_publicKeyX The new public key value (y coordinate) + * \return true on success, false otherwise + fx_generateKeyPair_nistp256(out octetstring p_privateKey, out octetstring p_publicKeyX, out octetstring p_publicKeyY) return boolean; + */ + BOOLEAN fx__generateKeyPair__brainpoolp384r1(OCTETSTRING &p__privateKey, OCTETSTRING &p__publicKeyX, OCTETSTRING &p__publicKeyY, + OCTETSTRING &p__publicKeyCompressed, INTEGER &p__compressedMode) { + security_ecc k(ec_elliptic_curves::brainpool_p_384_r1); + if (k.generate() != 0) { + p__privateKey = OCTETSTRING(0, nullptr); + p__publicKeyX = OCTETSTRING(0, nullptr); + p__publicKeyY = OCTETSTRING(0, nullptr); + p__publicKeyCompressed = OCTETSTRING(0, nullptr); + return FALSE; + } + + // Sanity checks + if (k.private_key().lengthof() != 48) { + loggers::get_instance().error("fx__generateKeyPair__brainpoolp384r1: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 48) { + loggers::get_instance().error("fx__generateKeyPair__brainpoolp384r1: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 48) { + loggers::get_instance().error("fx__generateKeyPair__brainpoolp384r1: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 48) { + loggers::get_instance().error("fx__generateKeyPair__brainpoolp384r1: Invalid public compressed key size"); + return FALSE; + } + p__privateKey = k.private_key(); + p__publicKeyX = k.public_key_x(); + p__publicKeyY = k.public_key_y(); + p__publicKeyCompressed = k.public_key_compressed(); + p__compressedMode = INTEGER((int)k.public_key_compressed_mode()); + + return TRUE; + } + + BOOLEAN fx__get__uncompressed__key__nistp256(const OCTETSTRING &p__privateKey, const OCTETSTRING &p__publicKeyCompressed, const INTEGER &p__compressedMode, + OCTETSTRING &p__publicKeyY) { + security_ecc k(ec_elliptic_curves::nist_p_256, p__privateKey); + + // Sanity checks + if (k.private_key().lengthof() != 32) { + loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 32) { + loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 32) { + loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 32) { + loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public compressed key size"); + return FALSE; + } + // if (p__compressedMode != INTEGER((int)k.public_key_compressed_mode())) { + // loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public compressed mode"); + // return FALSE; + // } + // if (p__publicKeyCompressed != k.public_key_compressed()) { + // loggers::get_instance().error("fx__get__uncompressed__key__nistp256: Invalid public compressed key value"); + // return FALSE; + // } + + p__publicKeyY = k.public_key_y(); + + return TRUE; + } + + BOOLEAN fx__get__uncompressed__key__brainpoolp256r1(const OCTETSTRING &p__privateKey, const OCTETSTRING &p__publicKeyCompressed, + const INTEGER &p__compressedMode, OCTETSTRING &p__publicKeyY) { + security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, p__privateKey); + + // Sanity checks + if (k.private_key().lengthof() != 32) { + loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 32) { + loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 32) { + loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 32) { + loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public compressed key size"); + return FALSE; + } + // if (p__compressedMode != INTEGER((int)k.public_key_compressed_mode())) { + // loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public compressed mode"); + // return FALSE; + // } + // if (p__publicKeyCompressed != k.public_key_compressed()) { + // loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp256r1: Invalid public compressed key value"); + // return FALSE; + // } + + p__publicKeyY = k.public_key_y(); + + return TRUE; + } + + BOOLEAN fx__get__uncompressed__key__brainpoolp384r1(const OCTETSTRING &p__privateKey, const OCTETSTRING &p__publicKeyCompressed, + const INTEGER &p__compressedMode, OCTETSTRING &p__publicKeyY) { + security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__privateKey); + + // Sanity checks + if (k.private_key().lengthof() != 48) { + loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 48) { + loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 48) { + loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 48) { + loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public compressed key size"); + return FALSE; + } + // if (p__compressedMode != INTEGER((int)k.public_key_compressed_mode())) { + // loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public compressed mode"); + // return FALSE; + // } + // if (p__publicKeyCompressed != k.public_key_compressed()) { + // loggers::get_instance().error("fx__get__uncompressed__key__brainpoolp384r1: Invalid public compressed key value"); + // return FALSE; + // } + + p__publicKeyY = k.public_key_y(); + + return TRUE; + } + + BOOLEAN fx__get__uncompressed__key__nistp384(const OCTETSTRING &p__privateKey, const OCTETSTRING &p__publicKeyCompressed, + const INTEGER &p__compressedMode, OCTETSTRING &p__publicKeyY) { + security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, p__privateKey); + + // Sanity checks + if (k.private_key().lengthof() != 48) { + loggers::get_instance().error("fx__get__uncompressed__key__nistp384: Invalid private key size"); + return FALSE; + } + if (k.public_key_x().lengthof() != 48) { + loggers::get_instance().error("fx__get__uncompressed__key__nistp384: Invalid public key X-coordonate size"); + return FALSE; + } + if (k.public_key_y().lengthof() != 48) { + loggers::get_instance().error("fx__get__uncompressed__key__nistp384: Invalid public key Y-coordonate size"); + return FALSE; + } + if (k.public_key_compressed().lengthof() != 48) { + loggers::get_instance().error("fx__get__uncompressed__key__nistp384: Invalid public compressed key size"); + return FALSE; + } + // if (p__compressedMode != INTEGER((int)k.public_key_compressed_mode())) { + // loggers::get_instance().error("fx__get__uncompressed__key__nistp384: Invalid public compressed mode"); + // return FALSE; + // } + // if (p__publicKeyCompressed != k.public_key_compressed()) { + // loggers::get_instance().error("fx__get__uncompressed__key__nistp384: Invalid public compressed key value"); + // return FALSE; + // } + + p__publicKeyY = k.public_key_y(); + + return TRUE; + } + + // group encryption + + // group certificatesLoader + + /** + * \brief Load in memory cache the certificates available in the specified directory + * \param p_rootDirectory Root directory to access to the certificates identified by the certificate ID + * \param p_configId A configuration identifier + * @remark This method SHALL be call before any usage of certificates + * \return true on success, false otherwise + fx_loadCertificates(in charstring p_rootDirectory, in charstring p_configId) return boolean; + */ + BOOLEAN fx__loadCertificates(const CHARSTRING &p__rootDirectory, const CHARSTRING &p__configId) { + loggers::get_instance().log(">>> fx__loadCertificates: '%s', '%s'", static_cast(p__rootDirectory), static_cast(p__configId)); + + std::string str(static_cast(p__rootDirectory)); + if (p__configId.lengthof() != 0) { + str += "/"; + str += std::string(static_cast(p__configId)); + } + params_its params; + params.insert(std::pair(std::string("sec_db_path"), str)); + if (security_services_its::get_instance().setup(params) == -1) { + return FALSE; + } + + return TRUE; + } + + BOOLEAN fx__store__certificate(const INTEGER& p__signing__algorithm, const CHARSTRING &p__cert__id, const OCTETSTRING &p__cert, const OCTETSTRING &p__private__key, + const OCTETSTRING &p__public__key__x, const OCTETSTRING &p__public__key__y, const OCTETSTRING &p__public__key__compressed, + const INTEGER &p__public__key__compressed__mode, const OCTETSTRING &p__hash, const OCTETSTRING &p__hash__256, + const OCTETSTRING &p__hashid8, const OCTETSTRING &p__issuer, const OCTETSTRING_template &p__private__enc__key, + const OCTETSTRING_template &p__public__enc__key__x, const OCTETSTRING_template &p__public__enc__key__y, + const OCTETSTRING_template &p__public__enc__compressed__key, const INTEGER_template &p__public__enc__key__compressed__mode) { + loggers::get_instance().log(">>> fx__store__certificate: '%s'", static_cast(p__cert__id)); + + int result; + if (!p__private__enc__key.is_omit()) { + const OCTETSTRING private_enc_key = p__private__enc__key.valueof(); + const OCTETSTRING public_enc_key_x = p__public__enc__key__x.valueof(); + const OCTETSTRING public_enc_key_y = p__public__enc__key__y.valueof(); + result = security_services_its::get_instance().store_certificate( + static_cast(static_cast(p__signing__algorithm)), p__cert__id, p__cert, p__private__key, p__public__key__x, p__public__key__y, p__public__key__compressed, p__public__key__compressed__mode, p__hash, + p__hash__256, p__hashid8, p__issuer, p__private__enc__key.valueof(), p__public__enc__key__x.valueof(), p__public__enc__key__y.valueof(), + p__public__enc__compressed__key.valueof(), p__public__enc__key__compressed__mode.valueof()); + } else { + result = security_services_its::get_instance().store_certificate( + static_cast(static_cast(p__signing__algorithm)), p__cert__id, p__cert, p__private__key, p__public__key__x, p__public__key__y, p__public__key__compressed, p__public__key__compressed__mode, p__hash, + p__hash__256, p__hashid8, p__issuer, OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), OCTETSTRING(0, nullptr), INTEGER(-1)); + } + + return (result == 0); + } + + /** + * \brief Unload from memory cache the certificates + * \return true on success, false otherwise + */ + BOOLEAN fx__unloadCertificates() { return TRUE; } + + /** + * \brief Read the specified certificate + * \param p_certificate_id the certificate identifier + * \param p_certificate the expected certificate + * \return true on success, false otherwise + */ + BOOLEAN fx__readCertificate(const CHARSTRING &p__certificateId, OCTETSTRING &p__certificate) { + loggers::get_instance().log(">>> fx__readCertificate: '%s'", static_cast(p__certificateId)); + + if (security_services_its::get_instance().read_certificate(p__certificateId, p__certificate) == -1) { + return FALSE; + } + + return TRUE; + } + + BOOLEAN fx__readCertificateFromDigest(const OCTETSTRING &p__digest, CHARSTRING &p__certificateId) { + loggers::get_instance().log_msg(">>> fx__readCertificateFromDigest: ", p__digest); + + if (security_services_its::get_instance().read_certificate_from_digest(p__digest, p__certificateId) == -1) { + return FALSE; + } + loggers::get_instance().log_msg("fx__readCertificateFromDigest: ", p__certificateId); + + return TRUE; + } + + BOOLEAN fx__readCertificateFromHashedId3(const OCTETSTRING &p__digest, CHARSTRING &p__certificateId) { + loggers::get_instance().log_msg(">>> fx__readCertificateFromHashedId3: ", p__digest); + + if (security_services_its::get_instance().read_certificate_from_hashed_id3(p__digest, p__certificateId) == -1) { + return FALSE; + } + loggers::get_instance().log_msg("fx__readCertificateFromHashedId3: ", p__certificateId); + + return TRUE; + } + + /** + * \brief Read the specified certificate digest + * \param p_certificate_id the certificate identifier + * \param p_digest the expected certificate + * \return true on success, false otherwise + */ + BOOLEAN fx__readCertificateDigest(const CHARSTRING &p__certificateId, OCTETSTRING &p__digest) { + loggers::get_instance().log(">>> fx__readCertificateDigest: '%s'", static_cast(p__certificateId)); + + if (security_services_its::get_instance().read_certificate_digest(p__certificateId, p__digest) == -1) { + return FALSE; + } + + return TRUE; + } + + /** + * \brief Read the whole-hash of the certificate + * \param p_certificate_id the certificate identifier + * \param p_hash the expected certificate + * \return true on success, false otherwise + */ + BOOLEAN fx__readCertificateHash(const CHARSTRING &p__certificateId, OCTETSTRING &p__hash) { + loggers::get_instance().log(">>> fx__readCertificateHash: '%s'", static_cast(p__certificateId)); + + if (security_services_its::get_instance().read_certificate_hash(p__certificateId, p__hash) == -1) { + return FALSE; + } + + return TRUE; + } + + /** + * \brief Read the whole-hash of the certificate using SHA 256 + * \param p_certificate_id the certificate identifier + * \param p_hash the expected certificate + * \return true on success, false otherwise + */ + BOOLEAN fx__readCertificateHash256(const CHARSTRING &p__certificateId, OCTETSTRING &p__hash) { + loggers::get_instance().log(">>> fx__readCertificateHash256: '%s'", static_cast(p__certificateId)); + + if (security_services_its::get_instance().read_certificate_hash_sha_256(p__certificateId, p__hash) == -1) { + return FALSE; + } + + return TRUE; + } + + /** + * \brief Read the private keys for the specified certificate + * \param p_certificate_id the keys identifier + * \param p_signingPrivateKey the signing private key + * \return true on success, false otherwise + */ + BOOLEAN fx__readSigningKey(const CHARSTRING &p__certificateId, OCTETSTRING &p__signingPrivateKey) { + loggers::get_instance().log(">>> fx__readSigningKey: '%s'", static_cast(p__certificateId)); + + if (security_services_its::get_instance().read_private_key(p__certificateId, p__signingPrivateKey) == -1) { + return FALSE; + } + + return TRUE; + } + + /** + * \brief Read the private keys for the specified certificate + * \param p_keysId the keys identifier + * \param p_encryptPrivateKey the encrypt private key + * \return true on success, false otherwise + fx_readEncryptingKey(in charstring p_keysId, out Oct32 p_encryptingPrivateKey) return boolean; + */ + BOOLEAN fx__readEncryptingKey(const CHARSTRING &p__certificateId, OCTETSTRING &p__encryptingPrivateKey) { + loggers::get_instance().log(">>> fx__readSigningKey: '%s'", static_cast(p__certificateId)); + + if (security_services_its::get_instance().read_private_enc_key(p__certificateId, p__encryptingPrivateKey) == -1) { + return FALSE; + } + + return TRUE; + } + + BOOLEAN fx__reconstructPublicKeyNistP256( + const OCTETSTRING &p__cert__to__be__signed, + const OCTETSTRING &p__issuer, + const OCTETSTRING &p__reconstruct__public__key__compressed, + const INTEGER &p__compressedMode, + OCTETSTRING &p__public__key__x, + OCTETSTRING &p__public__key__y, + OCTETSTRING &p__public__key__compressed, + INTEGER &p__public__key__compressed_mode + ) { + loggers::get_instance().log_msg(">>> fx__reconstruct__public__key: p__cert__to__be__signed: ", p__cert__to__be__signed); + loggers::get_instance().log_msg(">>> fx__reconstruct__public__key: p__issuer: ", p__issuer); + loggers::get_instance().log_msg(">>> fx__reconstruct__public__key: p__reconstruct__public__key__compressed: ", p__reconstruct__public__key__compressed); + loggers::get_instance().log_msg(">>> fx__reconstruct__public__key: p__compressedMode: ", p__compressedMode); + + CHARSTRING certificate_id; + if (security_services_its::get_instance().read_certificate_from_digest(p__issuer, certificate_id) == -1) { + return FALSE; + } + OCTETSTRING public_key_x, public_key_y; + if (security_services_its::get_instance().read_public_keys(certificate_id, public_key_x, public_key_y) == -1) { + return FALSE; + } + // Create reconstruction key + security_ecc ecc(ec_elliptic_curves::nist_p_256, p__reconstruct__public__key__compressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (ecc.reconstruct_public_keys(p__cert__to__be__signed, public_key_x, public_key_y, p__public__key__x, p__public__key__y, p__public__key__compressed, p__public__key__compressed_mode) == -1) { + return FALSE; + } + + return TRUE; + } + + BOOLEAN fx__reconstructPublicKeyBrainpoolP256r1( + const OCTETSTRING &p__cert__to__be__signed, + const OCTETSTRING &p__issuer, + const OCTETSTRING &p__reconstruct__public__key__compressed, + const INTEGER &p__compressedMode, + OCTETSTRING &p__public__key__x, + OCTETSTRING &p__public__key__y, + OCTETSTRING &p__public__key__compressed, + INTEGER &p__public__key__compressed_mode + ) { + loggers::get_instance().log_msg(">>> fx_reconstructPublicKeyBrainpoolP256r1: p__cert__to__be__signed: ", p__cert__to__be__signed); + loggers::get_instance().log_msg(">>> fx_reconstructPublicKeyBrainpoolP256r1: p__issuer: ", p__issuer); + loggers::get_instance().log_msg(">>> fx_reconstructPublicKeyBrainpoolP256r1: p__reconstruct__public__key__compressed: ", p__reconstruct__public__key__compressed); + loggers::get_instance().log_msg(">>> fx_reconstructPublicKeyBrainpoolP256r1: p__compressedMode: ", p__compressedMode); + + CHARSTRING certificate_id; + if (security_services_its::get_instance().read_certificate_from_digest(p__issuer, certificate_id) == -1) { + return FALSE; + } + OCTETSTRING public_key_x, public_key_y; + if (security_services_its::get_instance().read_public_keys(certificate_id, public_key_x, public_key_y) == -1) { + return FALSE; + } + // Create reconstruction key + security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p__reconstruct__public__key__compressed, (p__compressedMode == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1); + if (ecc.reconstruct_public_keys(p__cert__to__be__signed, public_key_x, public_key_y, p__public__key__x, p__public__key__y, p__public__key__compressed, p__public__key__compressed_mode) == -1) { + return FALSE; + } + + return TRUE; + } + + // group geospacial + + /* * \brief Check that given polygon doesn't have neither self-intersections nor holes. + * \param p_region Polygonal Region + * \return true on success, false otherwise + * @verdict Unchanged + fx_isValidPolygonalRegion(in PolygonalRegion p_region) return boolean; + */ + BOOLEAN fx__isValidPolygonalRegion(const Ieee1609Dot2BaseTypes::PolygonalRegion &p__region) { return TRUE; } + + /* * \brief Check if a polygonal region is inside another one + * \param p_parent The main polygonal region + * \param p_region The polygonal region to be included + * \return true on success, false otherwise + * @verdict Unchanged + fx_isPolygonalRegionInside(in PolygonalRegion p_parent, in PolygonalRegion p_region) return boolean; + */ + BOOLEAN fx__isPolygonalRegionInside(const Ieee1609Dot2BaseTypes::PolygonalRegion &p__parent, const Ieee1609Dot2BaseTypes::PolygonalRegion &p__region) { + return TRUE; + } + + /* * \brief Check that the location is inside a circular region + * \param p_region The circular region to consider + * \param p_location The device location + * \return true on success, false otherwise + * @verdict Unchanged + fx_isLocationInsideCircularRegion(in CircularRegion p_region, in ThreeDLocation p_location) return boolean; + */ + BOOLEAN fx__isLocationInsideCircularRegion(const Ieee1609Dot2BaseTypes::CircularRegion &p__region, const Ieee1609Dot2BaseTypes::ThreeDLocation &p__location) { + return TRUE; + } + + /* * \brief Check that the location is inside a rectangular region + * \param p_region The rectangular region to consider + * \param p_location The device location + * \return true on success, false otherwise + * @verdict Unchanged + fx_isLocationInsideRectangularRegion(in SequenceOfRectangularRegion p_region, in ThreeDLocation p_location) return boolean; + */ + BOOLEAN fx__isLocationInsideRectangularRegion(const Ieee1609Dot2BaseTypes::SequenceOfRectangularRegion &p__region, + const Ieee1609Dot2BaseTypes::ThreeDLocation & p__location) { + return TRUE; + } + + /* * \brief Check that the location is inside a polygonal region + * \param p_region The polygonal region to consider + * \param p_location The device location + * \return true on success, false otherwise + * @verdict Unchanged + fx_isLocationInsidePolygonalRegion(in PolygonalRegion p_region, in ThreeDLocation p_location) return boolean; + */ + BOOLEAN fx__isLocationInsidePolygonalRegion(const Ieee1609Dot2BaseTypes::PolygonalRegion &p__region, + const Ieee1609Dot2BaseTypes::ThreeDLocation & p__location) { + return TRUE; + } + + /* * \brief Check if the location is inside an identified region + * \param p_region The identified region to consider + * \param p_location The device location + * \return true on success, false otherwise + * @verdict Unchanged + fx_isLocationInsideIdentifiedRegion(in IdentifiedRegion p_region, in ThreeDLocation p_location) return boolean; + */ + BOOLEAN fx__isLocationInsideIdentifiedRegion(const Ieee1609Dot2BaseTypes::IdentifiedRegion &p__region, + const Ieee1609Dot2BaseTypes::ThreeDLocation & p__location) { + return TRUE; + } + + /* * \brief Check if the location is inside an undefined region + * \param p_region The identified region to consider + * \param p_location The device location + * \return true on success, false otherwise + * @verdict Unchanged + fx_isLocationInsideOtherRegion(in octetstring p_region, in ThreeDLocation p_location) return boolean; + */ + BOOLEAN fx__isLocationInsideOtherRegion(const OCTETSTRING &p_region, const Ieee1609Dot2BaseTypes::ThreeDLocation &p_location) { return TRUE; } + + /** + * \brief Check that p_circular_region_1 circular region is included into p_circular_region_2 circular region + * \param p_circular_region_1 Circular region 1 + * \param p_circular_region_2 Circular region 2 + * \return true on success, false otherwise + fx_areCirclesInside(in CircularRegion p_circular_region_1, in CircularRegion p_circular_region_2) return boolean; + */ + BOOLEAN fx__areCirclesInside(const Ieee1609Dot2BaseTypes::CircularRegion &p_circular_region_1, + const Ieee1609Dot2BaseTypes::CircularRegion &p_circular_region_2) { + // Compute distance between the 2 radius + FLOAT d = LibItsCommon__Functions::fx__computeDistance(p_circular_region_1.center().latitude(), p_circular_region_1.center().longitude(), + p_circular_region_2.center().latitude(), p_circular_region_2.center().longitude()); + if ((float)abs(p_circular_region_1.radius() - p_circular_region_2.radius()) > (float)d) { + return FALSE; + } + return TRUE; + } + + /* * \brief Check that p_rectanglar_region_1 rectangular region is included into p_rectanglar_region_2 rectangular region + * \param p_rectanglar_region_1 Rectangular region 1 + * \param p_rectanglar_region_2 Rectangular region 2 + * \return true on success, false otherwise + fx_areRectanglesInside(in SequenceOfRectangularRegion p_rectanglar_region_1, in SequenceOfRectangularRegion p_rectanglar_region_2) return boolean; + */ + BOOLEAN fx__areRectanglesInside(const Ieee1609Dot2BaseTypes::SequenceOfRectangularRegion &p_rectanglar_region_1, + const Ieee1609Dot2BaseTypes::SequenceOfRectangularRegion &p_rectanglar_region_2) { + + return TRUE; + } + + /* * \brief Check that p_polygonal_region_1 polygonal region is included into p_polygonal_region_2 polygonal region + * \param p_polygonal_region_1 Polygonal region 1 + * \param p_polygonal_region_2 Polygonal region 2 + * \return true on success, false otherwise + fx_arePolygonsInside(in PolygonalRegion p_polygonal_region_1, in PolygonalRegion p_polygonal_region_2) return boolean; + */ + BOOLEAN fx__arePolygonsInside(const Ieee1609Dot2BaseTypes::PolygonalRegion &p_polygonal_region_1, + const Ieee1609Dot2BaseTypes::PolygonalRegion &p_polygonal_region_2) { + return TRUE; + } + + /** + * \brief Convert a spacial coordinate from DMS to DMS + * \param p_degrees The degrees (D) + * \param p_minutes The minutes (M) + * \param p_seconds The seconds (S) + * \param p_latlon The latitude/longitude: (N|S|E|W) + * \return The decimal coordinate on success, 0.0, otherwise + * @verdict Unchanged + fx_dms2dd(in Int p_degrees, in Int p_minutes, in float p_seconds, in Oct1 p_latlon) return float; + */ + FLOAT fx__dms2dd(const INTEGER &p__degrees, const INTEGER &p__minutes, const FLOAT &p__seconds, const OCTETSTRING &p__latlon) { return 0.0; } + + FLOAT fx__int2ddlat(const INTEGER &p__latitude) { return (float)((float)p__latitude / 10000000.0); } + + FLOAT fx__int2ddlon(const INTEGER &p__longitude) { return (float)((float)p__longitude / 1000000.0); } + +} // namespace LibItsSecurity__Functions diff --git a/ccsrc/Externals/module.mk b/ccsrc/Externals/module.mk index 8dab377ca9e6d192312d8651faf8e1f23a27bf97..4f64a36fd9ce0b1ec2dc0c37c8f5129fb0daf624 100644 --- a/ccsrc/Externals/module.mk +++ b/ccsrc/Externals/module.mk @@ -4,7 +4,6 @@ sources := LibItsCommon_externals.cc \ includes := ../geospacial - ifeq (AtsCAM, $(ATS)) sources += LibItsSecurity_externals.cc endif @@ -25,6 +24,10 @@ ifeq (AtsPki, $(ATS)) sources += LibItsPki_externals.cc LibItsSecurity_externals.cc endif +ifeq (AtsMBR, $(ATS)) +sources += LibItsMbr_externals.cc LibItsSecurity_externals.cc +endif + ifeq (AtsGeoNetworking, $(ATS)) sources += LibItsSecurity_externals.cc endif diff --git a/ccsrc/Ports/LibIts_ports/MBR_ports/AdapterControlPort_Mbr.cc b/ccsrc/Ports/LibIts_ports/MBR_ports/AdapterControlPort_Mbr.cc new file mode 100644 index 0000000000000000000000000000000000000000..6cf40ce69ab7ae57f010f5f3373d9391bb26d80c --- /dev/null +++ b/ccsrc/Ports/LibIts_ports/MBR_ports/AdapterControlPort_Mbr.cc @@ -0,0 +1,88 @@ +#include + +#include "loggers.hh" +#include "registration.hh" + +#include "AdapterControlPort_Mbr.hh" +//============================================================================= +namespace LibItsMbr__TestSystem { + + AdapterControlPort::AdapterControlPort(const char *par_port_name) : AdapterControlPort_BASE(par_port_name)/*, _params()*/ { + loggers::get_instance().log("AdapterControlPort::AdapterControlPort"); + } + + AdapterControlPort::~AdapterControlPort() {} + + void AdapterControlPort::set_parameter(const char *parameter_name, const char *parameter_value) { + loggers::get_instance().log("AdapterControlPort::set_parameter: %s=%s", parameter_name, parameter_value); + } + + /*void AdapterControlPort::Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error) {}*/ + + void AdapterControlPort::Handle_Fd_Event_Error(int /*fd*/) {} + + void AdapterControlPort::Handle_Fd_Event_Writable(int /*fd*/) {} + + void AdapterControlPort::Handle_Fd_Event_Readable(int /*fd*/) {} + + /*void AdapterControlPort::Handle_Timeout(double time_since_last_call) {}*/ + + void AdapterControlPort::user_map(const char *system_port) { loggers::get_instance().log(">>> AdapterControlPort::user_map: %s", system_port); } + + void AdapterControlPort::user_unmap(const char *system_port) { loggers::get_instance().log(">>> AdapterControlPort::user_unmap: %s", system_port); } + + void AdapterControlPort::user_start() {} + + void AdapterControlPort::user_stop() {} + + void AdapterControlPort::outgoing_send(const LibItsMbr__TypesAndValues::AcMbrPrimitive &send_par) {/* + loggers::get_instance().log_msg(">>> AdapterControlPort::outgoing_send: ", send_par); + + // Register this object for AdapterControlPort + geonetworking_layer *p = registration::get_instance().get_item(std::string("GN")); + if (p != NULL) { + loggers::get_instance().log("AdapterControlPort::outgoing_send: Got GN layer %p", p); + LibItsGeoNetworking__TypesAndValues::AcGnResponse response; + response.failure() = LibItsGeoNetworking__TypesAndValues::AcGnResponseFailure(BOOLEAN(false)); + if (send_par.ischosen(LibItsGeoNetworking__TypesAndValues::AcGnPrimitive::ALT_startBeaconing)) { + loggers::get_instance().log("AdapterControlPort::outgoing_send: Start beaconing"); + p->start_beaconing(send_par.startBeaconing().beaconPacket()); + // No response + return; + } else if (send_par.ischosen(LibItsGeoNetworking__TypesAndValues::AcGnPrimitive::ALT_stopBeaconing)) { + loggers::get_instance().log("AdapterControlPort::outgoing_send: Stop beaconing"); + p->stop_beaconing(); + // No response + return; + } else if (send_par.ischosen(LibItsGeoNetworking__TypesAndValues::AcGnPrimitive::ALT_getLongPosVector)) { + loggers::get_instance().log("AdapterControlPort::outgoing_send: Get LongPosVector"); + const LibItsGeoNetworking__TypesAndValues::LongPosVector *lpv = p->get_lpv(send_par.getLongPosVector().gnAddress()); + loggers::get_instance().log("AdapterControlPort::outgoing_send: Return value: %p", lpv); + if (lpv == nullptr) { + response.failure() = LibItsGeoNetworking__TypesAndValues::AcGnResponseFailure(BOOLEAN(true)); + } else { + response.getLongPosVector() = *lpv; + } + } else if (send_par.ischosen(LibItsGeoNetworking__TypesAndValues::AcGnPrimitive::ALT_startPassBeaconing)) { + loggers::get_instance().log("AdapterControlPort::outgoing_send: Start pass beaconing"); + p->start_pass_beaconing(send_par.startPassBeaconing().beaconHeader()); + // No response + return; + } else if (send_par.ischosen(LibItsGeoNetworking__TypesAndValues::AcGnPrimitive::ALT_stopPassBeaconing)) { + loggers::get_instance().log("AdapterControlPort::outgoing_send: Stop pass beaconing"); + p->stop_pass_beaconing(); + // No response + return; + } else { + response.failure() = LibItsGeoNetworking__TypesAndValues::AcGnResponseFailure(BOOLEAN(true)); + } + // Send response + loggers::get_instance().log_msg("AdapterControlPort::outgoing_send: Send response: ", response); + incoming_message(response); + } else { + loggers::get_instance().error("AdapterControlPort::outgoing_send: %s not registered", "geoNetworkingPort"); + }*/ + } + +} // namespace LibItsMbr__TestSystem diff --git a/ccsrc/Ports/LibIts_ports/MBR_ports/AdapterControlPort_Mbr.hh b/ccsrc/Ports/LibIts_ports/MBR_ports/AdapterControlPort_Mbr.hh new file mode 100644 index 0000000000000000000000000000000000000000..fadf4b9f810feba11b696486c3eb3ae759694bd7 --- /dev/null +++ b/ccsrc/Ports/LibIts_ports/MBR_ports/AdapterControlPort_Mbr.hh @@ -0,0 +1,38 @@ +//============================================================================= +#ifndef AdapterControlPort_Mbr_HH +#define AdapterControlPort_Mbr_HH + +#include "LibItsMbr_TestSystem.hh" + +//#include "params.hh" + +namespace LibItsMbr__TestSystem { + + class AdapterControlPort : public AdapterControlPort_BASE { +// params _params; + + public: + AdapterControlPort(const char *par_port_name = NULL); + ~AdapterControlPort(); + + void set_parameter(const char *parameter_name, const char *parameter_value); + + private: + /* void Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error); */ + void Handle_Fd_Event_Error(int fd); + void Handle_Fd_Event_Writable(int fd); + void Handle_Fd_Event_Readable(int fd); + /* void Handle_Timeout(double time_since_last_call); */ + protected: + void user_map(const char *system_port); + void user_unmap(const char *system_port); + + void user_start(); + void user_stop(); + + void outgoing_send(const LibItsMbr__TypesAndValues::AcMbrPrimitive &send_par); + }; + +} // namespace LibItsMbr__TestSystem +#endif diff --git a/ccsrc/Ports/LibIts_ports/MBR_ports/UpperTesterMbrPort.cc b/ccsrc/Ports/LibIts_ports/MBR_ports/UpperTesterMbrPort.cc new file mode 100644 index 0000000000000000000000000000000000000000..9ae6f028bb9a2946b2b8f1e9dad8e5436fe8553d --- /dev/null +++ b/ccsrc/Ports/LibIts_ports/MBR_ports/UpperTesterMbrPort.cc @@ -0,0 +1,103 @@ +#include + +#include "UpperTesterMbrPort.hh" + +#include "loggers.hh" + +#include "uppertester_mbr_layer.hh" +#include "uppertester_mbr_layer_factory.hh" + +//============================================================================= +namespace LibItsMbr__TestSystem { + + UpperTesterMbrPort::UpperTesterMbrPort(const char *par_port_name) + : UpperTesterMbrPort_BASE(par_port_name), _cfg_params(), _layer_params(), _layer(NULL), _time_key("UpperTesterMbrPort_Mbr::outgoing_send") { + loggers::get_instance().log("UpperTesterMbrPort_Mbr::UpperTesterMbrPort_Mbr"); + } + + UpperTesterMbrPort::~UpperTesterMbrPort() { + if (_layer != NULL) { + delete _layer; + } + } + + void UpperTesterMbrPort::set_parameter(const char *parameter_name, const char *parameter_value) { + loggers::get_instance().log("UpperTesterMbrPort_Mbr::set_parameter: %s=%s", parameter_name, parameter_value); + _cfg_params.insert(std::pair(std::string(parameter_name), std::string(parameter_value))); + _cfg_params.log(); + } + + /*void UpperTesterMbrPort::Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error) {}*/ + + void UpperTesterMbrPort::Handle_Fd_Event_Error(int /*fd*/) {} + + void UpperTesterMbrPort::Handle_Fd_Event_Writable(int /*fd*/) {} + + void UpperTesterMbrPort::Handle_Fd_Event_Readable(int /*fd*/) {} + + /*void UpperTesterMbrPort::Handle_Timeout(double time_since_last_call) {}*/ + + void UpperTesterMbrPort::user_map(const char *system_port) { + loggers::get_instance().log(">>> UpperTesterMbrPort_Mbr::user_map: %s", system_port); + // Build layer stack + params_its::iterator it = _cfg_params.find(std::string("params")); + if (it != _cfg_params.end()) { + loggers::get_instance().log("UpperTesterMbrPort_Mbr::user_map: %s", it->second.c_str()); + _layer = layer_stack_builder::get_instance()->create_layer_stack(it->second.c_str()); + if (static_cast(_layer) == NULL) { + loggers::get_instance().error("UpperTesterMbrPort_Mbr::user_map: Invalid stack configuration: %s", it->second.c_str()); + } + static_cast(_layer)->add_upper_port(this); + } else { + loggers::get_instance().error("UpperTesterMbrPort_Mbr::user_map: No layers defined in configuration file"); + } + } + + void UpperTesterMbrPort::user_unmap(const char *system_port) { + loggers::get_instance().log(">>> UpperTesterMbrPort_Mbr::user_unmap: %s", system_port); + if (_layer != NULL) { + delete _layer; + _layer = NULL; + } + } + + void UpperTesterMbrPort::user_start() {} + + void UpperTesterMbrPort::user_stop() {} + + void UpperTesterMbrPort::outgoing_send(const LibItsMbr__TypesAndValues::UtMbrInitialize &send_par) { + loggers::get_instance().log_msg(">>> UppertesterPort::outgoing_send: ", send_par); + + float duration; + loggers::get_instance().set_start_time(_time_key); + static_cast(_layer)->sendMsg(send_par, _layer_params); + loggers::get_instance().set_stop_time(_time_key, duration); + } + + void UpperTesterMbrPort::outgoing_send(const LibItsMbr__TypesAndValues::UtMbrTrigger &send_par) { + loggers::get_instance().log_msg(">>> UppertesterPort::outgoing_send: ", send_par); + + float duration; + loggers::get_instance().set_start_time(_time_key); + static_cast(_layer)->sendMsg(send_par, _layer_params); + loggers::get_instance().set_stop_time(_time_key, duration); + } + + void UpperTesterMbrPort::receiveMsg(const Base_Type &p_ind, const params &p_params) { + loggers::get_instance().log_msg(">>> UpperTesterMbrPort_Mbr::receive_msg: ", p_ind); + // Sanity check + if (!p_ind.is_bound()) { + return; + } + + if (std::string(p_ind.get_descriptor()->name).compare("@LibItsMbr_TypesAndValues.UtMbrResults") == 0) { // TODO To be refined + incoming_message(static_cast(p_ind)); + } else if (std::string(p_ind.get_descriptor()->name).compare("@LibItsMbr_TypesAndValues.UtMbrEventInd") == 0) { // TODO To be refined + incoming_message(static_cast(p_ind)); + } else { + loggers::get_instance().warning("UpperTesterMbrPort_Mbr::receive_msg: Message not processed: %s", p_ind.get_descriptor()->name); + } + } + +} // namespace LibItsMbr__TestSystem diff --git a/ccsrc/Ports/LibIts_ports/MBR_ports/UpperTesterMbrPort.hh b/ccsrc/Ports/LibIts_ports/MBR_ports/UpperTesterMbrPort.hh new file mode 100644 index 0000000000000000000000000000000000000000..c1e1dc7df6c1c0a9b3cc04cdba948eef5a201c68 --- /dev/null +++ b/ccsrc/Ports/LibIts_ports/MBR_ports/UpperTesterMbrPort.hh @@ -0,0 +1,47 @@ +#ifndef UpperTesterMbrPort_HH +#define UpperTesterMbrPort_HH + +//============================================================================= +#include "LibItsMbr_TestSystem.hh" + +#include "layer.hh" +#include "params.hh" + +namespace LibItsMbr__TestSystem { + + class UpperTesterMbrPort : public UpperTesterMbrPort_BASE { + params _cfg_params; + params _layer_params; + layer * _layer; + std::string _time_key; + + public: + UpperTesterMbrPort(const char *par_port_name = NULL); + ~UpperTesterMbrPort(); + + void set_parameter(const char *parameter_name, const char *parameter_value); + + void receiveMsg(const Base_Type &, const params &); + + private: + /* void Handle_Fd_Event(int fd, boolean is_readable, + boolean is_writable, boolean is_error); */ + void Handle_Fd_Event_Error(int fd); + void Handle_Fd_Event_Writable(int fd); + void Handle_Fd_Event_Readable(int fd); + /* void Handle_Timeout(double time_since_last_call); */ + protected: + void user_map(const char *system_port); + void user_unmap(const char *system_port); + + void user_start(); + void user_stop(); + + void outgoing_send(const LibItsMbr__TypesAndValues::UtMbrInitialize &send_par); + + void outgoing_send(const LibItsMbr__TypesAndValues::UtMbrTrigger &send_par); + + }; + +} // namespace LibItsMbr__TestSystem +#endif diff --git a/ccsrc/Ports/LibIts_ports/MBR_ports/module.mk b/ccsrc/Ports/LibIts_ports/MBR_ports/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..26c1077eab6a25f1cc92ff4cce89d454c80b46b9 --- /dev/null +++ b/ccsrc/Ports/LibIts_ports/MBR_ports/module.mk @@ -0,0 +1,2 @@ +sources := UpperTesterMbrPort.cc +includes := . diff --git a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.cc b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.cc index 9f411ab771e3000a6391e400b9822a5a5ad0a3c5..0cf07783a85fecca4991f9b943940106e86754ab 100644 --- a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.cc +++ b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.cc @@ -11,6 +11,8 @@ #include "uppertester_cam_codec.hh" #include "uppertester_denm_codec.hh" #include "uppertester_geonetworking_codec.hh" +#include "uppertester_pki_codec.hh" +#include "uppertester_mbr_codec.hh" #include "uppertester_ivim_codec.hh" #include "uppertester_mapem_spatem_codec.hh" @@ -117,7 +119,7 @@ void ConfigRsuSimulatorLayer::sendMsg(const LibItsDenm__TypesAndValues::UtDenmRe encoding_buffer.put_c(static_cast(uppertester_denm_codec::c_utDenmTriggerResult)); const LibItsDenm__TypesAndValues::UtDenmTriggerResult &r = send_par.utDenmTriggerResult(); encoding_buffer.put_c((unsigned char)static_cast(r.result())); - OCTETSTRING os = int2oct(r.actionId().originatingStationID(), 4); + OCTETSTRING os = int2oct(r.actionId().originatingStationId(), 4); encoding_buffer.put_s(os.lengthof(), static_cast(os)); os = int2oct(r.actionId().sequenceNumber(), 2); encoding_buffer.put_s(os.lengthof(), static_cast(os)); @@ -125,7 +127,7 @@ void ConfigRsuSimulatorLayer::sendMsg(const LibItsDenm__TypesAndValues::UtDenmRe encoding_buffer.put_c(static_cast(uppertester_denm_codec::c_utDenmUpdateResult)); const LibItsDenm__TypesAndValues::UtDenmUpdateResult &r = send_par.utDenmUpdateResult(); encoding_buffer.put_c((unsigned char)static_cast(r.result())); - OCTETSTRING os = int2oct(r.actionId().originatingStationID(), 4); + OCTETSTRING os = int2oct(r.actionId().originatingStationId(), 4); encoding_buffer.put_s(os.lengthof(), static_cast(os)); os = int2oct(r.actionId().sequenceNumber(), 2); encoding_buffer.put_s(os.lengthof(), static_cast(os)); @@ -185,6 +187,36 @@ void ConfigRsuSimulatorLayer::sendMsg(const LibItsPki__TypesAndValues::UtPkiTrig send_data(os, params); } +void ConfigRsuSimulatorLayer::sendMsg(const LibItsMbr__TypesAndValues::UtMbrResults &send_par, params ¶ms) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::sendMsg: ", send_par); + + TTCN_Buffer encoding_buffer; + if (send_par.ischosen(LibItsMbr__TypesAndValues::UtMbrResults::ALT_utMbrInitializeResult)) { + encoding_buffer.put_c(static_cast(uppertester_mbr_codec::c_utMbrInitializeResult)); + encoding_buffer.put_c((unsigned char)static_cast(send_par.utMbrInitializeResult())); + } else if (send_par.ischosen(LibItsMbr__TypesAndValues::UtMbrResults::ALT_utMbrTriggerResult)) { + encoding_buffer.put_c(static_cast(uppertester_mbr_codec::c_utMbrTriggerResult)); + encoding_buffer.put_c((unsigned char)static_cast(send_par.utMbrTriggerResult())); + } else { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::sendMsg: Unsupported UtMbrResults variant"); + return; + } + + OCTETSTRING os(encoding_buffer.get_len(), encoding_buffer.get_data()); + send_data(os, params); +} + +void ConfigRsuSimulatorLayer::sendMsg(const LibItsMbr__TypesAndValues::UtMbrEventInd &send_par, params ¶ms) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::sendMsg: ", send_par); + + TTCN_Buffer encoding_buffer; + encoding_buffer.put_c(static_cast(uppertester_mbr_codec::c_utMbrEventInd)); + loggers::get_instance().error("ConfigRsuSimulatorLayer::sendMsg: UtMbrEventInd no supported yet"); + + OCTETSTRING os(encoding_buffer.get_len(), encoding_buffer.get_data()); + send_data(os, params); +} + void ConfigRsuSimulatorLayer::sendMsg(const LibItsIvim__TypesAndValues::UtIvimResults &send_par, params ¶ms) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::sendMsg: ", send_par); @@ -423,6 +455,8 @@ void ConfigRsuSimulatorLayer::receive_data(OCTETSTRING &data, params ¶ms) { } else if ((id == uppertester_pki_codec::c_utPkiTriggerEnrolmentRequest) || (id == uppertester_pki_codec::c_utPkiTriggerAuthorizationRequest)) { // Receive an UtPkiTrigger process_ut_pki_trigger(data, params); + } else if (id == uppertester_mbr_codec::c_utMbrTrigger) { // Receive an UtMbrTrigger + process_ut_mbr_trigger(data, params); } else { loggers::get_instance().warning("ConfigRsuSimulatorLayer::receive_data: Unsupported tag %02x", id); } @@ -477,6 +511,11 @@ int ConfigRsuSimulatorLayer::process_utinitialize_data(const OCTETSTRING &data, LibItsRtcmem__TypesAndValues::UtRtcmemInitialize p(hashedId); // Pass it to the ports if any to_all_upper_ports(p, params); + } else if (_params[std::string("ut")].compare("mbr") == 0) { + OCTETSTRING hashedId(data.lengthof() - 1, 1 + static_cast(data)); + LibItsMbr__TypesAndValues::UtMbrInitialize p(hashedId); + // Pass it to the ports if any + to_all_upper_ports(p, params); } else { loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_utinitialize_data: Unsupported protocol"); return -1; @@ -668,7 +707,7 @@ int ConfigRsuSimulatorLayer::process_ut_denm_update(const OCTETSTRING &data, par loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_denm_update: flag=%02x", flag); LibItsDenm__TypesAndValues::UtDenmUpdate update; // See ETSI TR 103 099 Cause C.4.1 GenerateDenmEvent // Statuion ID - update.actionId().originatingStationID() = oct2int(OCTETSTRING(4, p)); + update.actionId().originatingStationId() = oct2int(OCTETSTRING(4, p)); p += 4; // SequenceNumber update.actionId().sequenceNumber() = oct2int(OCTETSTRING(2, p)); @@ -754,7 +793,7 @@ int ConfigRsuSimulatorLayer::process_ut_denm_termination(const OCTETSTRING &data unsigned char msg_id = *p++; loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_denm_termination: msg_id=%02x", msg_id); LibItsDenm__TypesAndValues::UtDenmTermination termination; - termination.actionId().originatingStationID() = oct2int(OCTETSTRING(4, p)); + termination.actionId().originatingStationId() = oct2int(OCTETSTRING(4, p)); p += 4; termination.actionId().sequenceNumber() = oct2int(OCTETSTRING(2, p)); @@ -854,9 +893,9 @@ int ConfigRsuSimulatorLayer::process_ut_pki_trigger(const OCTETSTRING &data, par if (_params[std::string("ut")].compare("pki") == 0) { unsigned char msg_id = *static_cast(data); - loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_geonetworking_trigger: msg_id=%02x", msg_id); + loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_mbr_trigger: msg_id=%02x", msg_id); OCTETSTRING payload(data.lengthof() - 1, 1 + static_cast(data)); - loggers::get_instance().log_msg("ConfigRsuSimulatorLayer::process_ut_geonetworking_trigger: payload:", payload); + loggers::get_instance().log_msg("ConfigRsuSimulatorLayer::process_ut_mbr_trigger: payload:", payload); TTCN_EncDec::clear_error(); TTCN_Buffer decoding_buffer(payload); @@ -889,6 +928,35 @@ int ConfigRsuSimulatorLayer::process_ut_pki_trigger(const OCTETSTRING &data, par return 0; } +int ConfigRsuSimulatorLayer::process_ut_mbr_trigger(const OCTETSTRING &data, params ¶ms) { + loggers::get_instance().log(">>> ConfigRsuSimulatorLayer::process_ut_mbr_trigger"); + + params::const_iterator it = _params.find("ut"); + if (it == _params.cend()) { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_mbr_trigger: CF layer's ut parameter is missing"); + return -1; + } + + if (_params[std::string("ut")].compare("mbr") == 0) { + unsigned char msg_id = *static_cast(data); + loggers::get_instance().log("ConfigRsuSimulatorLayer::process_ut_mbr_trigger: msg_id=%02x", msg_id); + + LibItsMbr__TypesAndValues::UtMbrTrigger p; + if (msg_id == uppertester_mbr_codec::c_utMbrTrigger) { + p.targetId() = oct2int(OCTETSTRING(1, 1 + static_cast(data))); + p.cause() = oct2int(OCTETSTRING(1, 2 + static_cast(data))); + } + + // Pass it to the ports if any + to_all_upper_ports(p, params); + } else { + loggers::get_instance().warning("ConfigRsuSimulatorLayer::process_ut_mbr_trigger: Unsupported protocol"); + return -1; + } + + return 0; +} + int ConfigRsuSimulatorLayer::process_ut_mapem_spatem_trigger(const OCTETSTRING &data, params ¶ms) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorLayer::process_ut_mapem_spatem_trigger", data); diff --git a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.hh b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.hh index 7e0b7c2d63a1f276ad7e49adf9a70d8a61e61748..7750af1cc81a61808eb71349e3e3061e945061f9 100644 --- a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.hh +++ b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorLayer.hh @@ -20,6 +20,7 @@ #include "uppertester_ivim_codec.hh" #include "uppertester_mapem_spatem_codec.hh" #include "uppertester_pki_codec.hh" +#include "uppertester_mbr_codec.hh" namespace ItsRSUsSimulator__TestSystem { class ConfigRsuSimulatorPort; @@ -45,6 +46,8 @@ public: void sendMsg(const LibItsDenm__TypesAndValues::UtDenmEventInd &send_par, params ¶ms); void sendMsg(const LibItsPki__TypesAndValues::UtPkiResults &send_par, params ¶ms); void sendMsg(const LibItsPki__TypesAndValues::UtPkiTriggerInd &send_par, params ¶ms); + void sendMsg(const LibItsMbr__TypesAndValues::UtMbrResults &send_par, params ¶ms); + void sendMsg(const LibItsMbr__TypesAndValues::UtMbrEventInd &send_par, params ¶ms); void sendMsg(const LibItsIvim__TypesAndValues::UtIvimResults &send_par, params ¶ms); void sendMsg(const LibItsIvim__TypesAndValues::UtIvimEventInd &send_par, params ¶ms); void sendMsg(const LibItsMapemSpatem__TypesAndValues::UtMapemSpatemResults &send_par, params ¶ms); @@ -70,6 +73,7 @@ private: int process_ut_denm_termination(const OCTETSTRING &data, params ¶ms); int process_ut_geonetworking_trigger(const OCTETSTRING &data, params ¶ms); int process_ut_pki_trigger(const OCTETSTRING &data, params ¶ms); + int process_ut_mbr_trigger(const OCTETSTRING &data, params ¶ms); int process_ut_ivim_trigger(const OCTETSTRING &data, params ¶ms); int process_ut_ivim_update(const OCTETSTRING &data, params ¶ms); int process_ut_ivim_termination(const OCTETSTRING &data, params ¶ms); diff --git a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.cc b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.cc index 7975ba6023b00ee264d613717888ecda68751d57..bb6972a12432314dff326170b238dae52c81d127 100644 --- a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.cc +++ b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.cc @@ -153,6 +153,24 @@ namespace ItsRSUsSimulator__TestSystem { loggers::get_instance().set_stop_time(_time_key, duration); } + void ConfigRsuSimulatorPort::outgoing_send(const LibItsMbr__TypesAndValues::UtMbrResults &send_par) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::outgoing_send: payload=", send_par); + + float duration; + loggers::get_instance().set_start_time(_time_key); + static_cast(_layer)->sendMsg(send_par, _layer_params); + loggers::get_instance().set_stop_time(_time_key, duration); + } + + void ConfigRsuSimulatorPort::outgoing_send(const LibItsMbr__TypesAndValues::UtMbrEventInd &send_par) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::outgoing_send: payload=", send_par); + + float duration; + loggers::get_instance().set_start_time(_time_key); + static_cast(_layer)->sendMsg(send_par, _layer_params); + loggers::get_instance().set_stop_time(_time_key, duration); + } + void ConfigRsuSimulatorPort::outgoing_send(const LibItsIvim__TypesAndValues::UtIvimResults &send_par) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::outgoing_send: payload=", send_par); @@ -353,6 +371,26 @@ namespace ItsRSUsSimulator__TestSystem { incoming_message(p_ind); } + void ConfigRsuSimulatorPort::receiveMsg(const LibItsMbr__TypesAndValues::UtMbrInitialize &p_ind, const params &p_params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::receive_msg: ", p_ind); + // Sanity check + if (!p_ind.is_bound()) { + return; + } + + incoming_message(p_ind); + } + + void ConfigRsuSimulatorPort::receiveMsg(const LibItsMbr__TypesAndValues::UtMbrTrigger &p_ind, const params &p_params) { + loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::receive_msg: ", p_ind); + // Sanity check + if (!p_ind.is_bound()) { + return; + } + + incoming_message(p_ind); + } + void ConfigRsuSimulatorPort::receiveMsg(const LibItsIvim__TypesAndValues::UtIvimInitialize &p_ind, const params &p_params) { loggers::get_instance().log_msg(">>> ConfigRsuSimulatorPort::receive_msg: ", p_ind); // Sanity check diff --git a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.hh b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.hh index cb55ea3a989803471316c4f675aa866932a7bdbb..30801d727faa3a78cc92bc146e7f3dae4846b33d 100644 --- a/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.hh +++ b/ccsrc/Ports/LibIts_ports/RSUsSimulator_ports/ConfigRsuSimulatorPort.hh @@ -29,6 +29,8 @@ namespace ItsRSUsSimulator__TestSystem { void receiveMsg(const LibItsDenm__TypesAndValues::UtDenmTermination &p_ind, const params &p_params); void receiveMsg(const LibItsPki__TypesAndValues::UtPkiInitialize &p_ind, const params &p_params); void receiveMsg(const LibItsPki__TypesAndValues::UtPkiTrigger &p_ind, const params &p_params); + void receiveMsg(const LibItsMbr__TypesAndValues::UtMbrInitialize &p_ind, const params &p_params); + void receiveMsg(const LibItsMbr__TypesAndValues::UtMbrTrigger &p_ind, const params &p_params); void receiveMsg(const LibItsIvim__TypesAndValues::UtIvimInitialize &p_ind, const params &p_params); void receiveMsg(const LibItsIvim__TypesAndValues::UtIvimTrigger &p_ind, const params &p_params); void receiveMsg(const LibItsIvim__TypesAndValues::UtIvimUpdate &p_ind, const params &p_params); @@ -82,6 +84,8 @@ namespace ItsRSUsSimulator__TestSystem { void outgoing_send(const LibItsDenm__TypesAndValues::UtDenmEventInd &send_par); void outgoing_send(const LibItsPki__TypesAndValues::UtPkiResults &send_par); void outgoing_send(const LibItsPki__TypesAndValues::UtPkiTriggerInd &send_par); + void outgoing_send(const LibItsMbr__TypesAndValues::UtMbrResults &send_par); + void outgoing_send(const LibItsMbr__TypesAndValues::UtMbrEventInd &send_par); void outgoing_send(const LibItsIvim__TypesAndValues::UtIvimResults &send_par); void outgoing_send(const LibItsIvim__TypesAndValues::UtIvimEventInd &send_par); void outgoing_send(const LibItsMapemSpatem__TypesAndValues::UtMapemSpatemResults &send_par); diff --git a/ccsrc/Ports/LibIts_ports/UpperTesterPort.hh b/ccsrc/Ports/LibIts_ports/UpperTesterPort.hh index 96e47623e3033e4ec4ef46467cbd5a93aa49aa38..82e0da26eb35ed479775a169088fa2c2981b9c55 100644 --- a/ccsrc/Ports/LibIts_ports/UpperTesterPort.hh +++ b/ccsrc/Ports/LibIts_ports/UpperTesterPort.hh @@ -40,6 +40,14 @@ #endif #endif +#ifdef AtsMBR +#include "BTP_ports/UpperTesterPort_BTP.hh" +#include "GN_ports/UpperTesterPort_GN.hh" +#ifndef LibItsGeoNetworking__TestSystem_HH +#include "MBR_ports/UpperTesterMbrPort.hh" +#endif +#endif + #ifdef AtsIS #include "BTP_ports/UpperTesterPort_BTP.hh" #include "GN_ports/UpperTesterPort_GN.hh" @@ -101,6 +109,13 @@ #include "UpperTesterPort_GN.hh" #endif +#ifdef AtsMBR +#include "UpperTesterPort_BTP.hh" +#include "UpperTesterPort_CAM.hh" +#include "UpperTesterPort_DENM.hh" +#include "UpperTesterPort_GN.hh" +#endif + #ifdef AtsIS #include "UpperTesterPort_BTP.hh" #include "UpperTesterPort_GN.hh" diff --git a/ccsrc/Protocols/GeoNetworking/decoding_context.cc b/ccsrc/Protocols/GeoNetworking/decoding_context.cc new file mode 100644 index 0000000000000000000000000000000000000000..12cf7c7a5ae9bfa3a90a0f4439565c45a5bc8d24 --- /dev/null +++ b/ccsrc/Protocols/GeoNetworking/decoding_context.cc @@ -0,0 +1,22 @@ +#include "decoding_context.hh" + +void decoding_context::reset() { + _next_header = 0xff; + _header_type = 0xff; + _header_sub_type = 0xff; + _lifetime = 0; + _length = -1; +} + +unsigned char decoding_context::get_next_header() { return _next_header; }; +void decoding_context::set_next_header(const unsigned char p_next_header) { _next_header = p_next_header; }; +unsigned char decoding_context::get_header_type() { return _header_type; }; +void decoding_context::set_header_type(const unsigned char p_header_type) { _header_type = p_header_type; }; +unsigned char decoding_context::get_header_sub_type() { return _header_sub_type; }; +void decoding_context::set_header_sub_type(const unsigned char p_header_sub_type) { _header_sub_type = p_header_sub_type; }; +unsigned char decoding_context::get_traffic_class() { return _traffic_class; }; +void decoding_context::set_traffic_class(const unsigned char p_traffic_class) { _traffic_class = p_traffic_class; }; +unsigned int decoding_context::get_lifetime() { return _lifetime; }; +void decoding_context::set_lifetime(const unsigned int p_lifetime) { _lifetime = p_lifetime; }; +unsigned int decoding_context::get_length() { return _length; }; +void decoding_context::set_length(const unsigned int p_length) { _length = p_length; }; diff --git a/ccsrc/Protocols/GeoNetworking/decoding_context.hh b/ccsrc/Protocols/GeoNetworking/decoding_context.hh index d5c26adba7b587984d80368a0fed6f89af2e473a..93a0aed026238a7d599efa09b64557772f733729 100644 --- a/ccsrc/Protocols/GeoNetworking/decoding_context.hh +++ b/ccsrc/Protocols/GeoNetworking/decoding_context.hh @@ -13,25 +13,19 @@ class decoding_context { public: explicit decoding_context() { reset(); }; ~decoding_context(){}; - inline void reset() { - _next_header = 0xff; - _header_type = 0xff; - _header_sub_type = 0xff; - _lifetime = 0; - _length = -1; - }; + void reset(); public: - inline unsigned char get_next_header() { return _next_header; }; - inline void set_next_header(const unsigned char p_next_header) { _next_header = p_next_header; }; - inline unsigned char get_header_type() { return _header_type; }; - inline void set_header_type(const unsigned char p_header_type) { _header_type = p_header_type; }; - inline unsigned char get_header_sub_type() { return _header_sub_type; }; - inline void set_header_sub_type(const unsigned char p_header_sub_type) { _header_sub_type = p_header_sub_type; }; - inline unsigned char get_traffic_class() { return _traffic_class; }; - inline void set_traffic_class(const unsigned char p_traffic_class) { _traffic_class = p_traffic_class; }; - inline unsigned int get_lifetime() { return _lifetime; }; - inline void set_lifetime(const unsigned int p_lifetime) { _lifetime = p_lifetime; }; - inline unsigned int get_length() { return _length; }; - inline void set_length(const unsigned int p_length) { _length = p_length; }; + unsigned char get_next_header(); + void set_next_header(const unsigned char p_next_header); + unsigned char get_header_type(); + void set_header_type(const unsigned char p_header_type); + unsigned char get_header_sub_type(); + void set_header_sub_type(const unsigned char p_header_sub_type); + unsigned char get_traffic_class(); + void set_traffic_class(const unsigned char p_traffic_class); + unsigned int get_lifetime(); + void set_lifetime(const unsigned int p_lifetime); + unsigned int get_length(); + void set_length(const unsigned int p_length); }; // End of class decoding_context diff --git a/ccsrc/Protocols/GeoNetworking/encoding_context.cc b/ccsrc/Protocols/GeoNetworking/encoding_context.cc new file mode 100644 index 0000000000000000000000000000000000000000..6745ad27b1a9c3eac41c51349167d2bdc301ba66 --- /dev/null +++ b/ccsrc/Protocols/GeoNetworking/encoding_context.cc @@ -0,0 +1,21 @@ +#include "encoding_context.hh" + + +void encoding_context::reset() { + _basic_header = 0xff; + _next_header = 0xff; + _header_type = 0xff; + _length_position = -1; + _length = -1; +} + +unsigned char encoding_context::get_basic_header() { return _basic_header; }; +void encoding_context::set_basic_header(const unsigned char p_basic_header) { _basic_header = p_basic_header; }; +unsigned char encoding_context::get_next_header() { return _next_header; }; +void encoding_context::set_next_header(const unsigned char p_next_header) { _next_header = p_next_header; }; +unsigned char encoding_context::get_header_type() { return _header_type; }; +void encoding_context::set_header_type(const unsigned char p_header_type) { _header_type = p_header_type; }; +unsigned int encoding_context::get_length_position() { return _length_position; }; +void encoding_context::set_length_position(const unsigned int p_length_position) { _length_position = p_length_position; }; +unsigned int encoding_context::get_length() { return _length; }; +void encoding_context::set_length(const unsigned int p_length) { _length = p_length; }; diff --git a/ccsrc/Protocols/GeoNetworking/encoding_context.hh b/ccsrc/Protocols/GeoNetworking/encoding_context.hh index 74ace5c2b6ad217d7f2c033f01cde9af86ec8e40..0a0de32c51f067b5dd4c930654c397c6dc97c6a6 100644 --- a/ccsrc/Protocols/GeoNetworking/encoding_context.hh +++ b/ccsrc/Protocols/GeoNetworking/encoding_context.hh @@ -11,23 +11,17 @@ class encoding_context { public: explicit encoding_context() { reset(); } - inline void reset() { - _basic_header = 0xff; - _next_header = 0xff; - _header_type = 0xff; - _length_position = -1; - _length = -1; - } + void reset(); public: - inline unsigned char get_basic_header() { return _basic_header; }; - inline void set_basic_header(const unsigned char p_basic_header) { _basic_header = p_basic_header; }; - inline unsigned char get_next_header() { return _next_header; }; - inline void set_next_header(const unsigned char p_next_header) { _next_header = p_next_header; }; - inline unsigned char get_header_type() { return _header_type; }; - inline void set_header_type(const unsigned char p_header_type) { _header_type = p_header_type; }; - inline unsigned int get_length_position() { return _length_position; }; - inline void set_length_position(const unsigned int p_length_position) { _length_position = p_length_position; }; - inline unsigned int get_length() { return _length; }; - inline void set_length(const unsigned int p_length) { _length = p_length; }; + unsigned char get_basic_header(); + void set_basic_header(const unsigned char p_basic_header); + unsigned char get_next_header(); + void set_next_header(const unsigned char p_next_header); + unsigned char get_header_type(); + void set_header_type(const unsigned char p_header_type); + unsigned int get_length_position(); + void set_length_position(const unsigned int p_length_position); + unsigned int get_length(); + void set_length(const unsigned int p_length); }; // End of class encoding_context diff --git a/ccsrc/Protocols/GeoNetworking/geonetworking_codec.cc b/ccsrc/Protocols/GeoNetworking/geonetworking_codec.cc index be8b6b853c838836a79e899c8f34b944ffc1043f..408f905847b6eb3708daf71a84d85180655f9908 100644 --- a/ccsrc/Protocols/GeoNetworking/geonetworking_codec.cc +++ b/ccsrc/Protocols/GeoNetworking/geonetworking_codec.cc @@ -23,17 +23,17 @@ int geonetworking_codec::encode(const LibItsGeoNetworking__TypesAndValues::GeoNe data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()); // Overwrite the payload length if (_ec.get_length() != (unsigned int)-1) { - loggers::get_instance().log("geonetworking_codec::encode: length=%d - plLength_position = %d - plLength = %d", data.lengthof(), _ec.get_length_position(), + loggers::get_instance().log("geonetworking_codec::encode (1): length=%d - plLength_position = %d - plLength = %d", data.lengthof(), _ec.get_length_position(), _ec.get_length()); unsigned char b[] = {(unsigned char)((_ec.get_length() & 0x0000FF00) >> 8), (unsigned char)_ec.get_length()}; OCTETSTRING rpl(sizeof(b), b); loggers::get_instance().log_msg("geonetworking_codec::encode: rpl=", rpl); data = replace(data, _ec.get_length_position(), rpl.lengthof(), rpl); - loggers::get_instance().log_msg("geonetworking_codec::encode: after replace: ", data); + loggers::get_instance().log_msg("geonetworking_codec::encode (1): after replace: ", data); } - loggers::get_instance().log_msg("geonetworking_codec::encode: After encoding: ", data); + loggers::get_instance().log_msg("geonetworking_codec::encode (1): After encoding: ", data); - loggers::get_instance().log("<<< geonetworking_codec::encode"); + loggers::get_instance().log("<<< geonetworking_codec::encode (1)"); return 0; } @@ -46,17 +46,17 @@ int geonetworking_codec::encode(const LibItsGeoNetworking__TypesAndValues::GnNon data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()); // Overwrite the payload length if (_ec.get_length() != (unsigned int)-1) { - loggers::get_instance().log("geonetworking_codec::encode: length=%d - plLength_position = %d - plLength = %d", data.lengthof(), _ec.get_length_position(), + loggers::get_instance().log("geonetworking_codec::encode (2): length=%d - plLength_position = %d - plLength = %d", data.lengthof(), _ec.get_length_position(), _ec.get_length()); unsigned char b[] = {(unsigned char)((_ec.get_length() & 0x0000FF00) >> 8), (unsigned char)_ec.get_length()}; OCTETSTRING rpl(sizeof(b), b); - loggers::get_instance().log_msg("geonetworking_codec::encode: rpl=", rpl); + loggers::get_instance().log_msg("geonetworking_codec::encode (2): rpl=", rpl); data = replace(data, _ec.get_length_position(), rpl.lengthof(), rpl); - loggers::get_instance().log_msg("geonetworking_codec::encode: after replace: ", data); + loggers::get_instance().log_msg("geonetworking_codec::encode (2): after replace: ", data); } - loggers::get_instance().log_msg("geonetworking_codec::encode: After encoding: ", data); + loggers::get_instance().log_msg("geonetworking_codec::encode (2): After encoding: ", data); - loggers::get_instance().log("<<< geonetworking_codec::encode"); + loggers::get_instance().log("<<< geonetworking_codec::encode (2)"); return 0; } diff --git a/ccsrc/Protocols/GeoNetworking/geonetworking_layer.cc b/ccsrc/Protocols/GeoNetworking/geonetworking_layer.cc index eab4c85f71a2d14ceffde3cc68dc6d01db94074f..e8451ee9cb77caf2fc4f471070252426e00924d9 100644 --- a/ccsrc/Protocols/GeoNetworking/geonetworking_layer.cc +++ b/ccsrc/Protocols/GeoNetworking/geonetworking_layer.cc @@ -1,940 +1,949 @@ -#include -#include -#include -#include - -#include "geonetworking_types.hh" - -#include "geonetworking_layer_factory.hh" - -#include "loggers.hh" - -#include "security_services.hh" - -#include "base_time.hh" - -#include "registration.hh" - -#include "converter.hh" - -using namespace LibItsGeoNetworking__TypesAndValues; - -geonetworking_layer::geonetworking_layer(const std::string &p_type, const std::string &p_param) - : t_layer(p_type), _params(), _codec(), _beacon(nullptr), _gbc_packet(nullptr), _shb_packet(nullptr), - _tsb_packet(nullptr), _uni_packet(nullptr), _ls_reply(nullptr), _location_table(), - _pass_beacon_table(), _device_mode{false}, _secured_mode{false}, _encrypted_mode{false}, _enable_security_checks{false}, - _sendData(), _timerid{0}, _sev{0}, _its{0}, _freq_nanosecs(0), _mask{0}, _sa{0}, _sequence_number{0}, _latitude{0}, _longitude{0}, _force_certificate{false} { - loggers::get_instance().log(">>> geonetworking_layer::geonetworking_layer: %s, %s", to_string().c_str(), p_param.c_str()); - - init(p_type, p_param); -} // End of constructor - -geonetworking_layer::~geonetworking_layer() { - loggers::get_instance().log(">>> geonetworking_layer::~geonetworking_layer"); - - if (_timerid != 0) { - timer_delete(_timerid); - } - if (_beacon != nullptr) { - delete _beacon; - } - if (_gbc_packet != nullptr) { - delete _gbc_packet; - } - if (_shb_packet != nullptr) { - delete _shb_packet; - } - if (_tsb_packet != nullptr) { - delete _tsb_packet; - } - if (_uni_packet != nullptr) { - delete _uni_packet; - } - if (_ls_reply != nullptr) { - delete _ls_reply; - } -} // End of destructor - -void geonetworking_layer::init(const std::string &p_type, const std::string &p_param) { - loggers::get_instance().log(">>> geonetworking_layer::init: %s, %s", to_string().c_str(), p_param.c_str()); - - // Setup parameters - params_its::convert(_params, p_param); - // Sanity checks - params_its::const_iterator it = _params.find(params_its::latitude); - if (it != _params.cend()) { - _latitude = converter::get_instance().string_to_int(it->second); - } - it = _params.find(params_its::longitude); - if (it != _params.cend()) { - _longitude = converter::get_instance().string_to_int(it->second); - } - OCTETSTRING ll_address; - it = _params.find(params_its::ll_address); - if (it != _params.cend()) { - ll_address = str2oct(CHARSTRING(it->second.c_str())); - } - INTEGER distanceA = 1000; // 1km - it = _params.find(params_its::distanceA); - if (it != _params.cend()) { - distanceA = converter::get_instance().string_to_int(it->second); - } - INTEGER distanceB = 1000; // 1Km - it = _params.find(params_its::distanceB); - if (it != _params.cend()) { - distanceB = converter::get_instance().string_to_int(it->second); - } - INTEGER angle = 0; - it = _params.find(params_its::angle); - if (it != _params.cend()) { - angle = converter::get_instance().string_to_int(it->second); - } - INTEGER station_type = 5; // passangerCar - it = _params.find(params_its::station_type); - if (it != _params.cend()) { - station_type = converter::get_instance().string_to_int(it->second); - } - INTEGER country = 0; - it = _params.find(params_its::country); - if (it != _params.cend()) { - country = converter::get_instance().string_to_int(it->second); - } - INTEGER type_of_address = 1; // Manual - it = _params.find(params_its::type_of_address); - if (it != _params.cend()) { - type_of_address = converter::get_instance().string_to_int(it->second); - } - - it = _params.find(params_its::device_mode); - if (it != _params.cend()) { - _device_mode = (1 == converter::get_instance().string_to_int(it->second)); - } - it = _params.find(params_its::secured_mode); - if (it != _params.cend()) { - _secured_mode = (1 == converter::get_instance().string_to_int(it->second)); - } else { - _params.insert(std::pair(params_its::secured_mode, "0")); - } - it = _params.find(params_its::encrypted_mode); - if (it != _params.cend()) { - _encrypted_mode = (1 == converter::get_instance().string_to_int(it->second)); - } else { - _params.insert(std::pair(params_its::encrypted_mode, "0")); - } - it = _params.find(params_its::enable_security_checks); - if (it != _params.cend()) { - _enable_security_checks = (1 == converter::get_instance().string_to_int(it->second)); - } - - // Add broadcast address if needed - it = _params.find(params_its::its_aid); - if (it == _params.cend()) { - _params.insert(std::pair(params_its::its_aid, "141")); - } - it = _params.find(params_its::mac_bc); - if (it == _params.cend()) { - _params.insert(std::pair(params_its::its_aid, "FFFFFFFFFFFF")); - } - - // Set up default security parameters value - if (_secured_mode || _encrypted_mode) { - loggers::get_instance().log("geonetworking_layer::init: Setup secured mode"); - setup_secured_mode(); - } - - // Automatic beaconing mode - fill_beacon(ll_address, station_type, country, type_of_address); - params_its::const_iterator i = _params.find(params_its::beaconing); - if ((i != _params.cend()) && (i->second.compare("1") == 0)) { // Immediate beaconing was requested - // Prepare beaconing operation - start_beaconing(); - } - - // Fill packet templates - fill_gbc_packet(ll_address, _latitude, _longitude, distanceA, distanceB, - angle); // TODO Check if GeoBroadcastArea lat/lon are identical to lat/lon of the Test System - fill_shb_packet(ll_address); - fill_tsb_packet(ll_address); - fill_uni_packet(ll_address); - fill_ls_reply(ll_address); - - // Register this object for AdapterControlPort - loggers::get_instance().log("geonetworking_layer::init: Register %s/%p", p_type.c_str(), this); - registration::get_instance().add_item(p_type, this); - - // Add 4 leap seconds to convert to TAI (as Feb 2019) - base_time::get_instance().set_leap_delay_us(4 * 1000000); // TODO Set it as parameter -} // End of init_params - -void geonetworking_layer::sendMsg(const LibItsGeoNetworking__TypesAndValues::GeoNetworkingReq &p, params &p_params) { - loggers::get_instance().log(">>> geonetworking_layer::sendMsg"); - - params_its param(_params); - // Encode GeoNetworking PDU - OCTETSTRING data; - _codec.encode(p.msgOut(), data); - params_its::const_iterator it = param.find(params_its::its_aid); - if (it != param.cend()) { - int aid = std::stoi(param[params_its::its_aid]); - loggers::get_instance().log("geonetworking_layer::sendMsg: aid=%d/%d", aid, (int)p.its__aid()); - if (aid != (int)p.its__aid()) { - param[params_its::its_aid] = std::to_string((int)p.its__aid()); - loggers::get_instance().log("geonetworking_layer::sendMsg: New aid=%s", param[params_its::its_aid].c_str()); - } - } else{ - param.insert(std::pair(params_its::its_aid, std::to_string((int)p.its__aid()))); - } - if (_force_certificate == true) { // Force certificate instead of hashed_id in next message - _force_certificate = false; - param.insert(std::pair(params_its::force_certificate, std::string("1"))); - } - loggers::get_instance().log("geonetworking_layer::sendMsg: _params"); - _params.log(); - loggers::get_instance().log("geonetworking_layer::sendMsg: params"); - param.log(); - send_data(data, param); -} - -void geonetworking_layer::send_data(OCTETSTRING &data, params &p_params) { - loggers::get_instance().log_msg(">>> geonetworking_layer::send_data: ", data); - p_params.log(); - - params_its ¶ms = static_cast(p_params); - - if (_device_mode) { // Need to build a GN packet - params[params_its::certificate] = _params[params_its::certificate]; - params[params_its::hash] = _params[params_its::hash]; // TODO Should be removed - if (build_geonetworking_pdu(data, params) != 0) { - return; - } - } - if (_secured_mode) { // Add Security support - if (build_secured_pdu(data, params) != 0) { - return; - } - } - - // TODO To be removed - while (_sendData.try_lock() == FALSE) { - // not ready yet - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } // End of 'while' statement - send_to_all_layers(data, params); - _sendData.unlock(); - loggers::get_instance().log("<<< geonetworking_layer::send_data"); -} - -const TTCN_RAWdescriptor_t _intx_raw_ = {RAW_INTX, SG_NO, ORDER_MSB, ORDER_MSB, ORDER_LSB, ORDER_MSB, EXT_BIT_NO, ORDER_LSB, ORDER_LSB, - TOP_BIT_INHERITED, 0, 0, 0, 8, 0, NULL, -1, CharCoding::UNKNOWN}; -const TTCN_Typedescriptor_t _intx_descr_ = {"IntX", NULL, &_intx_raw_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; - -void geonetworking_layer::receive_data(OCTETSTRING &data, params &p_params) { - loggers::get_instance().log_msg(">>> geonetworking_layer::receive_data: ", data); - - params_its ¶ms = static_cast(p_params); - - // Check security mode - Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data; - LibItsGeoNetworking__TypesAndValues::BasicHeader basic_header; - decode_basic_header(data, basic_header); - if ((int)basic_header.nextHeader() == 2) { // Verify and extract the GeoNetworking Secured Packet as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) - // Clause 9.6.1 Composition of the Basic Header - unsigned int basic_header_len = 4; // FIXME How to retrive the BasicHeader length basic_header.get_descriptor()->raw->fieldlength / 8; - loggers::get_instance().log("geonetworking_layer::receive_data: basic_header_len = %d", basic_header_len); - // Verify and extract the GeoNetworking Secured Packet as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) Clause 9.4 GeoNetworking Secured Packet - OCTETSTRING unsecured_gn_payload; - OCTETSTRING secured_data = OCTETSTRING(data.lengthof() - basic_header_len, static_cast(data) + basic_header_len); - /////////////////// - // FIXME Check what to do with this! - if (*static_cast(secured_data) != 0x03) { - loggers::get_instance().warning("geonetworking_layer::receive_data: Security error, wrong protocol number, discard it anyway"); - if (_enable_security_checks) { - return; - } - return; - } else { - if (security_services::get_instance().verify_and_extract_gn_payload(secured_data, _enable_security_checks, ieee_1609dot2_data, unsecured_gn_payload, - params) != 0) { - loggers::get_instance().warning("geonetworking_layer::receive_data: Security error"); - if (_enable_security_checks) { - return; - } - } - } - // Update data - loggers::get_instance().log_msg("geonetworking_layer::receive_data: Unsecured payload: ", unsecured_gn_payload); - data = OCTETSTRING(basic_header_len, static_cast(data)) + unsecured_gn_payload; - } - - // Decode the payload - loggers::get_instance().log_msg("geonetworking_layer::receive_data: Geonetworking payload to decode: ", data); - LibItsGeoNetworking__TypesAndValues::GeoNetworkingInd ind; - _codec.decode(data, ind.msgIn(), ¶ms); - if (ind.msgIn().is_bound()) { - // Update optional securedMsg field if required - if (ieee_1609dot2_data.is_bound()) { - ind.msgIn().gnPacket().securedMsg() = OPTIONAL(ieee_1609dot2_data); - } // else, nothing to do - // Update context - const LibItsGeoNetworking__TypesAndValues::LongPosVector * sopv = nullptr; - const LibItsGeoNetworking__TypesAndValues::GnNonSecuredPacket &p = ind.msgIn().gnPacket().packet(); - const LibItsGeoNetworking__TypesAndValues::HeaderTST & htst = p.commonHeader().headerTST(); - if (p.extendedHeader().ispresent()) { // Update location table - const LibItsGeoNetworking__TypesAndValues::ExtendedHeader &ex = p.extendedHeader(); - if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) { // Receive a beacon - sopv = &ex.beaconHeader().srcPosVector(); - } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_tsbHdr)) { // Receive a topologicallyScopeBroadcast - if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_tsbHeader)) { - sopv = &ex.tsbHeader().srcPosVector(); - } else { - sopv = &ex.shbHeader().srcPosVector(); - } - } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoBroadcastHdr)) { - sopv = &ex.geoBroadcastHeader().srcPosVector(); - } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_lsHdr)) { // Receive a location service - if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_lsRequestHeader)) { // Receive a LocationService/LsRequest - sopv = &ex.lsRequestHeader().srcPosVector(); - // TODO Send LsReply if we are not in context of GN ATS in case of non GN test suite - if (_device_mode) { - // Update _ls_reply - ExtendedHeader *eh = static_cast(_ls_reply->gnPacket().packet().extendedHeader().get_opt_value()); - if (eh != nullptr) { - // Update sequence number - eh->lsReplyHeader().seqNumber() = _sequence_number++; - // Update destination - eh->lsReplyHeader().dstPosVector().gnAddr() = sopv->gnAddr(); - eh->lsReplyHeader().dstPosVector().latitude() = sopv->latitude(); - eh->lsReplyHeader().dstPosVector().longitude() = sopv->longitude(); - // Update timestamp - eh->lsReplyHeader().srcPosVector().timestamp__().set_long_long_val(base_time::get_instance().get_its_current_time_mod_ms()); - eh->lsReplyHeader().dstPosVector().timestamp__() = eh->lsReplyHeader().srcPosVector().timestamp__(); - - loggers::get_instance().log_msg("geonetworking_layer::receive_data: ", *_ls_reply); - - // send it - // Encode GeoNetworking PDU - OCTETSTRING os; - _codec.encode(*_ls_reply, os); - // Apply signature - if (_secured_mode) { - if (build_secured_pdu(data, _params) != 0) { - return; - } - } - // Send it - // TODO To be removed - while (_sendData.try_lock() == FALSE) { - // not ready yet - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } // End of 'while' statement - send_to_all_layers(os, params); - _sendData.unlock(); - } else { - loggers::get_instance().error("geonetworking_layer::send_data: Wrong cast"); - return; - } - } - } else { - sopv = &ex.lsReplyHeader().srcPosVector(); - } - } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoAnycastHdr)) { // Receive a GeoAnycast - sopv = &ex.geoAnycastHeader().srcPosVector(); - } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoUnicastHdr)) { - sopv = &ex.geoUnicastHeader().srcPosVector(); - } // else, nothing to do - loggers::get_instance().log("geonetworking_layer::receive_data: sopv is bound: %d", sopv->is_bound()); - if (sopv->is_bound()) { - const LibItsGeoNetworking__TypesAndValues::LongPosVector &lpv = *sopv; - if (_location_table.add_entry(lpv) == 1) { - // Force to send new certificate to anticipate certificate distribution process with the new ITS-S - _force_certificate = true; - } - } - } - - // By default incoming beacons are filtered by the test adapter - if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) { - loggers::get_instance().log_msg("geonetworking_layer::receive_data: Pass beaconing filtering: ", sopv->gnAddr().mid()); - if (_pass_beacon_table.empty()) { // Discard beacon - loggers::get_instance().log("geonetworking_layer::receive_data: Pass beaconing table empty, discard it"); - return; - } else { // Check beacon filter for StartPassBeaconing/Stop - if (!_pass_beacon_table.has_entry(sopv->gnAddr().mid())) { // Discard beacon - loggers::get_instance().log_msg("geonetworking_layer::receive_data: Not in pass beaconing table, discard it", *sopv); - return; - } // else, continue - } - } // else, continue - } else { - // Inavlid GeoNetworking payload, discard it - loggers::get_instance().warning("geonetworking_layer::receive_data: Failed to decode payload, discard it"); - return; - } - - // Add lower layers parameters - // 1. Destination MAC address - params_its::const_iterator it = params.find(params_its::mac_dst); - if (it != params.cend()) { - loggers::get_instance().log("geonetworking_layer::receive_data: dst=%s", it->second.c_str()); - ind.macDestinationAddress() = str2oct(CHARSTRING(it->second.c_str())); - } else { - ind.macDestinationAddress() = str2oct(CHARSTRING(_params["mac_bc"].c_str())); - } - // 2. ssp - it = params.find(params_its::ssp); - if (it != params.cend()) { - loggers::get_instance().log("geonetworking_layer::receive_data: ssp=%s", it->second.c_str()); - ind.ssp() = oct2bit(str2oct(CHARSTRING(it->second.c_str()))); - } else { - ind.ssp().set_to_omit(); - } - // 3. its_aid - it = params.find(params_its::its_aid); - if (it != params.cend()) { - loggers::get_instance().log("geonetworking_layer::receive_data: its_aid=%s", it->second.c_str()); - ind.its__aid() = std::stoi(it->second.c_str()); - } else { - ind.its__aid().set_to_omit(); - } - - // Pass the GeoNetworking raw payload to the upper layers if any - it = params.find(params_its::gn_payload); - if (it != params.cend()) { - loggers::get_instance().log("geonetworking_layer::receive_data: gn_payload=%s", it->second.c_str()); - OCTETSTRING os(str2oct(CHARSTRING(it->second.c_str()))); - receive_to_all_layers(os, params); - } else { - loggers::get_instance().warning("geonetworking_layer::receive_data: No payload to pass to upper layers"); - } - - // Pass it to the ports - to_all_upper_ports(ind, params); -} - -OCTETSTRING geonetworking_layer::trigger_ac_event(OCTETSTRING &data, params_its ¶ms) { - loggers::get_instance().log_to_hexa(">>> geonetworking_layer::trigger_ac_event: ", data); - - return int2oct(0, 2); -} // End of trigger_ac_event method - -void geonetworking_layer::start_beaconing() { - loggers::get_instance().log(">>> geonetworking_layer::start_beaconing"); - // loggers::get_instance().log_msg("geonetworking_layer::start_beaconing: _beacon=", *_beacon); - - // Establish handler for timer signal - loggers::get_instance().log("geonetworking_layer::start_beaconing: Establishing handler for signal %d\n", _signal_id); - _sa.sa_flags = SA_SIGINFO; - _sa.sa_sigaction = timer_irq_sigalrm_handler; - sigemptyset(&_sa.sa_mask); - if (sigaction(_signal_id, &_sa, nullptr) == -1) { - loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigaction failure: %d", errno); - } - // Block timer signal temporarily - loggers::get_instance().log("geonetworking_layer::start_beaconing: Blocking signal %d\n", _signal_id); - sigemptyset(&_mask); - sigaddset(&_mask, _signal_id); - if (sigprocmask(SIG_SETMASK, &_mask, nullptr) == -1) { - loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno); - } - // Create the timer - _sev.sigev_notify = SIGEV_SIGNAL; - _sev.sigev_signo = _signal_id; // Use signal alarm - _sev.sigev_value.sival_ptr = this; // The geonetworking_layer object address - if (timer_create(CLOCK_REALTIME, &_sev, &_timerid) == -1) { - loggers::get_instance().error("geonetworking_layer::start_beaconing: Timer failure: %d", errno); - } - loggers::get_instance().log("geonetworking_layer::start_beaconing: timer ID is 0x%x\n", (long)_timerid); - // Start the timer - unsigned int expiry = 1000; // Default expiry time 1000ms - params_its::const_iterator i = _params.find("expiry"); - if (i != _params.cend()) { - expiry = static_cast(std::strtoul(i->second.c_str(), nullptr, 10)); - } - _freq_nanosecs = expiry * 1000000; - _its.it_value.tv_sec = _freq_nanosecs / 1000000000; - _its.it_value.tv_nsec = _freq_nanosecs % 1000000000; - _its.it_interval.tv_sec = _its.it_value.tv_sec; - _its.it_interval.tv_nsec = _its.it_value.tv_nsec; - if (timer_settime(_timerid, 0, &_its, nullptr) == -1) { - loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno); - } - // Unlock the timer signal, so that timer notification can be delivered - loggers::get_instance().log("geonetworking_layer::start_beaconing: Unblocking signal %d\n", _signal_id); - if (sigprocmask(SIG_UNBLOCK, &_mask, nullptr) == -1) { - loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno); - } -} // End of start_beaconing method - -void geonetworking_layer::start_beaconing(const LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu &p_beacon) { - loggers::get_instance().log_msg(">>> geonetworking_layer::start_beaconing", p_beacon); - - // Initialize the beacon - if (_beacon != nullptr) { - delete _beacon; - } - _beacon = new LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu(p_beacon); - - start_beaconing(); // TODO Refined adding a boolean return code -} // End of start_beaconing method - -void geonetworking_layer::stop_beaconing() { - loggers::get_instance().log(">>> geonetworking_layer::stop_beaconing"); - - // Block timer signal temporarily - loggers::get_instance().log("geonetworking_layer::stop_beaconing: Blocking signal %d\n", _signal_id); - sigemptyset(&_mask); - sigaddset(&_mask, _signal_id); - if (sigprocmask(SIG_SETMASK, &_mask, nullptr) == -1) { - loggers::get_instance().error("geonetworking_layer::stop_beaconing: Sigprocmask failure: %d", errno); - } - timer_delete(_timerid); - _timerid = 0; -} // End of stop_beaconing method - -void geonetworking_layer::send_beacon() { - loggers::get_instance().log(">>> geonetworking_layer::send_beacon"); - - ExtendedHeader *eh = static_cast(_beacon->gnPacket().packet().extendedHeader().get_opt_value()); - if (eh == nullptr) { - loggers::get_instance().error("geonetworking_layer::send_beacon: Wrong cast"); - } - // Update timestamp - eh->beaconHeader().srcPosVector().timestamp__().set_long_long_val((unsigned int)base_time::get_instance().get_its_current_time_mod_ms()); - // loggers::get_instance().log_msg("geonetworking_layer::send_beacon: ", *_beacon); - // Encode message using TITAN because of payload in omited - TTCN_Buffer encoding_buffer; - _beacon->encode(*(_beacon->get_descriptor()), encoding_buffer, TTCN_EncDec::CT_RAW); - OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data()); - params_its params(_params); - if (_secured_mode) { // Apply Security - if (build_secured_pdu(data, params) != 0) { - return; - } - } - // Send it - // TODO To be removed - while (_sendData.try_lock() == FALSE) { - // not ready yet - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } // End of 'while' statement - send_to_all_layers(data, params); - _sendData.unlock(); - - // loggers::get_instance().log("<<< geonetworking_layer::send_beacon"); -} // End of send_beacon method - -void geonetworking_layer::start_pass_beaconing(const LibItsGeoNetworking__TypesAndValues::BeaconHeader &p_beacon) { - loggers::get_instance().log_msg(">>> geonetworking_layer::start_pass_beaconing", p_beacon); - - const LibItsGeoNetworking__TypesAndValues::LongPosVector &lpv = p_beacon.srcPosVector(); - if (!_pass_beacon_table.has_entry(lpv.gnAddr().mid())) { - _pass_beacon_table.add_entry(lpv); - } // TODO Refined adding a boolean return code -} // End of start_pass_beaconing method - -void geonetworking_layer::stop_pass_beaconing() { - loggers::get_instance().log(">>> geonetworking_layer::stop_pass_beaconing"); - - _pass_beacon_table.reset(); -} // End of stop_pass_beaconing method - -int geonetworking_layer::enable_secured_mode(const std::string &p_certificate_id, const boolean p_enforce_security) { - loggers::get_instance().log(">>> geonetworking_layer::enable_secured_mode: '%s' - %x", p_certificate_id.c_str(), p_enforce_security); - - loggers::get_instance().log("geonetworking_layer::enable_secured_mode: _secured_mode = %x", _secured_mode); - if (!_secured_mode) { - loggers::get_instance().log("geonetworking_layer::enable_secured_mode: Setup secured mode"); - _secured_mode = true; - setup_secured_mode(); - } - _enable_security_checks = p_enforce_security; - params_its::const_iterator it = _params.find(params_its::certificate); - if (it == _params.cend()) { - _params.insert(std::pair(params_its::certificate, p_certificate_id)); - } else { - _params[params_its::certificate] = p_certificate_id; - } - - loggers::get_instance().log("geonetworking_layer::enable_secured_mode: Certificate to be used: '%s'", _params[params_its::certificate].c_str()); - - return 0; -} - -int geonetworking_layer::disable_secured_mode() { - loggers::get_instance().log(">>> geonetworking_layer::disable_secured_mode"); - _secured_mode = false; - _enable_security_checks = false; - return 0; -} - -const LongPosVector *geonetworking_layer::get_lpv(const GN__Address &p_gn_address) { - loggers::get_instance().log_msg(">>> geonetworking_layer::get_lpv", p_gn_address); - - const LongPosVector *lpv = nullptr; - if (_location_table.has_entry(p_gn_address.mid())) { - lpv = _location_table.get_entry(p_gn_address.mid()); - } - return lpv; -} // End of get_lpv - -const LibItsGeoNetworking__TypesAndValues::BasicHeader geonetworking_layer::fill_basic_header() const { - return LibItsGeoNetworking__TypesAndValues::BasicHeader(1, // GeoNetworking version - BasicNextHeader(BasicNextHeader::e__commonHeader), 0, Lifetime(4, LtBase(LtBase::e__50ms)), 1); -} - -void geonetworking_layer::fill_beacon(const OCTETSTRING &p_ll_address, const INTEGER p_station_type, const INTEGER p_country, const INTEGER type_of_address) { - _beacon = new GeoNetworkingPdu(); - HeaderTST h; - h.beaconHdr() = BeaconHeaderType(HeaderType(HeaderType::e__beacon), 0); - ExtendedHeader eh; - eh.beaconHeader() = - BeaconHeader(LongPosVector(GN__Address(TypeOfAddress((TypeOfAddress)type_of_address), StationType((StationType)p_station_type), p_country, p_ll_address), 0, - _latitude, _longitude, int2bit(0, 1), 0, 0)); - _beacon->basicHeader() = fill_basic_header(); - _beacon->gnPacket().packet() = - GnNonSecuredPacket(CommonHeader(NextHeader(NextHeader::e__any), 0, h, - TrafficClass(SCF(SCF::e__scfEnabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), int2bit(0, 8), 0, 1, 0), - OPTIONAL(eh), OPTIONAL()); - _beacon->gnPacket().packet().payload().set_to_omit(); - _beacon->gnPacket().securedMsg().set_to_omit(); - // loggers::get_instance().log_msg("geonetworking_layer::fill_beacon: beacon value: ", *_beacon); -} // End of fill_beacon method - -void geonetworking_layer::fill_gbc_packet(const OCTETSTRING &p_ll_address, const INTEGER &p_geoAreaPosLatitude, const INTEGER &p_geoAreaPosLongitude, - const INTEGER &p_distanceA, const INTEGER &p_distanceB, const INTEGER &p_angle) { - _gbc_packet = new GeoNetworkingPdu(); - HeaderTST h; - h.geoBroadcastHdr() = - GeoBroadcastHeaderType(HeaderType(HeaderType::e__geoBroadcast), HeaderSubTypeGeoBroadcast(HeaderSubTypeGeoBroadcast::e__geoBroadcastElip)); - ExtendedHeader eh; - eh.geoBroadcastHeader() = GeoAnycastHeader( // GeoBradcastHeader is identical as GeoAnycastHeader - 0, 0, - LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params - StationType(StationType::e__passengerCar), // TODO Use params - 33, p_ll_address), - 0, _latitude, _longitude, int2bit(1, 1), // PAI - 0, 0), - p_geoAreaPosLatitude, p_geoAreaPosLongitude, p_distanceA, p_distanceB, p_angle, 0); - _gbc_packet->basicHeader() = fill_basic_header(); - _gbc_packet->gnPacket().packet() = GnNonSecuredPacket( - CommonHeader(NextHeader(NextHeader::e__btpA), 0, h, TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), - int2bit(128, 8), // Mobile stationnary flag set - 0, 5, 0), - OPTIONAL(eh), OPTIONAL()); - _gbc_packet->gnPacket().packet().payload().set_to_omit(); - _gbc_packet->gnPacket().securedMsg().set_to_omit(); - // loggers::get_instance().log_msg("geonetworking_layer::fill_gbc_packet: packet value: ", *_gbc_packet); -} // End of fill_gbc_packet method - -void geonetworking_layer::fill_shb_packet(const OCTETSTRING &p_ll_address) { - _shb_packet = new GeoNetworkingPdu(); - HeaderTST h; - h.tsbHdr() = TsbHeaderType(HeaderType(HeaderType::e__topologicallyScopedBroadcast), HeaderSubTypeTSB(HeaderSubTypeTSB::e__singleHop)); - ExtendedHeader eh; - eh.shbHeader() = SHBHeader(LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params - StationType(StationType::e__passengerCar), // TODO Use params - 33, p_ll_address), - 0, _latitude, _longitude, int2bit(1, 1), // PAI - 0, 0), - 0); - _shb_packet->basicHeader() = fill_basic_header(); - _shb_packet->gnPacket().packet() = GnNonSecuredPacket( - CommonHeader(NextHeader(NextHeader::e__btpA), 0, h, TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), - int2bit(128, 8), // Mobile stationnary flag set - 0, 1, 0), - OPTIONAL(eh), OPTIONAL()); - _shb_packet->gnPacket().packet().payload().set_to_omit(); - _shb_packet->gnPacket().securedMsg().set_to_omit(); - // loggers::get_instance().log_msg("geonetworking_layer::fill_shb_packet: packet value: ", *_shb_packet); -} // End of fill_shb_packet method - -void geonetworking_layer::fill_tsb_packet(const OCTETSTRING &p_ll_address, const int p_hop_number, const int p_max_hop_limit) { - _tsb_packet = new GeoNetworkingPdu(); - HeaderTST h; - h.tsbHdr() = TsbHeaderType(HeaderType(HeaderType::e__topologicallyScopedBroadcast), HeaderSubTypeTSB(HeaderSubTypeTSB::e__multiHop)); - ExtendedHeader eh; - eh.tsbHeader() = TSBHeader(0, 0, - LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params - StationType(StationType::e__passengerCar), // TODO Use params - 33, p_ll_address), - 0, _latitude, _longitude, int2bit(1, 1), // PAI - 0, 0)); - _tsb_packet->basicHeader() = fill_basic_header(); - _tsb_packet->gnPacket().packet() = GnNonSecuredPacket( - CommonHeader(NextHeader(NextHeader::e__btpA), 0, h, TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), - int2bit(128, 8), // Mobile stationnary flag set - 0, p_max_hop_limit, 0), - OPTIONAL(eh), OPTIONAL()); - _tsb_packet->gnPacket().packet().payload().set_to_omit(); - _tsb_packet->gnPacket().securedMsg().set_to_omit(); - // loggers::get_instance().log_msg("geonetworking_layer::fill_tsb_packet: packet value: ", *_tsb_packet); -} // End of fill_tsb_packet method - -void geonetworking_layer::fill_uni_packet(const OCTETSTRING &p_ll_address, const int p_hop_number, const int p_max_hop_limit) { - _uni_packet = new GeoNetworkingPdu(); - HeaderTST h; - h.geoUnicastHdr() = GeoUnicastHeaderType(HeaderType(HeaderType::e__geoUnicast), 0); - ExtendedHeader eh; - eh.geoUnicastHeader() = GeoUnicastHeader(0, 0, - LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params - StationType(StationType::e__passengerCar), // TODO Use params - 33, p_ll_address), - 0, _latitude, _longitude, int2bit(1, 1), // PAI - 0, 0), - ShortPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params - StationType(StationType::e__passengerCar), // TODO Use params - 33, p_ll_address), - 0, _latitude + 100, _longitude + 100)); - _uni_packet->basicHeader() = fill_basic_header(); - _uni_packet->gnPacket().packet() = GnNonSecuredPacket( - CommonHeader(NextHeader(NextHeader::e__btpA), 0, h, TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), - int2bit(128, 8), // Mobile stationnary flag set - 0, p_max_hop_limit, 0), - OPTIONAL(eh), OPTIONAL()); - _uni_packet->gnPacket().packet().payload().set_to_omit(); - _uni_packet->gnPacket().securedMsg().set_to_omit(); - // loggers::get_instance().log_msg("geonetworking_layer::fill_uni_packet: packet value: ", *_uni_packet); -} // End of fill_uni_packet method - -void geonetworking_layer::fill_ls_reply(const OCTETSTRING &p_ll_address) { - _ls_reply = new GeoNetworkingPdu(); - HeaderTST h; - h.lsHdr() = LsHeaderType(HeaderType(HeaderType::e__locationService), HeaderSubTypeLs(HeaderSubTypeLs::e__lsReply)); - ExtendedHeader eh; - eh.lsReplyHeader() = LSReplyHeader(0, 0, - LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params - StationType(StationType::e__passengerCar), // TODO Use params - 33, p_ll_address), - 0, _latitude, _longitude, int2bit(1, 1), // PAI - 0, 0), - ShortPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params - StationType(StationType::e__passengerCar), // TODO Use params - 33, p_ll_address), - 0, _latitude, _longitude)); - _ls_reply->basicHeader() = fill_basic_header(); - _ls_reply->gnPacket().packet() = GnNonSecuredPacket(CommonHeader(NextHeader(NextHeader::e__any), 0, h, - TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), - int2bit(128, 8), // Mobile stationnary flag set - 0, 5, 0), - OPTIONAL(eh), OPTIONAL()); - _ls_reply->gnPacket().packet().payload().set_to_omit(); - _ls_reply->gnPacket().securedMsg().set_to_omit(); - // loggers::get_instance().log_msg("geonetworking_layer::fill_ls_reply: packet value: ", *_ls_reply); -} // End of fill_ls_reply method - -void geonetworking_layer::timer_irq_sigalrm_handler(int p_signal, siginfo_t *p_signal_info, void *p_uc) { - // loggers::get_instance().log(">>> geonetworking_layer::timer_irq_sigalrm_handler: Caught signal %d", p_signal); - - static_cast(p_signal_info->si_value.sival_ptr)->send_beacon(); -} // End of method timer_irq_sigalrm_handler - -int geonetworking_layer::build_geonetworking_pdu(OCTETSTRING &data, params_its ¶ms) { - loggers::get_instance().log(">>> geonetworking_layer::build_geonetworking_pdu"); - // params.log(); - - std::string next_header; - params_its::const_iterator it = params.find(params_its::next_header); - if (it != params.cend()) { - next_header = it->second.c_str(); - } - std::string header_type; - it = params.find(params_its::header_type); - if (it != params.cend()) { - header_type = it->second.c_str(); - } - std::string header_sub_type; - it = params.find(params_its::header_sub_type); - if (it != params.cend()) { - header_sub_type = it->second.c_str(); - } - loggers::get_instance().log("geonetworking_layer::build_geonetworking_pdu: %s, %s, %s", next_header.c_str(), header_type.c_str(), header_sub_type.c_str()); - - if (header_type.compare("tsb") == 0) { - if (header_sub_type.compare("sh") == 0) { // Use SHB - ExtendedHeader *eh = static_cast(_shb_packet->gnPacket().packet().extendedHeader().get_opt_value()); - if (eh == nullptr) { - loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast"); - return -1; - } - // Update NextHeader - it = params.find(params_its::next_header); - if (next_header.compare("btpB") == 0) { - _shb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB; - } else { // Default btp is btpA - _shb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA; - } - // Update payload - _shb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof(); - _shb_packet->gnPacket().packet().payload() = OPTIONAL(data); - // Update timestamp - eh->shbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast(base_time::get_instance().get_its_current_time_mod_ms())); - - loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: shb: ", *_shb_packet); - // Encode GeoNetworking PDU - OCTETSTRING os; - _codec.encode(*_shb_packet, os); - data = os; - } else { // Use TSB - ExtendedHeader *eh = static_cast(_tsb_packet->gnPacket().packet().extendedHeader().get_opt_value()); - if (eh == nullptr) { - loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast"); - return -1; - } - // Update sequence number - eh->tsbHeader().seqNumber() = _sequence_number++; - // Update NextHeader - it = params.find(params_its::next_header); - if (next_header.compare("btpB") == 0) { - _tsb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB; - } else { // Default btp is btpA - _tsb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA; - } - // Update payload - _tsb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof(); - _tsb_packet->gnPacket().packet().payload() = OPTIONAL(data); - // Update timestamp - eh->tsbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast(base_time::get_instance().get_its_current_time_mod_ms())); - - loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: tsb: ", *_tsb_packet); - // Encode GeoNetworking PDU - OCTETSTRING os; - _codec.encode(*_tsb_packet, os); - data = os; - } - } else if (header_type.compare("uni") == 0) { - ExtendedHeader *eh = static_cast(_uni_packet->gnPacket().packet().extendedHeader().get_opt_value()); - if (eh == nullptr) { - loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast"); - return -1; - } - // Update NextHeader - it = params.find(params_its::next_header); - if (next_header.compare("btpB") == 0) { - _uni_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB; - } else { // Default btp is btpA - _uni_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA; - } - // Update sequence number - eh->geoUnicastHeader().seqNumber() = _sequence_number++; - // Update payload - _uni_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof(); - _uni_packet->gnPacket().packet().payload() = OPTIONAL(data); - // Update timestamp - eh->geoUnicastHeader().srcPosVector().timestamp__().set_long_long_val(static_cast(base_time::get_instance().get_its_current_time_mod_ms())); - - loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: uni: ", *_uni_packet); - - // Encode GeoNetworking PDU - OCTETSTRING os; - _codec.encode(*_uni_packet, os); - data = os; - } else { // TODO To be continued - // Default: Use GBC - ExtendedHeader *eh = static_cast(_gbc_packet->gnPacket().packet().extendedHeader().get_opt_value()); - if (eh == nullptr) { - loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast"); - return -1; - } - // Update NextHeader - it = params.find(params_its::next_header); - if (next_header.compare("btpB") == 0) { - _gbc_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB; - } else { // Default btp is btpA - _gbc_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA; - } - // Update sequence number - eh->geoBroadcastHeader().seqNumber() = _sequence_number++; - // Update payload - _gbc_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof(); - _gbc_packet->gnPacket().packet().payload() = OPTIONAL(data); - // Update timestamp - eh->geoBroadcastHeader().srcPosVector().timestamp__().set_long_long_val(static_cast(base_time::get_instance().get_its_current_time_mod_ms())); - - loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: gbc: ", *_gbc_packet); - - // Encode GeoNetworking PDU - OCTETSTRING os; - _codec.encode(*_gbc_packet, os); - data = os; - } - - return 0; -} - -int geonetworking_layer::build_secured_pdu(OCTETSTRING &data, params_its ¶ms) { - loggers::get_instance().log_msg(">>> geonetworking_layer::build_secured_pdu: ", data); - // params.log(); - - LibItsGeoNetworking__TypesAndValues::BasicHeader basic_header; - decode_basic_header(data, basic_header); - if (basic_header.nextHeader() == BasicNextHeader::e__securedPacket) { // Already secured (ATS Security test suite/f_sendSecuredGn/Cam/Denm TTCN-3 functions - // Leave data unchanged - loggers::get_instance().log_msg("<<< geonetworking_layer::build_secured_pdu: Leave data unchanged: ", data); - return 0; - } - // Update security mode - unsigned int basic_header_len = 4; // FIXME How to retrieve the BasicHeader length basic_header.get_descriptor()->raw->fieldlength / 8; - loggers::get_instance().log("geonetworking_layer::build_secured_pdu: basic_header_len = %d", basic_header_len); - basic_header.nextHeader() = BasicNextHeader::e__securedPacket; - OCTETSTRING unsecured_gn_payload = OCTETSTRING(data.lengthof() - basic_header_len, static_cast(data) + basic_header_len); - OCTETSTRING secured_gn_payload; - if (security_services::get_instance().secure_gn_payload(unsecured_gn_payload, secured_gn_payload, params) != 0) { - loggers::get_instance().warning("geonetworking_layer::build_secured_pdu: failed to build secured pdu"); - return -1; - } - - // Encode the basic header - // loggers::get_instance().log_msg("geonetworking_layer::build_secured_pdu: New basic_header = ", basic_header); - RAW_enc_tr_pos rp; - rp.level = 0; - rp.pos = NULL; - RAW_enc_tree enc_tree(FALSE, NULL, &rp, 1, basic_header.get_descriptor()->raw); - basic_header.RAW_encode(*basic_header.get_descriptor(), enc_tree); - TTCN_Buffer encoding_buffer; - enc_tree.put_to_buf(encoding_buffer); - // Copy result - data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()) + secured_gn_payload; - loggers::get_instance().log_msg("geonetworking_layer::build_secured_pdu: Secured pdu = ", data); - - return 0; -} - -int geonetworking_layer::decode_basic_header(const OCTETSTRING &p_data, LibItsGeoNetworking__TypesAndValues::BasicHeader &p_basic_header) { - // loggers::get_instance().log_msg(">>> geonetworking_layer::decode_basic_header: ", p_data); - - // Update security mode - OCTETSTRING bh = - OCTETSTRING(4, static_cast(p_data)); // Extract the basic header as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) Clause 9.6 - // loggers::get_instance().log_msg("geonetworking_layer::decode_basic_header: bh: ", bh); - TTCN_Buffer decoding_buffer(bh); - p_basic_header.RAW_decode(*p_basic_header.get_descriptor(), decoding_buffer, decoding_buffer.get_len() * 8, raw_order_t::ORDER_MSB); - // loggers::get_instance().log_msg("geonetworking_layer::decode_basic_header: ", p_basic_header); - - return 0; -} - -int geonetworking_layer::setup_secured_mode() { - loggers::get_instance().log(">>> geonetworking_layer::setup_secured_mode"); - - loggers::get_instance().log("geonetworking_layer::setup_secured_mode: GN Layer address = %p", this); - - params_its::const_iterator it = _params.find(params_its::certificate); - if (it == _params.cend()) { - _params.insert(std::pair(std::string("certificate"), "CERT_TS_A_AT")); - } - it = _params.find(params_its::sec_db_path); - if (it == _params.cend()) { - _params.insert(std::pair(std::string("sec_db_path"), "")); - } - it = _params.find(params_its::hash); - if (it == _params.cend()) { - _params.insert(std::pair(std::string("hash"), "SHA-256")); - } - // Set up security services even if secured_mode is set to 0. Later, we can receive an AcEnableSecurity request, the sertificate caching will be ready to go - security_services::get_instance().setup(_params); - security_services::get_instance().set_position(_latitude, _longitude); - - return 0; -} - -geonetworking_layer_factory geonetworking_layer_factory::_f; +#include +#include +#include +#include + +#include "geonetworking_types.hh" + +#include "geonetworking_layer_factory.hh" + +#include "loggers.hh" + +#include "security_services_its.hh" + +#include "base_time.hh" + +#include "registration.hh" + +#include "converter.hh" + +using namespace LibItsGeoNetworking__TypesAndValues; + +geonetworking_layer::geonetworking_layer(const std::string &p_type, const std::string &p_param) + : t_layer(p_type), _params(), _codec(), _beacon(nullptr), _gbc_packet(nullptr), _shb_packet(nullptr), + _tsb_packet(nullptr), _uni_packet(nullptr), _ls_reply(nullptr), _location_table(), + _pass_beacon_table(), _device_mode{false}, _secured_mode{false}, _encrypted_mode{false}, _enable_security_checks{false}, + _sendData(), _timerid{0}, _sev{0}, _its{0}, _freq_nanosecs(0), _mask{0}, _sa{0}, _sequence_number{0}, _latitude{0}, _longitude{0}, _force_certificate{false}, + _leap_delay_us(4000/*Add 4 leap seconds to convert to TAI (as Feb 2019)*/) { + loggers::get_instance().log(">>> geonetworking_layer::geonetworking_layer: %s, %s", to_string().c_str(), p_param.c_str()); + + init(p_type, p_param); +} // End of constructor + +geonetworking_layer::~geonetworking_layer() { + loggers::get_instance().log(">>> geonetworking_layer::~geonetworking_layer"); + + if (_timerid != 0) { + timer_delete(_timerid); + } + if (_beacon != nullptr) { + delete _beacon; + } + if (_gbc_packet != nullptr) { + delete _gbc_packet; + } + if (_shb_packet != nullptr) { + delete _shb_packet; + } + if (_tsb_packet != nullptr) { + delete _tsb_packet; + } + if (_uni_packet != nullptr) { + delete _uni_packet; + } + if (_ls_reply != nullptr) { + delete _ls_reply; + } +} // End of destructor + +void geonetworking_layer::init(const std::string &p_type, const std::string &p_param) { + loggers::get_instance().log(">>> geonetworking_layer::init: %s, %s", to_string().c_str(), p_param.c_str()); + + // Setup parameters + params_its::convert(_params, p_param); + // Sanity checks + params_its::const_iterator it = _params.find(params_its::latitude); + if (it != _params.cend()) { + _latitude = converter::get_instance().string_to_int(it->second); + } + it = _params.find(params_its::longitude); + if (it != _params.cend()) { + _longitude = converter::get_instance().string_to_int(it->second); + } + OCTETSTRING ll_address; + it = _params.find(params_its::ll_address); + if (it != _params.cend()) { + ll_address = str2oct(CHARSTRING(it->second.c_str())); + } + INTEGER distanceA = 1000; // 1km + it = _params.find(params_its::distanceA); + if (it != _params.cend()) { + distanceA = converter::get_instance().string_to_int(it->second); + } + INTEGER distanceB = 1000; // 1Km + it = _params.find(params_its::distanceB); + if (it != _params.cend()) { + distanceB = converter::get_instance().string_to_int(it->second); + } + INTEGER angle = 0; + it = _params.find(params_its::angle); + if (it != _params.cend()) { + angle = converter::get_instance().string_to_int(it->second); + } + INTEGER station_type = 5; // passangerCar + it = _params.find(params_its::station_type); + if (it != _params.cend()) { + station_type = converter::get_instance().string_to_int(it->second); + } + INTEGER country = 0; + it = _params.find(params_its::country); + if (it != _params.cend()) { + country = converter::get_instance().string_to_int(it->second); + } + INTEGER type_of_address = 1; // Manual + it = _params.find(params_its::type_of_address); + if (it != _params.cend()) { + type_of_address = converter::get_instance().string_to_int(it->second); + } + + it = _params.find(params_its::device_mode); + if (it != _params.cend()) { + _device_mode = (1 == converter::get_instance().string_to_int(it->second)); + } + it = _params.find(params_its::secured_mode); + if (it != _params.cend()) { + _secured_mode = (1 == converter::get_instance().string_to_int(it->second)); + } else { + _params.insert(std::pair(params_its::secured_mode, "0")); + } + it = _params.find(params_its::encrypted_mode); + if (it != _params.cend()) { + _encrypted_mode = (1 == converter::get_instance().string_to_int(it->second)); + } else { + _params.insert(std::pair(params_its::encrypted_mode, "0")); + } + it = _params.find(params_its::enable_security_checks); + if (it != _params.cend()) { + _enable_security_checks = (1 == converter::get_instance().string_to_int(it->second)); + } + + // Add broadcast address if needed + it = _params.find(params_its::its_aid); + if (it == _params.cend()) { + _params.insert(std::pair(params_its::its_aid, "141")); + } + it = _params.find(params_its::mac_bc); + if (it == _params.cend()) { + _params.insert(std::pair(params_its::its_aid, "FFFFFFFFFFFF")); + } + it = _params.find(params_its::leap_delay_us); + if (it != _params.cend()) { + _leap_delay_us = converter::get_instance().string_to_int(it->second); + } + + // Set up default security parameters value + if (_secured_mode || _encrypted_mode) { + loggers::get_instance().log("geonetworking_layer::init: Setup secured mode"); + setup_secured_mode(); + } + + // Automatic beaconing mode + fill_beacon(ll_address, station_type, country, type_of_address); + params_its::const_iterator i = _params.find(params_its::beaconing); + if ((i != _params.cend()) && (i->second.compare("1") == 0)) { // Immediate beaconing was requested + // Prepare beaconing operation + start_beaconing(); + } + + // Fill packet templates + fill_gbc_packet(ll_address, _latitude, _longitude, distanceA, distanceB, + angle); // TODO Check if GeoBroadcastArea lat/lon are identical to lat/lon of the Test System + fill_shb_packet(ll_address); + fill_tsb_packet(ll_address); + fill_uni_packet(ll_address); + fill_ls_reply(ll_address); + + // Register this object for AdapterControlPort + loggers::get_instance().log("geonetworking_layer::init: Register %s/%p", p_type.c_str(), this); + registration::get_instance().add_item(p_type, this); + + // Add leap seconds to convert to TAI + base_time::get_instance().set_leap_delay_us(_leap_delay_us); +} // End of init_params + +void geonetworking_layer::sendMsg(const LibItsGeoNetworking__TypesAndValues::GeoNetworkingReq &p, params &p_params) { + loggers::get_instance().log(">>> geonetworking_layer::sendMsg"); + + params_its param(_params); + // Encode GeoNetworking PDU + OCTETSTRING data; + _codec.encode(p.msgOut(), data); + params_its::const_iterator it = param.find(params_its::its_aid); + if (it != param.cend()) { + int aid = std::stoi(param[params_its::its_aid]); + loggers::get_instance().log("geonetworking_layer::sendMsg: aid=%d/%d", aid, (int)p.its__aid()); + if (aid != (int)p.its__aid()) { + param[params_its::its_aid] = std::to_string((int)p.its__aid()); + loggers::get_instance().log("geonetworking_layer::sendMsg: New aid=%s", param[params_its::its_aid].c_str()); + } + } else{ + param.insert(std::pair(params_its::its_aid, std::to_string((int)p.its__aid()))); + } + if (_force_certificate == true) { // Force certificate instead of hashed_id in next message + _force_certificate = false; + param.insert(std::pair(params_its::force_certificate, std::string("1"))); + } + loggers::get_instance().log("geonetworking_layer::sendMsg: _params"); + _params.log(); + loggers::get_instance().log("geonetworking_layer::sendMsg: params"); + param.log(); + send_data(data, param); +} + +void geonetworking_layer::send_data(OCTETSTRING &data, params &p_params) { + loggers::get_instance().log_msg(">>> geonetworking_layer::send_data: ", data); + //p_params.log(); + + params_its ¶ms = static_cast(p_params); + + if (_device_mode) { // Need to build a GN packet + params[params_its::certificate] = _params[params_its::certificate]; + params[params_its::hash] = _params[params_its::hash]; // TODO Should be removed + if (build_geonetworking_pdu(data, params) != 0) { + return; + } + } + if (_secured_mode) { // Add Security support + if (build_secured_pdu(data, params) != 0) { + return; + } + } + + // TODO To be removed + while (_sendData.try_lock() == FALSE) { + // not ready yet + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } // End of 'while' statement + send_to_all_layers(data, params); + _sendData.unlock(); + loggers::get_instance().log("<<< geonetworking_layer::send_data"); +} + +const TTCN_RAWdescriptor_t _intx_raw_ = {RAW_INTX, SG_NO, ORDER_MSB, ORDER_MSB, ORDER_LSB, ORDER_MSB, EXT_BIT_NO, ORDER_LSB, ORDER_LSB, + TOP_BIT_INHERITED, 0, 0, 0, 8, 0, NULL, -1, CharCoding::UNKNOWN}; +const TTCN_Typedescriptor_t _intx_descr_ = {"IntX", NULL, &_intx_raw_, NULL, NULL, NULL, NULL, NULL, TTCN_Typedescriptor_t::DONTCARE}; + +void geonetworking_layer::receive_data(OCTETSTRING &data, params &p_params) { + loggers::get_instance().log_msg(">>> geonetworking_layer::receive_data: ", data); + + params_its ¶ms = static_cast(p_params); + + // Check security mode + Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data; + LibItsGeoNetworking__TypesAndValues::BasicHeader basic_header; + decode_basic_header(data, basic_header); + if ((int)basic_header.nextHeader() == 2) { // Verify and extract the GeoNetworking Secured Packet as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) + // Clause 9.6.1 Composition of the Basic Header + unsigned int basic_header_len = 4; // FIXME How to retrive the BasicHeader length basic_header.get_descriptor()->raw->fieldlength / 8; + loggers::get_instance().log("geonetworking_layer::receive_data: basic_header_len = %d", basic_header_len); + // Verify and extract the GeoNetworking Secured Packet as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) Clause 9.4 GeoNetworking Secured Packet + OCTETSTRING unsecured_gn_payload; + OCTETSTRING secured_data = OCTETSTRING(data.lengthof() - basic_header_len, static_cast(data) + basic_header_len); + /////////////////// + // FIXME Check what to do with this! + if (*static_cast(secured_data) != 0x03) { + loggers::get_instance().warning("geonetworking_layer::receive_data: Security error, wrong protocol number, discard it anyway"); + if (_enable_security_checks) { + return; + } + return; + } else { + if (security_services_its::get_instance().verify_and_extract_gn_payload(secured_data, _enable_security_checks, ieee_1609dot2_data, unsecured_gn_payload, + params) != 0) { + loggers::get_instance().warning("geonetworking_layer::receive_data: Security error"); + if (_enable_security_checks) { + return; + } + } + } + // Update data + loggers::get_instance().log_msg("geonetworking_layer::receive_data: Unsecured payload: ", unsecured_gn_payload); + data = OCTETSTRING(basic_header_len, static_cast(data)) + unsecured_gn_payload; + } + + // Decode the payload + loggers::get_instance().log_msg("geonetworking_layer::receive_data: Geonetworking payload to decode: ", data); + LibItsGeoNetworking__TypesAndValues::GeoNetworkingInd ind; + _codec.decode(data, ind.msgIn(), ¶ms); + if (ind.msgIn().is_bound()) { + // Update optional securedMsg field if required + if (ieee_1609dot2_data.is_bound()) { + ind.msgIn().gnPacket().securedMsg() = OPTIONAL(ieee_1609dot2_data); + } // else, nothing to do + // Update context + const LibItsGeoNetworking__TypesAndValues::LongPosVector * sopv = nullptr; + const LibItsGeoNetworking__TypesAndValues::GnNonSecuredPacket &p = ind.msgIn().gnPacket().packet(); + const LibItsGeoNetworking__TypesAndValues::HeaderTST & htst = p.commonHeader().headerTST(); + if (p.extendedHeader().ispresent()) { // Update location table + const LibItsGeoNetworking__TypesAndValues::ExtendedHeader &ex = p.extendedHeader(); + if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) { // Receive a beacon + sopv = &ex.beaconHeader().srcPosVector(); + } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_tsbHdr)) { // Receive a topologicallyScopeBroadcast + if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_tsbHeader)) { + sopv = &ex.tsbHeader().srcPosVector(); + } else { + sopv = &ex.shbHeader().srcPosVector(); + } + } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoBroadcastHdr)) { + sopv = &ex.geoBroadcastHeader().srcPosVector(); + } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_lsHdr)) { // Receive a location service + if (ex.ischosen(LibItsGeoNetworking__TypesAndValues::ExtendedHeader::ALT_lsRequestHeader)) { // Receive a LocationService/LsRequest + sopv = &ex.lsRequestHeader().srcPosVector(); + // TODO Send LsReply if we are not in context of GN ATS in case of non GN test suite + if (_device_mode) { + // Update _ls_reply + ExtendedHeader *eh = static_cast(_ls_reply->gnPacket().packet().extendedHeader().get_opt_value()); + if (eh != nullptr) { + // Update sequence number + eh->lsReplyHeader().seqNumber() = _sequence_number++; + // Update destination + eh->lsReplyHeader().dstPosVector().gnAddr() = sopv->gnAddr(); + eh->lsReplyHeader().dstPosVector().latitude() = sopv->latitude(); + eh->lsReplyHeader().dstPosVector().longitude() = sopv->longitude(); + // Update timestamp + eh->lsReplyHeader().srcPosVector().timestamp__().set_long_long_val(base_time::get_instance().get_its_current_time_mod_ms()); + eh->lsReplyHeader().dstPosVector().timestamp__() = eh->lsReplyHeader().srcPosVector().timestamp__(); + + loggers::get_instance().log_msg("geonetworking_layer::receive_data: ", *_ls_reply); + + // send it + // Encode GeoNetworking PDU + OCTETSTRING os; + _codec.encode(*_ls_reply, os); + // Apply signature + if (_secured_mode) { + if (build_secured_pdu(data, _params) != 0) { + return; + } + } + // Send it + // TODO To be removed + while (_sendData.try_lock() == FALSE) { + // not ready yet + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } // End of 'while' statement + send_to_all_layers(os, params); + _sendData.unlock(); + } else { + loggers::get_instance().error("geonetworking_layer::send_data: Wrong cast"); + return; + } + } + } else { + sopv = &ex.lsReplyHeader().srcPosVector(); + } + } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoAnycastHdr)) { // Receive a GeoAnycast + sopv = &ex.geoAnycastHeader().srcPosVector(); + } else if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_geoUnicastHdr)) { + sopv = &ex.geoUnicastHeader().srcPosVector(); + } // else, nothing to do + loggers::get_instance().log("geonetworking_layer::receive_data: sopv is bound: %d", sopv->is_bound()); + if (sopv->is_bound()) { + const LibItsGeoNetworking__TypesAndValues::LongPosVector &lpv = *sopv; + if (_location_table.add_entry(lpv) == 1) { + // Force to send new certificate to anticipate certificate distribution process with the new ITS-S + _force_certificate = true; + } + } + } + + if (_device_mode == 0) { // By default incoming beacons are filtered by the test adapter + if (htst.ischosen(LibItsGeoNetworking__TypesAndValues::HeaderTST::ALT_beaconHdr)) { + loggers::get_instance().log_msg("geonetworking_layer::receive_data: Pass beaconing filtering: ", sopv->gnAddr().mid()); + if (_pass_beacon_table.empty()) { // Discard beacon + loggers::get_instance().log("geonetworking_layer::receive_data: Pass beaconing table empty, discard it"); + return; + } else { // Check beacon filter for StartPassBeaconing/Stop + if (!_pass_beacon_table.has_entry(sopv->gnAddr().mid())) { // Discard beacon + loggers::get_instance().log_msg("geonetworking_layer::receive_data: Not in pass beaconing table, discard it", *sopv); + return; + } // else, continue + } + } // else, continue + } else { // Manage Forwarding + // Checks + + } + } else { + // Inavlid GeoNetworking payload, discard it + loggers::get_instance().warning("geonetworking_layer::receive_data: Failed to decode payload, discard it"); + return; + } + + // Add lower layers parameters + // 1. Destination MAC address + params_its::const_iterator it = params.find(params_its::mac_dst); + if (it != params.cend()) { + loggers::get_instance().log("geonetworking_layer::receive_data: dst=%s", it->second.c_str()); + ind.macDestinationAddress() = str2oct(CHARSTRING(it->second.c_str())); + } else { + ind.macDestinationAddress() = str2oct(CHARSTRING(_params["mac_bc"].c_str())); + } + // 2. ssp + it = params.find(params_its::ssp); + if (it != params.cend()) { + loggers::get_instance().log("geonetworking_layer::receive_data: ssp=%s", it->second.c_str()); + ind.ssp() = oct2bit(str2oct(CHARSTRING(it->second.c_str()))); + } else { + ind.ssp().set_to_omit(); + } + // 3. its_aid + it = params.find(params_its::its_aid); + if (it != params.cend()) { + loggers::get_instance().log("geonetworking_layer::receive_data: its_aid=%s", it->second.c_str()); + ind.its__aid() = std::stoi(it->second.c_str()); + } else { + ind.its__aid().set_to_omit(); + } + + // Pass the GeoNetworking raw payload to the upper layers if any + it = params.find(params_its::gn_payload); + if (it != params.cend()) { + loggers::get_instance().log("geonetworking_layer::receive_data: gn_payload=%s", it->second.c_str()); + OCTETSTRING os(str2oct(CHARSTRING(it->second.c_str()))); + receive_to_all_layers(os, params); + } else { + loggers::get_instance().warning("geonetworking_layer::receive_data: No payload to pass to upper layers"); + } + + // Pass it to the ports + to_all_upper_ports(ind, params); +} + +OCTETSTRING geonetworking_layer::trigger_ac_event(OCTETSTRING &data, params_its ¶ms) { + loggers::get_instance().log_to_hexa(">>> geonetworking_layer::trigger_ac_event: ", data); + + return int2oct(0, 2); +} // End of trigger_ac_event method + +void geonetworking_layer::start_beaconing() { + loggers::get_instance().log(">>> geonetworking_layer::start_beaconing"); + // loggers::get_instance().log_msg("geonetworking_layer::start_beaconing: _beacon=", *_beacon); + + // Establish handler for timer signal + loggers::get_instance().log("geonetworking_layer::start_beaconing: Establishing handler for signal %d\n", _signal_id); + _sa.sa_flags = SA_SIGINFO; + _sa.sa_sigaction = timer_irq_sigalrm_handler; + sigemptyset(&_sa.sa_mask); + if (sigaction(_signal_id, &_sa, nullptr) == -1) { + loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigaction failure: %d", errno); + } + // Block timer signal temporarily + loggers::get_instance().log("geonetworking_layer::start_beaconing: Blocking signal %d\n", _signal_id); + sigemptyset(&_mask); + sigaddset(&_mask, _signal_id); + if (sigprocmask(SIG_SETMASK, &_mask, nullptr) == -1) { + loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno); + } + // Create the timer + _sev.sigev_notify = SIGEV_SIGNAL; + _sev.sigev_signo = _signal_id; // Use signal alarm + _sev.sigev_value.sival_ptr = this; // The geonetworking_layer object address + if (timer_create(CLOCK_REALTIME, &_sev, &_timerid) == -1) { + loggers::get_instance().error("geonetworking_layer::start_beaconing: Timer failure: %d", errno); + } + loggers::get_instance().log("geonetworking_layer::start_beaconing: timer ID is 0x%x\n", (long)_timerid); + // Start the timer + unsigned int expiry = 1000; // Default expiry time 1000ms + params_its::const_iterator i = _params.find("expiry"); + if (i != _params.cend()) { + expiry = static_cast(std::strtoul(i->second.c_str(), nullptr, 10)); + } + _freq_nanosecs = expiry * 1000000; + _its.it_value.tv_sec = _freq_nanosecs / 1000000000; + _its.it_value.tv_nsec = _freq_nanosecs % 1000000000; + _its.it_interval.tv_sec = _its.it_value.tv_sec; + _its.it_interval.tv_nsec = _its.it_value.tv_nsec; + if (timer_settime(_timerid, 0, &_its, nullptr) == -1) { + loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno); + } + // Unlock the timer signal, so that timer notification can be delivered + loggers::get_instance().log("geonetworking_layer::start_beaconing: Unblocking signal %d\n", _signal_id); + if (sigprocmask(SIG_UNBLOCK, &_mask, nullptr) == -1) { + loggers::get_instance().error("geonetworking_layer::start_beaconing: Sigprocmask failure: %d", errno); + } +} // End of start_beaconing method + +void geonetworking_layer::start_beaconing(const LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu &p_beacon) { + loggers::get_instance().log_msg(">>> geonetworking_layer::start_beaconing", p_beacon); + + // Initialize the beacon + if (_beacon != nullptr) { + delete _beacon; + } + _beacon = new LibItsGeoNetworking__TypesAndValues::GeoNetworkingPdu(p_beacon); + + start_beaconing(); // TODO Refined adding a boolean return code +} // End of start_beaconing method + +void geonetworking_layer::stop_beaconing() { + loggers::get_instance().log(">>> geonetworking_layer::stop_beaconing"); + + // Block timer signal temporarily + loggers::get_instance().log("geonetworking_layer::stop_beaconing: Blocking signal %d\n", _signal_id); + sigemptyset(&_mask); + sigaddset(&_mask, _signal_id); + if (sigprocmask(SIG_SETMASK, &_mask, nullptr) == -1) { + loggers::get_instance().error("geonetworking_layer::stop_beaconing: Sigprocmask failure: %d", errno); + } + timer_delete(_timerid); + _timerid = 0; +} // End of stop_beaconing method + +void geonetworking_layer::send_beacon() { + loggers::get_instance().log(">>> geonetworking_layer::send_beacon"); + + ExtendedHeader *eh = static_cast(_beacon->gnPacket().packet().extendedHeader().get_opt_value()); + if (eh == nullptr) { + loggers::get_instance().error("geonetworking_layer::send_beacon: Wrong cast"); + } + // Update timestamp + eh->beaconHeader().srcPosVector().timestamp__().set_long_long_val((unsigned int)base_time::get_instance().get_its_current_time_mod_ms()); + // loggers::get_instance().log_msg("geonetworking_layer::send_beacon: ", *_beacon); + // Encode message using TITAN because of payload in omited + TTCN_Buffer encoding_buffer; + _beacon->encode(*(_beacon->get_descriptor()), encoding_buffer, TTCN_EncDec::CT_RAW); + OCTETSTRING data(encoding_buffer.get_len(), encoding_buffer.get_data()); + params_its params(_params); + if (_secured_mode) { // Apply Security + if (build_secured_pdu(data, params) != 0) { + return; + } + } + // Send it + // TODO To be removed + while (_sendData.try_lock() == FALSE) { + // not ready yet + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } // End of 'while' statement + send_to_all_layers(data, params); + _sendData.unlock(); + + // loggers::get_instance().log("<<< geonetworking_layer::send_beacon"); +} // End of send_beacon method + +void geonetworking_layer::start_pass_beaconing(const LibItsGeoNetworking__TypesAndValues::BeaconHeader &p_beacon) { + loggers::get_instance().log_msg(">>> geonetworking_layer::start_pass_beaconing", p_beacon); + + const LibItsGeoNetworking__TypesAndValues::LongPosVector &lpv = p_beacon.srcPosVector(); + if (!_pass_beacon_table.has_entry(lpv.gnAddr().mid())) { + _pass_beacon_table.add_entry(lpv); + } // TODO Refined adding a boolean return code +} // End of start_pass_beaconing method + +void geonetworking_layer::stop_pass_beaconing() { + loggers::get_instance().log(">>> geonetworking_layer::stop_pass_beaconing"); + + _pass_beacon_table.reset(); +} // End of stop_pass_beaconing method + +int geonetworking_layer::enable_secured_mode(const std::string &p_certificate_id, const boolean p_enforce_security) { + loggers::get_instance().log(">>> geonetworking_layer::enable_secured_mode: '%s' - %x", p_certificate_id.c_str(), p_enforce_security); + + loggers::get_instance().log("geonetworking_layer::enable_secured_mode: _secured_mode = %x", _secured_mode); + if (!_secured_mode) { + loggers::get_instance().log("geonetworking_layer::enable_secured_mode: Setup secured mode"); + _secured_mode = true; + setup_secured_mode(); + } + _enable_security_checks = p_enforce_security; + params_its::const_iterator it = _params.find(params_its::certificate); + if (it == _params.cend()) { + _params.insert(std::pair(params_its::certificate, p_certificate_id)); + } else { + _params[params_its::certificate] = p_certificate_id; + } + + loggers::get_instance().log("geonetworking_layer::enable_secured_mode: Certificate to be used: '%s'", _params[params_its::certificate].c_str()); + + return 0; +} + +int geonetworking_layer::disable_secured_mode() { + loggers::get_instance().log(">>> geonetworking_layer::disable_secured_mode"); + _secured_mode = false; + _enable_security_checks = false; + return 0; +} + +const LongPosVector *geonetworking_layer::get_lpv(const GN__Address &p_gn_address) { + loggers::get_instance().log_msg(">>> geonetworking_layer::get_lpv", p_gn_address); + + const LongPosVector *lpv = nullptr; + if (_location_table.has_entry(p_gn_address.mid())) { + lpv = _location_table.get_entry(p_gn_address.mid()); + } + return lpv; +} // End of get_lpv + +const LibItsGeoNetworking__TypesAndValues::BasicHeader geonetworking_layer::fill_basic_header() const { + return LibItsGeoNetworking__TypesAndValues::BasicHeader(1, // GeoNetworking version + BasicNextHeader(BasicNextHeader::e__commonHeader), 0, Lifetime(4, LtBase(LtBase::e__50ms)), 1); +} + +void geonetworking_layer::fill_beacon(const OCTETSTRING &p_ll_address, const INTEGER p_station_type, const INTEGER p_country, const INTEGER type_of_address) { + _beacon = new GeoNetworkingPdu(); + HeaderTST h; + h.beaconHdr() = BeaconHeaderType(HeaderType(HeaderType::e__beacon), 0); + ExtendedHeader eh; + eh.beaconHeader() = + BeaconHeader(LongPosVector(GN__Address(TypeOfAddress((TypeOfAddress)type_of_address), StationType((StationType)p_station_type), p_country, p_ll_address), 0, + _latitude, _longitude, int2bit(0, 1), 0, 0)); + _beacon->basicHeader() = fill_basic_header(); + _beacon->gnPacket().packet() = + GnNonSecuredPacket(CommonHeader(NextHeader(NextHeader::e__any), 0, h, + TrafficClass(SCF(SCF::e__scfEnabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), int2bit(0, 8), 0, 1, 0), + OPTIONAL(eh), OPTIONAL()); + _beacon->gnPacket().packet().payload().set_to_omit(); + _beacon->gnPacket().securedMsg().set_to_omit(); + // loggers::get_instance().log_msg("geonetworking_layer::fill_beacon: beacon value: ", *_beacon); +} // End of fill_beacon method + +void geonetworking_layer::fill_gbc_packet(const OCTETSTRING &p_ll_address, const INTEGER &p_geoAreaPosLatitude, const INTEGER &p_geoAreaPosLongitude, + const INTEGER &p_distanceA, const INTEGER &p_distanceB, const INTEGER &p_angle) { + _gbc_packet = new GeoNetworkingPdu(); + HeaderTST h; + h.geoBroadcastHdr() = + GeoBroadcastHeaderType(HeaderType(HeaderType::e__geoBroadcast), HeaderSubTypeGeoBroadcast(HeaderSubTypeGeoBroadcast::e__geoBroadcastElip)); + ExtendedHeader eh; + eh.geoBroadcastHeader() = GeoAnycastHeader( // GeoBradcastHeader is identical as GeoAnycastHeader + 0, 0, + LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params + StationType(StationType::e__passengerCar), // TODO Use params + 33, p_ll_address), + 0, _latitude, _longitude, int2bit(1, 1), // PAI + 0, 0), + p_geoAreaPosLatitude, p_geoAreaPosLongitude, p_distanceA, p_distanceB, p_angle, 0); + _gbc_packet->basicHeader() = fill_basic_header(); + _gbc_packet->gnPacket().packet() = GnNonSecuredPacket( + CommonHeader(NextHeader(NextHeader::e__btpA), 0, h, TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), + int2bit(128, 8), // Mobile stationnary flag set + 0, 5, 0), + OPTIONAL(eh), OPTIONAL()); + _gbc_packet->gnPacket().packet().payload().set_to_omit(); + _gbc_packet->gnPacket().securedMsg().set_to_omit(); + // loggers::get_instance().log_msg("geonetworking_layer::fill_gbc_packet: packet value: ", *_gbc_packet); +} // End of fill_gbc_packet method + +void geonetworking_layer::fill_shb_packet(const OCTETSTRING &p_ll_address) { + _shb_packet = new GeoNetworkingPdu(); + HeaderTST h; + h.tsbHdr() = TsbHeaderType(HeaderType(HeaderType::e__topologicallyScopedBroadcast), HeaderSubTypeTSB(HeaderSubTypeTSB::e__singleHop)); + ExtendedHeader eh; + eh.shbHeader() = SHBHeader(LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params + StationType(StationType::e__passengerCar), // TODO Use params + 33, p_ll_address), + 0, _latitude, _longitude, int2bit(1, 1), // PAI + 0, 0), + 0); + _shb_packet->basicHeader() = fill_basic_header(); + _shb_packet->gnPacket().packet() = GnNonSecuredPacket( + CommonHeader(NextHeader(NextHeader::e__btpA), 0, h, TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), + int2bit(128, 8), // Mobile stationnary flag set + 0, 1, 0), + OPTIONAL(eh), OPTIONAL()); + _shb_packet->gnPacket().packet().payload().set_to_omit(); + _shb_packet->gnPacket().securedMsg().set_to_omit(); + // loggers::get_instance().log_msg("geonetworking_layer::fill_shb_packet: packet value: ", *_shb_packet); +} // End of fill_shb_packet method + +void geonetworking_layer::fill_tsb_packet(const OCTETSTRING &p_ll_address, const int p_hop_number, const int p_max_hop_limit) { + _tsb_packet = new GeoNetworkingPdu(); + HeaderTST h; + h.tsbHdr() = TsbHeaderType(HeaderType(HeaderType::e__topologicallyScopedBroadcast), HeaderSubTypeTSB(HeaderSubTypeTSB::e__multiHop)); + ExtendedHeader eh; + eh.tsbHeader() = TSBHeader(0, 0, + LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params + StationType(StationType::e__passengerCar), // TODO Use params + 33, p_ll_address), + 0, _latitude, _longitude, int2bit(1, 1), // PAI + 0, 0)); + _tsb_packet->basicHeader() = fill_basic_header(); + _tsb_packet->gnPacket().packet() = GnNonSecuredPacket( + CommonHeader(NextHeader(NextHeader::e__btpA), 0, h, TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), + int2bit(128, 8), // Mobile stationnary flag set + 0, p_max_hop_limit, 0), + OPTIONAL(eh), OPTIONAL()); + _tsb_packet->gnPacket().packet().payload().set_to_omit(); + _tsb_packet->gnPacket().securedMsg().set_to_omit(); + // loggers::get_instance().log_msg("geonetworking_layer::fill_tsb_packet: packet value: ", *_tsb_packet); +} // End of fill_tsb_packet method + +void geonetworking_layer::fill_uni_packet(const OCTETSTRING &p_ll_address, const int p_hop_number, const int p_max_hop_limit) { + _uni_packet = new GeoNetworkingPdu(); + HeaderTST h; + h.geoUnicastHdr() = GeoUnicastHeaderType(HeaderType(HeaderType::e__geoUnicast), 0); + ExtendedHeader eh; + eh.geoUnicastHeader() = GeoUnicastHeader(0, 0, + LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params + StationType(StationType::e__passengerCar), // TODO Use params + 33, p_ll_address), + 0, _latitude, _longitude, int2bit(1, 1), // PAI + 0, 0), + ShortPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params + StationType(StationType::e__passengerCar), // TODO Use params + 33, p_ll_address), + 0, _latitude + 100, _longitude + 100)); + _uni_packet->basicHeader() = fill_basic_header(); + _uni_packet->gnPacket().packet() = GnNonSecuredPacket( + CommonHeader(NextHeader(NextHeader::e__btpA), 0, h, TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), + int2bit(128, 8), // Mobile stationnary flag set + 0, p_max_hop_limit, 0), + OPTIONAL(eh), OPTIONAL()); + _uni_packet->gnPacket().packet().payload().set_to_omit(); + _uni_packet->gnPacket().securedMsg().set_to_omit(); + // loggers::get_instance().log_msg("geonetworking_layer::fill_uni_packet: packet value: ", *_uni_packet); +} // End of fill_uni_packet method + +void geonetworking_layer::fill_ls_reply(const OCTETSTRING &p_ll_address) { + _ls_reply = new GeoNetworkingPdu(); + HeaderTST h; + h.lsHdr() = LsHeaderType(HeaderType(HeaderType::e__locationService), HeaderSubTypeLs(HeaderSubTypeLs::e__lsReply)); + ExtendedHeader eh; + eh.lsReplyHeader() = LSReplyHeader(0, 0, + LongPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params + StationType(StationType::e__passengerCar), // TODO Use params + 33, p_ll_address), + 0, _latitude, _longitude, int2bit(1, 1), // PAI + 0, 0), + ShortPosVector(GN__Address(TypeOfAddress(TypeOfAddress::e__manual), // TODO Use params + StationType(StationType::e__passengerCar), // TODO Use params + 33, p_ll_address), + 0, _latitude, _longitude)); + _ls_reply->basicHeader() = fill_basic_header(); + _ls_reply->gnPacket().packet() = GnNonSecuredPacket(CommonHeader(NextHeader(NextHeader::e__any), 0, h, + TrafficClass(SCF(SCF::e__scfDisabled), ChannelOffload(ChannelOffload::e__choffDisabled), 0), + int2bit(128, 8), // Mobile stationnary flag set + 0, 5, 0), + OPTIONAL(eh), OPTIONAL()); + _ls_reply->gnPacket().packet().payload().set_to_omit(); + _ls_reply->gnPacket().securedMsg().set_to_omit(); + // loggers::get_instance().log_msg("geonetworking_layer::fill_ls_reply: packet value: ", *_ls_reply); +} // End of fill_ls_reply method + +void geonetworking_layer::timer_irq_sigalrm_handler(int p_signal, siginfo_t *p_signal_info, void *p_uc) { + // loggers::get_instance().log(">>> geonetworking_layer::timer_irq_sigalrm_handler: Caught signal %d", p_signal); + + static_cast(p_signal_info->si_value.sival_ptr)->send_beacon(); +} // End of method timer_irq_sigalrm_handler + +int geonetworking_layer::build_geonetworking_pdu(OCTETSTRING &data, params_its ¶ms) { + loggers::get_instance().log(">>> geonetworking_layer::build_geonetworking_pdu"); + // params.log(); + + std::string next_header; + params_its::const_iterator it = params.find(params_its::next_header); + if (it != params.cend()) { + next_header = it->second.c_str(); + } + std::string header_type; + it = params.find(params_its::header_type); + if (it != params.cend()) { + header_type = it->second.c_str(); + } + std::string header_sub_type; + it = params.find(params_its::header_sub_type); + if (it != params.cend()) { + header_sub_type = it->second.c_str(); + } + loggers::get_instance().log("geonetworking_layer::build_geonetworking_pdu: %s, %s, %s", next_header.c_str(), header_type.c_str(), header_sub_type.c_str()); + + if (header_type.compare("tsb") == 0) { + if (header_sub_type.compare("sh") == 0) { // Use SHB + ExtendedHeader *eh = static_cast(_shb_packet->gnPacket().packet().extendedHeader().get_opt_value()); + if (eh == nullptr) { + loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast"); + return -1; + } + // Update NextHeader + it = params.find(params_its::next_header); + if (next_header.compare("btpB") == 0) { + _shb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB; + } else { // Default btp is btpA + _shb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA; + } + // Update payload + _shb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof(); + _shb_packet->gnPacket().packet().payload() = OPTIONAL(data); + // Update timestamp + eh->shbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast(base_time::get_instance().get_its_current_time_mod_ms())); + + loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: shb: ", *_shb_packet); + // Encode GeoNetworking PDU + OCTETSTRING os; + _codec.encode(*_shb_packet, os); + data = os; + } else { // Use TSB + ExtendedHeader *eh = static_cast(_tsb_packet->gnPacket().packet().extendedHeader().get_opt_value()); + if (eh == nullptr) { + loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast"); + return -1; + } + // Update sequence number + eh->tsbHeader().seqNumber() = _sequence_number++; + // Update NextHeader + it = params.find(params_its::next_header); + if (next_header.compare("btpB") == 0) { + _tsb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB; + } else { // Default btp is btpA + _tsb_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA; + } + // Update payload + _tsb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof(); + _tsb_packet->gnPacket().packet().payload() = OPTIONAL(data); + // Update timestamp + eh->tsbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast(base_time::get_instance().get_its_current_time_mod_ms())); + + loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: tsb: ", *_tsb_packet); + // Encode GeoNetworking PDU + OCTETSTRING os; + _codec.encode(*_tsb_packet, os); + data = os; + } + } else if (header_type.compare("uni") == 0) { + ExtendedHeader *eh = static_cast(_uni_packet->gnPacket().packet().extendedHeader().get_opt_value()); + if (eh == nullptr) { + loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast"); + return -1; + } + // Update NextHeader + it = params.find(params_its::next_header); + if (next_header.compare("btpB") == 0) { + _uni_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB; + } else { // Default btp is btpA + _uni_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA; + } + // Update sequence number + eh->geoUnicastHeader().seqNumber() = _sequence_number++; + // Update payload + _uni_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof(); + _uni_packet->gnPacket().packet().payload() = OPTIONAL(data); + // Update timestamp + eh->geoUnicastHeader().srcPosVector().timestamp__().set_long_long_val(static_cast(base_time::get_instance().get_its_current_time_mod_ms())); + + loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: uni: ", *_uni_packet); + + // Encode GeoNetworking PDU + OCTETSTRING os; + _codec.encode(*_uni_packet, os); + data = os; + } else { // TODO To be continued + // Default: Use GBC + ExtendedHeader *eh = static_cast(_gbc_packet->gnPacket().packet().extendedHeader().get_opt_value()); + if (eh == nullptr) { + loggers::get_instance().error("geonetworking_layer::build_geonetworking_pdu: Wrong cast"); + return -1; + } + // Update NextHeader + it = params.find(params_its::next_header); + if (next_header.compare("btpB") == 0) { + _gbc_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpB; + } else { // Default btp is btpA + _gbc_packet->gnPacket().packet().commonHeader().nextHeader() = NextHeader::e__btpA; + } + // Update sequence number + eh->geoBroadcastHeader().seqNumber() = _sequence_number++; + // Update payload + _gbc_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof(); + _gbc_packet->gnPacket().packet().payload() = OPTIONAL(data); + // Update timestamp + eh->geoBroadcastHeader().srcPosVector().timestamp__().set_long_long_val(static_cast(base_time::get_instance().get_its_current_time_mod_ms())); + + loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: gbc: ", *_gbc_packet); + + // Encode GeoNetworking PDU + OCTETSTRING os; + _codec.encode(*_gbc_packet, os); + data = os; + } + + return 0; +} + +int geonetworking_layer::build_secured_pdu(OCTETSTRING &data, params_its ¶ms) { + loggers::get_instance().log_msg(">>> geonetworking_layer::build_secured_pdu: ", data); + // params.log(); + + LibItsGeoNetworking__TypesAndValues::BasicHeader basic_header; + decode_basic_header(data, basic_header); + if (basic_header.nextHeader() == BasicNextHeader::e__securedPacket) { // Already secured (ATS Security test suite/f_sendSecuredGn/Cam/Denm TTCN-3 functions + // Leave data unchanged + loggers::get_instance().log_msg("<<< geonetworking_layer::build_secured_pdu: Leave data unchanged: ", data); + return 0; + } + // Update security mode + unsigned int basic_header_len = 4; // FIXME How to retrieve the BasicHeader length basic_header.get_descriptor()->raw->fieldlength / 8; + loggers::get_instance().log("geonetworking_layer::build_secured_pdu: basic_header_len = %d", basic_header_len); + basic_header.nextHeader() = BasicNextHeader::e__securedPacket; + OCTETSTRING unsecured_gn_payload = OCTETSTRING(data.lengthof() - basic_header_len, static_cast(data) + basic_header_len); + OCTETSTRING secured_gn_payload; + if (security_services_its::get_instance().secure_gn_payload(unsecured_gn_payload, secured_gn_payload, params) != 0) { + loggers::get_instance().warning("geonetworking_layer::build_secured_pdu: failed to build secured pdu"); + return -1; + } + + // Encode the basic header + // loggers::get_instance().log_msg("geonetworking_layer::build_secured_pdu: New basic_header = ", basic_header); + RAW_enc_tr_pos rp; + rp.level = 0; + rp.pos = NULL; + RAW_enc_tree enc_tree(FALSE, NULL, &rp, 1, basic_header.get_descriptor()->raw); + basic_header.RAW_encode(*basic_header.get_descriptor(), enc_tree); + TTCN_Buffer encoding_buffer; + enc_tree.put_to_buf(encoding_buffer); + // Copy result + data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()) + secured_gn_payload; + loggers::get_instance().log_msg("geonetworking_layer::build_secured_pdu: Secured pdu = ", data); + + return 0; +} + +int geonetworking_layer::decode_basic_header(const OCTETSTRING &p_data, LibItsGeoNetworking__TypesAndValues::BasicHeader &p_basic_header) { + // loggers::get_instance().log_msg(">>> geonetworking_layer::decode_basic_header: ", p_data); + + // Update security mode + OCTETSTRING bh = + OCTETSTRING(4, static_cast(p_data)); // Extract the basic header as specified in ETSI EN 302 636-4-1 V1.3.1 (2017-08) Clause 9.6 + // loggers::get_instance().log_msg("geonetworking_layer::decode_basic_header: bh: ", bh); + TTCN_Buffer decoding_buffer(bh); + p_basic_header.RAW_decode(*p_basic_header.get_descriptor(), decoding_buffer, decoding_buffer.get_len() * 8, raw_order_t::ORDER_MSB); + // loggers::get_instance().log_msg("geonetworking_layer::decode_basic_header: ", p_basic_header); + + return 0; +} + +int geonetworking_layer::setup_secured_mode() { + loggers::get_instance().log(">>> geonetworking_layer::setup_secured_mode"); + + loggers::get_instance().log("geonetworking_layer::setup_secured_mode: GN Layer address = %p", this); + + params_its::const_iterator it = _params.find(params_its::certificate); + if (it == _params.cend()) { + _params.insert(std::pair(std::string("certificate"), "CERT_TS_A_AT")); + } + it = _params.find(params_its::sec_db_path); + if (it == _params.cend()) { + _params.insert(std::pair(std::string("sec_db_path"), "")); + } + it = _params.find(params_its::hash); + if (it == _params.cend()) { + _params.insert(std::pair(std::string("hash"), "SHA-256")); + } + // Set up security services even if secured_mode is set to 0. Later, we can receive an AcEnableSecurity request, the sertificate caching will be ready to go + security_services_its::get_instance().setup(_params); + security_services_its::get_instance().set_position(_latitude, _longitude); + + return 0; +} + +geonetworking_layer_factory geonetworking_layer_factory::_f; diff --git a/ccsrc/Protocols/GeoNetworking/geonetworking_layer.hh b/ccsrc/Protocols/GeoNetworking/geonetworking_layer.hh index b9f195da85ee125bc9f153a92f6cbee7a2311f33..88569400404dc4265be7c53468e630a9e8b09390 100644 --- a/ccsrc/Protocols/GeoNetworking/geonetworking_layer.hh +++ b/ccsrc/Protocols/GeoNetworking/geonetworking_layer.hh @@ -72,6 +72,7 @@ class geonetworking_layer : public t_layer>> http_codec_its::decode_body_binary"); std::map>>::const_iterator it; diff --git a/ccsrc/Protocols/Http/http_codec_its.hh b/ccsrc/Protocols/Http/http_codec_its.hh index e9cb631fc0576dd7a36b10476142b4e833f879c2..931d17c79ffa8132dec2edde5caa0bc8e61f1c92 100644 --- a/ccsrc/Protocols/Http/http_codec_its.hh +++ b/ccsrc/Protocols/Http/http_codec_its.hh @@ -12,5 +12,5 @@ public: protected: //! \protectedsection bool encode_body_binary(const LibHttp__BinaryMessageBodyTypes::BinaryBody &p_binary_body, OCTETSTRING &p_encoding_buffer, const std::string &p_content_type); - bool decode_body_binary(const OCTETSTRING &p_data, LibHttp__BinaryMessageBodyTypes::BinaryBody &p_binary_body, const std::string &p_content_type, params* p_params); + bool decode_body_binary(const OCTETSTRING &p_data, LibHttp__BinaryMessageBodyTypes::BinaryBody &p_binary_body, const std::string &p_content_type); }; \ No newline at end of file diff --git a/ccsrc/Protocols/Mbr/etsi_ts103759_data_codec.cc b/ccsrc/Protocols/Mbr/etsi_ts103759_data_codec.cc new file mode 100644 index 0000000000000000000000000000000000000000..51c8c8f4783f86fdd572390e9ec4e66e658076f0 --- /dev/null +++ b/ccsrc/Protocols/Mbr/etsi_ts103759_data_codec.cc @@ -0,0 +1,27 @@ +#include "etsi_ts103759_data_codec.hh" + +#include "loggers.hh" + +int etsi_ts103759_data_codec::encode(const EtsiTs103759Core::EtsiTs103759Data &p_etsi_ts_103759_data, OCTETSTRING &p_data) { + loggers::get_instance().log(">>> etsi_ts103759_data_codec::encode: %s", p_etsi_ts_103759_data.get_descriptor()->name); + + TTCN_EncDec::clear_error(); + TTCN_Buffer buffer; + p_etsi_ts_103759_data.encode(*p_etsi_ts_103759_data.get_descriptor(), buffer, TTCN_EncDec::CT_OER); + p_data = OCTETSTRING(buffer.get_len(), buffer.get_data()); + loggers::get_instance().log_msg("etsi_ts103759_data_codec::encode: ", p_data); + + return 0; +} + +int etsi_ts103759_data_codec::decode(const OCTETSTRING &p_data, EtsiTs103759Core::EtsiTs103759Data &p_etsi_ts_103759_data, params *p_params) { + loggers::get_instance().log_msg(">>> etsi_ts103759_data_codec::decode: ", p_data); + + TTCN_EncDec::clear_error(); + TTCN_Buffer decoding_buffer(p_data); + // _params = params; + p_etsi_ts_103759_data.decode(*p_etsi_ts_103759_data.get_descriptor(), decoding_buffer, TTCN_EncDec::CT_OER); + + loggers::get_instance().log_msg("<<< etsi_ts103759_data_codec::decode: ", (const Base_Type &)p_etsi_ts_103759_data); + return 0; +} diff --git a/ccsrc/Protocols/Mbr/etsi_ts103759_data_codec.hh b/ccsrc/Protocols/Mbr/etsi_ts103759_data_codec.hh new file mode 100644 index 0000000000000000000000000000000000000000..25ef1412513eb48329a61971c525e7ef88517834 --- /dev/null +++ b/ccsrc/Protocols/Mbr/etsi_ts103759_data_codec.hh @@ -0,0 +1,15 @@ +#pragma once + +#include "codec_gen.hh" +#include "params.hh" + +#include "EtsiTs103759Core.hh" + +class etsi_ts103759_data_codec : public codec_gen { +public: + explicit etsi_ts103759_data_codec() : codec_gen(){}; + virtual ~etsi_ts103759_data_codec(){}; + + virtual int encode(const EtsiTs103759Core::EtsiTs103759Data &p_etsi_ts_10291_data, OCTETSTRING &p_data); + virtual int decode(const OCTETSTRING &p_data, EtsiTs103759Core::EtsiTs103759Data &p_etsi_ts_10291_data, params *p_params = NULL); +}; // End of class etsi_ts103759_data_codec diff --git a/ccsrc/Protocols/Mbr/module.mk b/ccsrc/Protocols/Mbr/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..2af1ece02928abbf340f8d36c06641801adfac14 --- /dev/null +++ b/ccsrc/Protocols/Mbr/module.mk @@ -0,0 +1,2 @@ +sources := etsi_ts103759_data_codec.cc +includes := . diff --git a/ccsrc/Protocols/Pki/etsi_ts102941_trust_lists_ctl_format.cc b/ccsrc/Protocols/Pki/etsi_ts102941_trust_lists_ctl_format.cc index f0c880445e9062c029e3c4f12a50c99a1e0a5bdb..49a7bb6f00f1da974eaad446501d18cd410cb749 100644 --- a/ccsrc/Protocols/Pki/etsi_ts102941_trust_lists_ctl_format.cc +++ b/ccsrc/Protocols/Pki/etsi_ts102941_trust_lists_ctl_format.cc @@ -5,7 +5,6 @@ int etsi_ts102941_trust_lists_ctl_format::encode(const EtsiTs102941TrustLists::CtlFormat &p_ctl_format, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts102941_trust_lists_ctl_format::encode: %s", p_ctl_format.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_ctl_format.encode(*p_ctl_format.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/certificates_loader.cc b/ccsrc/Protocols/Security/certificates_loader.cc index 4ee8fe3b2ae06b84a63d1c57e4b52eac9f10e4dc..2c261c58ac9c9ba026c44ebcef6305ece1de13a5 100644 --- a/ccsrc/Protocols/Security/certificates_loader.cc +++ b/ccsrc/Protocols/Security/certificates_loader.cc @@ -6,6 +6,9 @@ #include "certificates_loader.hh" #include "etsi_ts103097_certificate_codec.hh" +#include "etsi_ts103097_tobesigned_certificate_codec.hh" + +#include "security_services_its.hh" #include "sha256.hh" #include "sha384.hh" @@ -14,11 +17,31 @@ #include "loggers.hh" +bool security_cache_comp::operator()(const OCTETSTRING &p_lhs, const OCTETSTRING &p_rhs) const { + // loggers::get_instance().log_msg(">>> security_cache_comp::operator(): p_lhs= ", p_lhs); + // loggers::get_instance().log_msg(">>> security_cache_comp::operator(): p_rhs= ", p_rhs); + unsigned char *first1 = (unsigned char *)static_cast(p_lhs); + unsigned char *first2 = (unsigned char *)static_cast(p_rhs); + unsigned char *last1 = p_lhs.lengthof() + (unsigned char *)static_cast(p_lhs); + unsigned char *last2 = p_rhs.lengthof() + (unsigned char *)static_cast(p_rhs); + + while (first1 != last1) { + if ((first2 == last2) || (*first2 < *first1)) { + return false; + } else if (*first1 < *first2) { + return true; + } + ++first1; + ++first2; + } // End of 'while' statement + return (first2 != last2); +} + certificates_loader *certificates_loader::instance = nullptr; certificates_loader::certificates_loader() : _certificateExt{".oer"}, _privateKeyExt{".vkey"}, _privateEncKeyExt{".ekey"}, - _full_path(), _is_cache_initialized{false}, _directory_filter{".svn", "._.DS_Store", ".DS_Store"} { + _full_path(), _is_cache_initialized{false}, _directory_filter{".svn", "._.DS_Store", ".DS_Store"}, _hashed_id8s(), _certificates_idx() { // loggers::get_instance().log(">>> certificates_loader::certificates_loader"); } // End of ctor @@ -53,7 +76,7 @@ int certificates_loader::build_path(const std::string &p_root_directory) { return 0; } // End of method build_path -int certificates_loader::build_certificates_index(std::map &p_certificates_idx, std::map &p_hashed_id8s) { +int certificates_loader::build_certificates_index() { // FIXME FSCOM Merge build_path and build_certificates_index methods in one loggers::get_instance().log(">>> certificates_loader::build_certificates_index"); // Sanity check @@ -78,12 +101,16 @@ int certificates_loader::build_certificates_index(std::map::iterator, bool> result = p_certificates_idx.insert(std::pair(certificate, h)); - if (result.second == false) { - loggers::get_instance().warning("certificates_loader::build_certificates_index: Failed to insert new record '%s'", certificate.c_str()); + std::pair::iterator, bool> r1 = _hashed_id8s.insert(std::pair(h, certificate)); + if (r1.second == false) { + loggers::get_instance().warning("certificates_loader::build_certificates_index (1): Failed to insert new record '%s'", certificate.c_str()); + continue; + } + std::pair::iterator, bool> r2 = _certificates_idx.insert(std::pair(certificate, h)); + if (r2.second == false) { + loggers::get_instance().warning("certificates_loader::build_certificates_index (2): Failed to insert new record '%s'", certificate.c_str()); continue; } - p_hashed_id8s.insert(std::pair(h, certificate)); } // End of 'while' statement is.close(); @@ -92,9 +119,17 @@ int certificates_loader::build_certificates_index(std::map& certificates_loader::get_hashed_id8s() { + return _hashed_id8s; +} + +std::map& certificates_loader::get_certificates() { + return _certificates_idx; +} + int certificates_loader::load_certificate(const OCTETSTRING& p_hashed_id8, const std::string p_certificate_name, std::map> & p_certificates) { - loggers::get_instance().log_msg(">>> certificates_loader::load_certificate", p_hashed_id8); - loggers::get_instance().log(">>> certificates_loader::load_certificate: %s", p_certificate_name.c_str()); + loggers::get_instance().log_msg(">>> certificates_loader::load_certificate: ", p_hashed_id8); + loggers::get_instance().log(">>> certificates_loader::load_certificate: '%s'", p_certificate_name.c_str()); std::experimental::filesystem::path p = _full_path.string() + "/" + p_certificate_name + _certificateExt; const std::string& key = p.stem(); @@ -107,19 +142,20 @@ int certificates_loader::load_certificate(const OCTETSTRING& p_hashed_id8, const OCTETSTRING certificate = int2oct(0, std::experimental::filesystem::file_size(p)); is.read((char *)static_cast(certificate), certificate.lengthof()); is.close(); + loggers::get_instance().log_msg("certificates_loader::load_certificate: certificate: ", certificate); // Load private key file OCTETSTRING private_key; p = p.replace_extension(_privateKeyExt); - // loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching private keys '%s'", p.string().c_str()); + // loggers::get_instance().log("certificates_loader::load_certificate: Caching private keys '%s'", p.string().c_str()); is.open(p, ios::in | ios::binary); if (!is.is_open()) { - loggers::get_instance().warning("certificates_loader::build_certificates_cache: Failed to open Private key"); + loggers::get_instance().warning("certificates_loader::load_certificate: Failed to open Private key"); private_key = OCTETSTRING(0, nullptr); } else { int size = std::experimental::filesystem::file_size(p); if ((size != 32) && (size != 48)) { - loggers::get_instance().warning("certificates_loader::build_certificates_cache: Private key size is incorrect for '%s'", key.c_str()); + loggers::get_instance().warning("certificates_loader::load_certificate: Private key size is incorrect for '%s'", key.c_str()); return -1; } private_key = int2oct(0, size); @@ -130,15 +166,15 @@ int certificates_loader::load_certificate(const OCTETSTRING& p_hashed_id8, const // Load private encryption key file if present OCTETSTRING private_enc_key; p = p.replace_extension(_privateEncKeyExt); - // loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching private encryption key '%s'", p.string().c_str()); + // loggers::get_instance().log("certificates_loader::load_certificate: Caching private encryption key '%s'", p.string().c_str()); is.open(p, ios::in | ios::binary); if (!is.is_open()) { - loggers::get_instance().warning("certificates_loader::build_certificates_cache: Failed to open Private encryption key file"); + loggers::get_instance().warning("certificates_loader::load_certificate: Failed to open Private encryption key file"); private_enc_key = OCTETSTRING(0, nullptr); } else { int size = std::experimental::filesystem::file_size(p); - if (size != 32) { // IEEE Std 1609.2 2017: NistP256 or BrainpoolP256r1 - loggers::get_instance().warning("certificates_loader::build_certificates_cache: Private encryption key size is incorrect for '%s'", key.c_str()); + if (size != 32) { // IEEE Std 1609.2 2017: NistP256 or BrainpoolP256r1 or Sm2P256 + loggers::get_instance().warning("certificates_loader::load_certificate: Private encryption key size is incorrect for '%s'", key.c_str()); return -1; } private_enc_key = int2oct(0, size); @@ -146,42 +182,22 @@ int certificates_loader::load_certificate(const OCTETSTRING& p_hashed_id8, const is.close(); } + // Whole-certificate hash using SHA-256 + OCTETSTRING hash_sha_256; + sha256 sha; + sha.generate(certificate, hash_sha_256); + loggers::get_instance().log_msg("certificates_loader::load_certificate: Whole-certificate SHA-256 hash for encryption: ", hash_sha_256); + std::pair>::iterator, bool> result; // Build DB record etsi_ts103097_certificate_codec codec; Ieee1609Dot2::CertificateBase decoded_certificate; codec.decode(certificate, decoded_certificate); - if (!decoded_certificate.is_value()) { - loggers::get_instance().warning("certificates_loader::build_certificates_cache: Failed to decode certificate for '%s'", key.c_str()); + if (!decoded_certificate.is_bound()) { + loggers::get_instance().warning("certificates_loader::load_certificate: Failed to decode certificate for '%s'", key.c_str()); return -1; } else { - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Decoded certificate: ", decoded_certificate); - // Prepare all fields - if (!decoded_certificate.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_verificationKey)) { - loggers::get_instance().warning("certificates_loader::build_certificates_cache: Wrong VerificationKeyIndicator variant for '%s'", key.c_str()); - return -1; - } - OCTETSTRING public_key_x; - OCTETSTRING public_key_y; - OCTETSTRING public_comp_key; // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) - Ieee1609Dot2BaseTypes::PublicVerificationKey &b = decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey(); - if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP256)) { - Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecdsaNistP256(); - fill_public_key_vectors(ec_elliptic_curves::nist_p_256, p, public_comp_key, public_key_x, public_key_y); - } else if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP384)) { - Ieee1609Dot2BaseTypes::EccP384CurvePoint &p = b.ecdsaNistP384(); - fill_public_key_vectors(ec_elliptic_curves::nist_p_384, p, public_comp_key, public_key_x, public_key_y); - } else if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP256r1)) { - Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecdsaBrainpoolP256r1(); - fill_public_key_vectors(ec_elliptic_curves::brainpool_p_256_r1, p, public_comp_key, public_key_x, public_key_y); - } else { // ALT_ecdsaBrainpoolP384r1 - Ieee1609Dot2BaseTypes::EccP384CurvePoint &p = b.ecdsaBrainpoolP384r1(); - fill_public_key_vectors(ec_elliptic_curves::brainpool_p_384_r1, p, public_comp_key, public_key_x, public_key_y); - } - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: public_key_x: ", public_key_x); - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: public_key_y: ", public_key_y); - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: public_comp_key: ", public_comp_key); - + // Extract common part of the certificate OCTETSTRING public_enc_key_x; OCTETSTRING public_enc_key_y; OCTETSTRING public_enc_comp_key; @@ -191,45 +207,24 @@ int certificates_loader::load_certificate(const OCTETSTRING& p_hashed_id8, const Ieee1609Dot2BaseTypes::BasePublicEncryptionKey &b = v.publicKey(); if (b.ischosen(Ieee1609Dot2BaseTypes::BasePublicEncryptionKey::ALT_eciesNistP256)) { Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = v.publicKey().eciesNistP256(); - fill_public_key_vectors(ec_elliptic_curves::nist_p_256, p, public_enc_comp_key, public_enc_key_x, public_enc_key_y); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::nist_p_256, p, public_enc_comp_key, public_enc_key_x, public_enc_key_y); } else if (b.ischosen(Ieee1609Dot2BaseTypes::BasePublicEncryptionKey::ALT_eciesBrainpoolP256r1)) { Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = v.publicKey().eciesBrainpoolP256r1(); - fill_public_key_vectors(ec_elliptic_curves::brainpool_p_256_r1, p, public_enc_comp_key, public_enc_key_x, public_enc_key_y); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::brainpool_p_256_r1, p, public_enc_comp_key, public_enc_key_x, public_enc_key_y); + } else if (b.ischosen(Ieee1609Dot2BaseTypes::BasePublicEncryptionKey::ALT_ecencSm2)) { + Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = v.publicKey().ecencSm2(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::sm2_p_256, p, public_enc_comp_key, public_enc_key_x, public_enc_key_y); } - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: public_enc_key_x: ", public_enc_key_x); - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: public_enc_key_y: ", public_enc_key_y); - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: public_enc_comp_key: ", public_enc_comp_key); + // loggers::get_instance().log_msg("certificates_loader::load_certificate: public_enc_key_x: ", public_enc_key_x); + // loggers::get_instance().log_msg("certificates_loader::load_certificate: public_enc_key_y: ", public_enc_key_y); + // loggers::get_instance().log_msg("certificates_loader::load_certificate: public_enc_comp_key: ", public_enc_comp_key); } else { public_enc_key_x = OCTETSTRING(0, nullptr); public_enc_key_y = OCTETSTRING(0, nullptr); public_enc_comp_key = OCTETSTRING(0, nullptr); } - OCTETSTRING hash_sha_256; // Whole-certificate hash using SHA-256 - sha256 sha; - sha.generate(certificate, hash_sha_256); - loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Whole-certificate SHA-256 hash for encryption: ", hash_sha_256); - - OCTETSTRING hash; // Whole-certificate hash - OCTETSTRING hashed_id; // Whole-certificate hashedid-8 OCTETSTRING issuer; // Certificate issuer - if (public_key_x.lengthof() == 32) { // See IEEE Std 1609.2a-2017 Clause 6.4.3 CertificateBase - hash = hash_sha_256; - loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Whole-certificate SHA-256 hash: ", hash); - hashed_id = OCTETSTRING(8, static_cast(hash) + hash.lengthof() - 8); - } else if (public_key_x.lengthof() == 48) { - sha384 sha; - sha.generate(certificate, hash); - loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Whole-certificate SHA-384 hash: ", hash); - hashed_id = OCTETSTRING(8, static_cast(hash) + hash.lengthof() - 8); - } else { - hash = OCTETSTRING(0, nullptr); - hash_sha_256 = OCTETSTRING(0, nullptr); - hashed_id = int2oct(0, 8); - } - loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: hash: ", hash); - loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: hashed_id: ", hashed_id); - if (decoded_certificate.issuer().ischosen(Ieee1609Dot2::IssuerIdentifier::ALT_sha256AndDigest)) { issuer = decoded_certificate.issuer().sha256AndDigest(); } else if (decoded_certificate.issuer().ischosen(Ieee1609Dot2::IssuerIdentifier::ALT_sha384AndDigest)) { @@ -239,43 +234,207 @@ int certificates_loader::load_certificate(const OCTETSTRING& p_hashed_id8, const if (decoded_certificate.issuer().self__() == Ieee1609Dot2BaseTypes::HashAlgorithm::sha256) { sha256 sha; sha.generate(certificate, h); - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Whole-certificate SHA-256 hash: ", hash); + // loggers::get_instance().log_msg("certificates_loader::load_certificate: Whole-certificate SHA-256 hash: ", hash); } else { sha384 sha; sha.generate(certificate, h); - // loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Whole-certificate SHA-384 hash: ", hash); + // loggers::get_instance().log_msg("certificates_loader::load_certificate: Whole-certificate SHA-384 hash: ", hash); } issuer = OCTETSTRING(8, static_cast(h) + h.lengthof() - 8); } else { issuer = int2oct(0, 8); } - loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: issuer: ", issuer); - - // Create new record - security_db_record *p = new security_db_record( - key, - certificate, // Certificate - decoded_certificate, - issuer, // Hashed ID fo the issuer - hash, hash_sha_256, - hashed_id, // Hashed ID - private_key, // Private key - public_key_x, // public keys X-coordinate - public_key_y, // public keys Y-coordinate - public_comp_key, // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) - private_enc_key, // Private encryption key - public_enc_key_x, // Public encryption key X-coordinate - public_enc_key_y, // Public encryption key Y-coordinate - public_enc_comp_key // Public compressed encryption key - ); - result = p_certificates.insert(std::pair>(key, std::unique_ptr(p))); - if (result.second == false) { - loggers::get_instance().warning("certificates_loader::build_certificates_cache: Failed to insert new record '%s'", key.c_str()); - delete p; - return -1; + loggers::get_instance().log_msg("certificates_loader::load_certificate: issuer: ", issuer); + + if (decoded_certificate.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_verificationKey)) { + // loggers::get_instance().log_msg("certificates_loader::load_certificate: Decoded certificate: ", decoded_certificate); + ec_elliptic_curves algorithm; + OCTETSTRING public_key_x; + OCTETSTRING public_key_y; + OCTETSTRING public_comp_key; // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) + Ieee1609Dot2BaseTypes::PublicVerificationKey &b = decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey(); + if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP256)) { + algorithm = ec_elliptic_curves::nist_p_256; + Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecdsaNistP256(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::nist_p_256, p, public_comp_key, public_key_x, public_key_y); + } else if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP384)) { + algorithm = ec_elliptic_curves::nist_p_384; + Ieee1609Dot2BaseTypes::EccP384CurvePoint &p = b.ecdsaNistP384(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::nist_p_384, p, public_comp_key, public_key_x, public_key_y); + } else if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP256r1)) { + algorithm = ec_elliptic_curves::brainpool_p_256_r1; + Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecdsaBrainpoolP256r1(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::brainpool_p_256_r1, p, public_comp_key, public_key_x, public_key_y); + } else if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP384r1)) { + algorithm = ec_elliptic_curves::brainpool_p_384_r1; + Ieee1609Dot2BaseTypes::EccP384CurvePoint &p = b.ecdsaBrainpoolP384r1(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::brainpool_p_384_r1, p, public_comp_key, public_key_x, public_key_y); + } else { // ALT_ecsigSm2 + algorithm = ec_elliptic_curves::sm2_p_256; + Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecsigSm2(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::sm2_p_256, p, public_comp_key, public_key_x, public_key_y); + } + // loggers::get_instance().log("certificates_loader::load_certificate: algorithm: %d", algorithm); + // loggers::get_instance().log_msg("certificates_loader::load_certificate: public_key_x: ", public_key_x); + // loggers::get_instance().log_msg("certificates_loader::load_certificate: public_key_y: ", public_key_y); + // loggers::get_instance().log_msg("certificates_loader::load_certificate: public_comp_key: ", public_comp_key); + + OCTETSTRING hash; // Whole-certificate hash + OCTETSTRING hashed_id; // Whole-certificate hashedid-8 + if (public_key_x.lengthof() == 32) { // See IEEE Std 1609.2a-2017 Clause 6.4.3 CertificateBase + hash = hash_sha_256; + loggers::get_instance().log_msg("certificates_loader::load_certificate: Whole-certificate SHA-256 hash: ", hash); + hashed_id = OCTETSTRING(8, static_cast(hash) + hash.lengthof() - 8); + } else if (public_key_x.lengthof() == 48) { + sha384 sha; + sha.generate(certificate, hash); + loggers::get_instance().log_msg("certificates_loader::load_certificate: Whole-certificate SHA-384 hash: ", hash); + hashed_id = OCTETSTRING(8, static_cast(hash) + hash.lengthof() - 8); + } else { + hash = OCTETSTRING(0, nullptr); + hash_sha_256 = OCTETSTRING(0, nullptr); + hashed_id = int2oct(0, 8); + } + loggers::get_instance().log_msg("certificates_loader::load_certificate: hash: ", hash); + loggers::get_instance().log_msg("certificates_loader::load_certificate: hashed_id: ", hashed_id); + + // Create new record + security_db_record *r = new security_db_record( + algorithm, // Signing algorithm + key, // Certificate name. Index key + certificate, // Certificate + decoded_certificate, + issuer, // Hashed ID fo the issuer + hash, // Hash of the certificate + hash_sha_256, // Whole-certificate SHA256 + hashed_id, // Hashed ID + private_key, // Private key + public_key_x, // public keys X-coordinate + public_key_y, // public keys Y-coordinate + public_comp_key, // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) + private_enc_key, // Private encryption key + public_enc_key_x, // Public encryption key X-coordinate + public_enc_key_y, // Public encryption key Y-coordinate + public_enc_comp_key // Public compressed encryption key + ); + result = p_certificates.insert(std::pair>(key, std::unique_ptr(r))); + if (result.second == false) { + loggers::get_instance().warning("certificates_loader::load_certificate: Failed to insert new record '%s'", key.c_str()); + delete r; + return -1; + } + } else if (decoded_certificate.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_reconstructionValue)) { + // Load certificate issuer + std::map::const_iterator it = _hashed_id8s.find(issuer); + if (it == _hashed_id8s.cend()) { + loggers::get_instance().warning("certificates_loader::load_certificate: Cannot find issuer of implicit certificate"); + return -1; + } + std::map> m; + if (load_certificate(issuer, it->second, m) == -1) { + loggers::get_instance().warning("certificates_loader::load_certificate: Cannot load implicit certificate issuer"); + return -1; + } + // The signing algorithm is provided by the issuer certificate + if (!m.cbegin()->second->decoded_certificate().toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_verificationKey)) { + loggers::get_instance().warning("certificates_loader::load_certificate: Inconsistent certificate issuer: Wrong VerificationKeyIndicator"); + return -1; + } + loggers::get_instance().log_msg("certificates_loader::load_certificate: Implicit certificate issuer: ", m.cbegin()->second->decoded_certificate()); + // Retrieve the issuer signing key + const Ieee1609Dot2BaseTypes::PublicVerificationKey &b = m.cbegin()->second->decoded_certificate().toBeSigned().verifyKeyIndicator().verificationKey(); + ec_elliptic_curves algorithm; + OCTETSTRING issuer_sign_key_x; + OCTETSTRING issuer_sign_key_y; + OCTETSTRING issuer_sign_key_comp_key; // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) + if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP256)) { + const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecdsaNistP256(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::nist_p_256, p, issuer_sign_key_comp_key, issuer_sign_key_x, issuer_sign_key_y); + algorithm = ec_elliptic_curves::nist_p_256; + } else if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP256r1)) { + const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecdsaBrainpoolP256r1(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::brainpool_p_256_r1, p, issuer_sign_key_comp_key, issuer_sign_key_x, issuer_sign_key_y); + algorithm = ec_elliptic_curves::brainpool_p_256_r1; + } else { + loggers::get_instance().warning("certificates_loader::load_certificate: Incosistent certificate issuer: Wrong PublicVerificationKey"); + return -1; + } + // Retrieve the reconstruction key key + const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = decoded_certificate.toBeSigned().verifyKeyIndicator().reconstructionValue(); + OCTETSTRING rv_key_x; + OCTETSTRING rv_key_y; + OCTETSTRING rv_comp_key; // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) + security_services_its::fill_public_key_vectors(algorithm, p, rv_comp_key, rv_key_x, rv_key_y); + // Compute the hash od the toBeSigned + OCTETSTRING tbs; + etsi_ts103097_tobesigned_certificate_codec codec; + codec.encode(decoded_certificate.toBeSigned(), tbs); + if (!tbs.is_bound()) { + loggers::get_instance().warning("certificates_loader::load_certificate: Failed to encode toBeSigned"); + return -1; + } + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Implicit encoded toBeSigned: ", tbs); + OCTETSTRING hash_tbs; + sha256 sha; + sha.generate(tbs, hash_tbs); + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Implicit hash(toBeSignedCertificate): ", hash_tbs); + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Implicit issuer hash: ", m.cbegin()->second->hash_sha_256()); + OCTETSTRING input = hash_tbs + m.cbegin()->second->hash_sha_256(); + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: input: ", input); + sha.generate(input, hash_tbs); + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: joint hash: ", hash_tbs); + // Reconstruction of the public key. + OCTETSTRING public_key_x; // public keys X-coordinate + OCTETSTRING public_key_y; // public keys Y-coordinate + OCTETSTRING public_comp_key; // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) + INTEGER public_comp_key_mode; // public compressed key mode (02 or 03) + security_ecc r_key(algorithm, rv_key_x, rv_key_y); // Reconstruction key + if (r_key.reconstruct_public_keys(hash_tbs, static_cast(issuer_sign_key_x), static_cast(issuer_sign_key_y), public_key_x, public_key_y, public_comp_key, public_comp_key_mode) == -1) { + loggers::get_instance().warning("certificates_loader::load_certificate: Failed to encode toBeSigned"); + return -1; + } + loggers::get_instance().log_msg("certificates_loader::load_certificate: public_key_x: ", public_key_x); + loggers::get_instance().log_msg("certificates_loader::load_certificate: public_key_y: ", public_key_y); + loggers::get_instance().log_msg("certificates_loader::load_certificate: public_comp_key: ", public_comp_key); + loggers::get_instance().log_msg("certificates_loader::load_certificate: public_comp_key_mode: ", public_comp_key_mode); + + OCTETSTRING hash = hash_sha_256; // Whole-certificate hash + OCTETSTRING hashed_id; // Whole-certificate hashedid-8 + hashed_id = OCTETSTRING(8, static_cast(hash) + hash.lengthof() - 8); + loggers::get_instance().log_msg("certificates_loader::load_certificate: hash: ", hash); + loggers::get_instance().log_msg("certificates_loader::load_certificate: hashed_id: ", hashed_id); + + // Create new record + security_db_record *r = new security_db_record( + algorithm, // Signing algorithm + key, // Certificate name. Index key + certificate, // Certificate + decoded_certificate, + issuer, // Hashed ID fo the issuer + hash, // Hash of the certificate + hash_sha_256, // Whole-certificate SHA256 + hashed_id, // Hashed ID + private_key, // Private key + public_key_x, // public keys X-coordinate + public_key_y, // public keys Y-coordinate + public_comp_key, // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) + private_enc_key, // Private encryption key + public_enc_key_x, // Public encryption key X-coordinate + public_enc_key_y, // Public encryption key Y-coordinate + public_enc_comp_key // Public compressed encryption key + ); + result = p_certificates.insert(std::pair>(key, std::unique_ptr(r))); + if (result.second == false) { + loggers::get_instance().warning("certificates_loader::load_certificate: Failed to insert new record '%s'", key.c_str()); + delete r; + return -1; + } + } else { + loggers::get_instance().error("certificates_loader::build_certificates_cache: Unsupported verifyKeyIndicator variant"); } } + loggers::get_instance().log("<<< certificates_loader::build_certificates_cache: 0"); return 0; } @@ -329,54 +488,9 @@ int certificates_loader::save_certificate(const security_db_record &p_certificat std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all); } + _hashed_id8s.insert(std::pair(p_certificate.hashed_id(), p_certificate.certificate_id())); + _certificates_idx.insert(std::pair(p_certificate.certificate_id(), p_certificate.hashed_id())); + return 0; } // End of method save_certificate -void certificates_loader::fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p_ecc_point, - OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y) { - loggers::get_instance().log_msg(">>> certificates_loader::fill_public_key_vectors: ", p_ecc_point); - - if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { - p_public_comp_key = int2oct(2, 1) + p_ecc_point.compressed__y__0(); - security_ecc ecc(p_elliptic_curve, p_ecc_point.compressed__y__0(), ecc_compressed_mode::compressed_y_0); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - } else if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { - p_public_comp_key = int2oct(3, 1) + p_ecc_point.compressed__y__1(); - security_ecc ecc(p_elliptic_curve, p_ecc_point.compressed__y__1(), ecc_compressed_mode::compressed_y_1); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - } else if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { - p_public_key_x = p_ecc_point.uncompressedP256().x(); - p_public_key_y = p_ecc_point.uncompressedP256().y(); - p_public_comp_key = int2oct(0, 33); - } else { - p_public_key_x = int2oct(0, 32); - p_public_key_y = int2oct(0, 32); - p_public_comp_key = int2oct(0, 33); - } -} -void certificates_loader::fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP384CurvePoint &p_ecc_point, - OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y) { - // loggers::get_instance().log_msg(">>> certificates_loader::fill_public_key_vectors: ", p_ecc_point); - - if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { - p_public_comp_key = int2oct(2, 1) + p_ecc_point.compressed__y__0(); - security_ecc ecc(p_elliptic_curve, p_ecc_point.compressed__y__0(), ecc_compressed_mode::compressed_y_0); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - } else if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { - p_public_comp_key = int2oct(3, 1) + p_ecc_point.compressed__y__1(); - security_ecc ecc(p_elliptic_curve, p_ecc_point.compressed__y__1(), ecc_compressed_mode::compressed_y_1); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - } else if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { - p_public_key_x = p_ecc_point.uncompressedP384().x(); - p_public_key_y = p_ecc_point.uncompressedP384().y(); - p_public_comp_key = int2oct(0, 49); - } else { - p_public_key_x = int2oct(0, 48); - p_public_key_y = int2oct(0, 48); - p_public_comp_key = int2oct(0, 49); - } -} diff --git a/ccsrc/Protocols/Security/certificates_loader.hh b/ccsrc/Protocols/Security/certificates_loader.hh index 20e53641eb881852121a248a34afc9bd265bb0be..35b260309de71338306c67603b4f5fa9fc3b0fa1 100644 --- a/ccsrc/Protocols/Security/certificates_loader.hh +++ b/ccsrc/Protocols/Security/certificates_loader.hh @@ -18,7 +18,7 @@ #include -#include "security_cache.hh" +// #include "security_cache.hh" #include "security_db_record.hh" #include "security_ecc.hh" @@ -27,19 +27,26 @@ namespace Ieee1609Dot2BaseTypes { class EccP384CurvePoint; //! Declare TITAN class } // namespace Ieee1609Dot2BaseTypes +struct security_cache_comp { + bool operator()(const OCTETSTRING &p_lhs, const OCTETSTRING &p_rhs) const; +}; + /*! * \class certificates_loader * \brief This class provides mechanism to load the certificates from the filesystem according the struecture defined in ETSI TS 103 099 * \remark Singleton pattern */ class certificates_loader { - std::string _certificateExt; //! COER encoding certificate extension. Default: .oer - std::string _privateKeyExt; //! Private signing key extension. Default: .vkey - std::string _privateEncKeyExt; //! Private cyphering key extension. Default: .ekey - std::experimental::filesystem::path _full_path; //! The full folder path to load certificates - bool _is_cache_initialized; //! Set to true when certificates are successfully loaded from file system - std::set _directory_filter; //! Directory filter (for local development purposes only) - static certificates_loader * instance; //! Unique static object reference of this class + std::string _certificateExt; //! COER encoding certificate extension. Default: .oer + std::string _privateKeyExt; //! Private signing key extension. Default: .vkey + std::string _privateEncKeyExt; //! Private cyphering key extension. Default: .ekey + std::experimental::filesystem::path _full_path; //! The full folder path to load certificates + bool _is_cache_initialized; //! Set to true when certificates are successfully loaded from file system + std::set _directory_filter; //! Directory filter (for local development purposes only) + static certificates_loader * instance; //! Unique static object reference of this class + std::map _hashed_id8s; + //! List of the certificates indexed by the HashedId8 + std::map _certificates_idx; //! List of the certificates indexed by the certificate identifier /*! * \brief Default private ctor @@ -49,6 +56,8 @@ class certificates_loader { * \brief Default private dtor */ ~certificates_loader() { + _hashed_id8s.clear(); + _certificates_idx.clear(); if (instance != NULL) { delete instance; instance = NULL; @@ -73,13 +82,11 @@ public: /*! \publicsection */ */ int build_path(const std::string &p_root_directory); /*! - * \fn int build_certificates_index(std::map &p_certificates_idx, std::map &p_hashed_id8s); + * \fn int build_certificates_index(); * \brief Store in memory the index of the certitifcates as a tuple {HashedId8, Certificate Name} - * \param[in] p_certificates_idx Memory stored index, key is the certificate name - * \param[in] p_hashed_id8s Memory stored index, key is the HashedId8 * \return 0 on success, -1 otherwise */ - int build_certificates_index(std::map &p_certificates_idx, std::map &p_hashed_id8s); + int build_certificates_index(); /*! * \fn int load_certificate(const OCTETSTRING& p_hashed_id8, const std::string p_certificate_name, std::map> & p_certificates); * \brief Store in memory the specified certificate @@ -96,18 +103,18 @@ public: /*! \publicsection */ * \return 0 on success, -1 otherwise */ int save_certificate(const security_db_record &p_certificate); - -private: /*! \privatesection */ /*! - * \fn int fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p_ecc_point, OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y); - * \brief Initialize public key vectors, based on 256 bits curve + * \fn std::map& get_hashed_id8s() const; + * \brief Retrieve the index of certificates name by HashedId8 value + * \return The reference to the index */ - void fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p_ecc_point, - OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y); + std::map& get_hashed_id8s(); /*! - * \fn int fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p_ecc_point, OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y); - * \brief Initialize public key vectors, based on 384 bits curve + * \fn std::map& get_certificate() const; + * \brief Retrieve the index of HashedId8 value by certificates name + * \return The HashedId8 of the certificate */ - void fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP384CurvePoint &p_ecc_point, - OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y); + std::map& get_certificates(); + +private: /*! \privatesection */ }; // End of class certificates_loader diff --git a/ccsrc/Protocols/Security/etsi_ts102941_base_types_public_keys.cc b/ccsrc/Protocols/Security/etsi_ts102941_base_types_public_keys.cc index 4ffd84152c552ffb3220d1092f30b598baef855a..52820f6e8abf1e2419025ff2e08790f883570c0c 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_base_types_public_keys.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_base_types_public_keys.cc @@ -5,7 +5,6 @@ int etsi_ts102941_base_types_public_keys::encode(const EtsiTs102941BaseTypes::PublicKeys &p_public_keys, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts102941_base_types_public_keys::encode: %s", p_public_keys.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_public_keys.encode(*p_public_keys.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_data_codec.cc b/ccsrc/Protocols/Security/etsi_ts102941_data_codec.cc index 68e461b96b21af05cfd826ac3c1d273e2a690b93..e111fce871de5a9a3e8ce4e720dd6cfb5f371426 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_data_codec.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_data_codec.cc @@ -5,7 +5,6 @@ int etsi_ts102941_data_codec::encode(const EtsiTs102941MessagesCa::EtsiTs102941Data &p_etsi_ts_102941_data, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts102941_data_codec::encode: %s", p_etsi_ts_102941_data.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_etsi_ts_102941_data.encode(*p_etsi_ts_102941_data.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_data_content_codec.cc b/ccsrc/Protocols/Security/etsi_ts102941_data_content_codec.cc index 877c6939e0b3071c7dc15644302cfea1f566c5a5..8d3d89c5124c8eacf6b943d0e91066d8ba0f9112 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_data_content_codec.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_data_content_codec.cc @@ -5,7 +5,6 @@ int etsi_ts102941_data_content_codec::encode(const EtsiTs102941MessagesCa::EtsiTs102941DataContent &p_etsi_ts_10291_data_content, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts102941_data_content_codec::encode: %s", p_etsi_ts_10291_data_content.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_etsi_ts_10291_data_content.encode(*p_etsi_ts_10291_data_content.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_inner_request.cc b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_inner_request.cc index 5fa3aa9153e6d9e5055317abdacff370c9884252..c4d9491ef90cb87fb3274c07fc8e4f2c180eeb45 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_inner_request.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_inner_request.cc @@ -5,7 +5,6 @@ int etsi_ts102941_types_authorization_inner_request::encode(const EtsiTs102941TypesAuthorization::InnerAtRequest &p_inner_request, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts102941_types_authorization_inner_request::encode: %s", p_inner_request.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_inner_request.encode(*p_inner_request.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_inner_response.cc b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_inner_response.cc index 09fbc8657dc8d682bc3d8fe3b57296ef6384381a..fc49f043267e14cb3c63ca2d872aebce79290b12 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_inner_response.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_inner_response.cc @@ -5,7 +5,6 @@ int etsi_ts102941_types_authorization_inner_response::encode(const EtsiTs102941TypesAuthorization::InnerAtResponse &p_inner_response, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts102941_types_authorization_inner_response::encode: %s", p_inner_response.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_inner_response.encode(*p_inner_response.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_shared_at_request.cc b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_shared_at_request.cc index 1370a75ba1218a20a734105acfdad4fc02d9bc57..e8496f59e8a7be1e8af1eabe89f534da23afb8fb 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_shared_at_request.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_shared_at_request.cc @@ -6,7 +6,6 @@ int etsi_ts102941_types_authorization_shared_at_request::encode(const EtsiTs1029 OCTETSTRING & p_data) { loggers::get_instance().log(">>> etsi_ts102941_types_authorization_shared_at_request::encode: %s", p_shared_at_request.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_shared_at_request.encode(*p_shared_at_request.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_validation_request.cc b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_validation_request.cc index accd048f1d9964e12035b2ca1825ae1b1b67b29d..7653416899f32b37a74b51eaaffc90b9def70312 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_validation_request.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_validation_request.cc @@ -7,7 +7,6 @@ int etsi_ts102941_types_authorization_validation_request::encode( loggers::get_instance().log(">>> etsi_ts102941_types_authorization_validation_request::encode: %s", p_authorization_validation_request.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_authorization_validation_request.encode(*p_authorization_validation_request.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_validation_response.cc b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_validation_response.cc index 168d4d601bac48a9870b5b3fd2840e59e3f2c3c4..1253a9c203ccc30242f5af0102de1d5dedc15162 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_validation_response.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_types_authorization_validation_response.cc @@ -7,7 +7,6 @@ int etsi_ts102941_types_authorization_validation_response::encode( loggers::get_instance().log(">>> etsi_ts102941_types_authorization_validation_response::encode: %s", p_authorization_validation_response.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_authorization_validation_response.encode(*p_authorization_validation_response.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_types_enrolment_inner_request.cc b/ccsrc/Protocols/Security/etsi_ts102941_types_enrolment_inner_request.cc index a7413993c0d72ff13dcacebf57a270ff70a055b5..30b0c3286f93fa58957b14eebca79d710d9a03d8 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_types_enrolment_inner_request.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_types_enrolment_inner_request.cc @@ -5,7 +5,6 @@ int etsi_ts102941_types_enrolment_inner_request::encode(const EtsiTs102941TypesEnrolment::InnerEcRequest &p_inner_request, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts102941_types_enrolment_inner_request::encode: %s", p_inner_request.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_inner_request.encode(*p_inner_request.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts102941_types_enrolment_inner_response.cc b/ccsrc/Protocols/Security/etsi_ts102941_types_enrolment_inner_response.cc index 99a1a44f88a9a9e01be7e50d17702f55e64faf6f..589e78154b3215602131f4847ec4daee49f6c508 100644 --- a/ccsrc/Protocols/Security/etsi_ts102941_types_enrolment_inner_response.cc +++ b/ccsrc/Protocols/Security/etsi_ts102941_types_enrolment_inner_response.cc @@ -5,7 +5,6 @@ int etsi_ts102941_types_enrolment_inner_response::encode(const EtsiTs102941TypesEnrolment::InnerEcResponse &p_inner_response, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts102941_types_enrolment_inner_response::encode: %s", p_inner_response.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_inner_response.encode(*p_inner_response.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts103097_certificate_codec.cc b/ccsrc/Protocols/Security/etsi_ts103097_certificate_codec.cc index 5fc427b69a949488ac8c24ae3fc624678778837a..14c9ff0d86e17e31e0317dbf3ff57030cfd1488f 100644 --- a/ccsrc/Protocols/Security/etsi_ts103097_certificate_codec.cc +++ b/ccsrc/Protocols/Security/etsi_ts103097_certificate_codec.cc @@ -9,7 +9,6 @@ int etsi_ts103097_certificate_codec::encode(const Ieee1609Dot2::CertificateBase &p_cert, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts103097_certificate_codec::encode: %s", p_cert.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_cert.encode(*p_cert.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts103097_data_codec.cc b/ccsrc/Protocols/Security/etsi_ts103097_data_codec.cc index 18e045de33fdc84a86729e92ada62909421a5fa4..6fe07e0a828f76cc831c36cdb49b3f9395af46d3 100644 --- a/ccsrc/Protocols/Security/etsi_ts103097_data_codec.cc +++ b/ccsrc/Protocols/Security/etsi_ts103097_data_codec.cc @@ -9,7 +9,6 @@ int etsi_ts103097_data_codec::encode(const Ieee1609Dot2::Ieee1609Dot2Data &p_ieee1609Dot2Data, OCTETSTRING &p_data) { loggers::get_instance().log(">>> etsi_ts103097_data_codec::encode: %s", p_ieee1609Dot2Data.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_ieee1609Dot2Data.encode(*p_ieee1609Dot2Data.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts103097_tobesigned_certificate_codec.cc b/ccsrc/Protocols/Security/etsi_ts103097_tobesigned_certificate_codec.cc index ab032fbd54c9f85c540db8542921908d858a49be..eee9014d89aa87f24247078d0b21c6d44a1d9e6c 100644 --- a/ccsrc/Protocols/Security/etsi_ts103097_tobesigned_certificate_codec.cc +++ b/ccsrc/Protocols/Security/etsi_ts103097_tobesigned_certificate_codec.cc @@ -9,7 +9,6 @@ int etsi_ts103097_tobesigned_certificate_codec::encode(const Ieee1609Dot2::ToBeSignedCertificate &p_cert, OCTETSTRING &data) { loggers::get_instance().log(">>> etsi_ts103097_tobesigned_certificate_codec::encode: %s", p_cert.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_cert.encode(*p_cert.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/etsi_ts103097_tobesigned_data_codec.cc b/ccsrc/Protocols/Security/etsi_ts103097_tobesigned_data_codec.cc index de882c8ac5858554e0cd92263cd85176875708d4..6e3d0a208751ee88ce6af77391f4db0fa5f1b9fc 100644 --- a/ccsrc/Protocols/Security/etsi_ts103097_tobesigned_data_codec.cc +++ b/ccsrc/Protocols/Security/etsi_ts103097_tobesigned_data_codec.cc @@ -9,7 +9,6 @@ int etsi_ts103097_tobesigned_data_codec::encode(const Ieee1609Dot2::ToBeSignedData &p_cert, OCTETSTRING &data) { loggers::get_instance().log(">>> etsi_ts103097_tobesigned_data_codec::encode: %s", p_cert.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_cert.encode(*p_cert.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/hmac.cc b/ccsrc/Protocols/Security/hmac.cc deleted file mode 100644 index 0ff752057113ca01e07f3ad4e780c9b8ce9d32ed..0000000000000000000000000000000000000000 --- a/ccsrc/Protocols/Security/hmac.cc +++ /dev/null @@ -1,54 +0,0 @@ -/*! - * \file hmac.cc - * \brief Source file for HMAC helper methods. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#include - -#include "hmac.hh" - -#include "loggers.hh" - -int hmac::generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING &p_hmac) { - // Sanity check - if (p_buffer.lengthof() == 0) { - return -1; - } - - return generate(static_cast(p_buffer), p_buffer.lengthof(), static_cast(p_secret_key), p_secret_key.lengthof(), - p_hmac); -} - -int hmac::generate(const unsigned char *p_buffer, const size_t p_buffer_length, const unsigned char *p_secret_key, const size_t p_secret_key_length, - OCTETSTRING &p_hmac) { - // Sanity check - if ((p_buffer == nullptr) || (p_secret_key == nullptr)) { - return -1; - } - ::HMAC_CTX_reset(_ctx); - - p_hmac = int2oct(0, EVP_MAX_MD_SIZE); - if (_hash_algorithms == hash_algorithms::sha_256) { - ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha256(), NULL); - } else if (_hash_algorithms == hash_algorithms::sha_384) { - ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha384(), NULL); - } else { // TODO To be continued - return -1; - } - // Compute the hash value - ::HMAC_Update(_ctx, p_buffer, p_buffer_length); - unsigned int length = p_hmac.lengthof(); - ::HMAC_Final(_ctx, (unsigned char *)static_cast(p_hmac), &length); - loggers::get_instance().log_to_hexa("hmac::generate: ", (unsigned char *)static_cast(p_hmac), length); - // Resize the hmac - if (_hash_algorithms == hash_algorithms::sha_256) { - p_hmac = OCTETSTRING(16, static_cast(p_hmac)); - } // FIXME Check length for the other hash algorithm - - return 0; -} diff --git a/ccsrc/Protocols/Security/hmac.hh b/ccsrc/Protocols/Security/hmac.hh deleted file mode 100644 index 9ae7215bd1729c2d75f6a722eb4d95f2f01a7d46..0000000000000000000000000000000000000000 --- a/ccsrc/Protocols/Security/hmac.hh +++ /dev/null @@ -1,69 +0,0 @@ -/*! - * \file hmac.hh - * \brief Header file for HMAC helper methods. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include - -#include - -class OCTETSTRING; //! TITAN forward declaration - -/*! - * \enum Supported hash algorithms - */ -enum class hash_algorithms : unsigned char { - sha_256, /*!< HMAC with SHA-256 */ - sha_384 /*!< HMAC with SHA-384 */ -}; // End of class hash_algorithms - -/*! - * \class hmac - * \brief This class provides description of HMAC helper methods - */ -class hmac { - HMAC_CTX * _ctx; //! HMAC context - hash_algorithms _hash_algorithms; //! HMAC hash algorithm to use -public: - /*! - * \brief Default constructor - * Create a new instance of the hmac class - * \param[in] p_hash_algorithms The hash algorithm to be used to compute the HMAC. Default: sha_256 - */ - hmac(const hash_algorithms p_hash_algorithms = hash_algorithms::sha_256) : _ctx{::HMAC_CTX_new()}, _hash_algorithms(p_hash_algorithms){}; - /*! - * \brief Default destructor - */ - virtual ~hmac() { - if (_ctx != nullptr) { - ::HMAC_CTX_free(_ctx); - }; - }; - - /*! - * \fn int generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING& p_hmac); - * \brief Generate the HMAC of data using a secret key - * \Param[in] p_buffer The data tobe hashed - * \param[in] p_secret_key The secret key to be used to generate the HMAC - * \param[out] p_hmac The HMAC value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING &p_hmac); // TODO Use reference & - - /*! - * \fn int generate(const unsigned char* p_buffer, const size_t p_buffer_length, const unsigned char* p_secret_key, const size_t p_secret_key_length, - * OCTETSTRING& p_hmac); \brief Generate the HMAC of data using a secret key \param[in] p_buffer The data to be hashed \param[in] p_buffer_length The size of - * the data \param[in] p_secret_key The secret key to be used to generate the HMAC \param[in] p_secret_key_length The size of the secret key \param[out] - * p_hmac The HMAC value based of the provided data \return 0 on success, -1 otherwise - */ - int generate(const unsigned char *p_buffer, const size_t p_buffer_length, const unsigned char *p_secret_key, const size_t p_secret_key_length, - OCTETSTRING &p_hmac); - -}; // End of class hmac diff --git a/ccsrc/Protocols/Security/http_etsi_ieee1609dot2_codec.cc b/ccsrc/Protocols/Security/http_etsi_ieee1609dot2_codec.cc index 18b95c2e770940b5a4f2689fd286b0fa6521f936..63ed151cf814cd646f208215a3938eab05c45fea 100644 --- a/ccsrc/Protocols/Security/http_etsi_ieee1609dot2_codec.cc +++ b/ccsrc/Protocols/Security/http_etsi_ieee1609dot2_codec.cc @@ -4,7 +4,7 @@ #include "LibHttp_MessageBodyTypes.hh" -#include "security_services.hh" +#include "security_services_its.hh" #include "loggers.hh" diff --git a/ccsrc/Protocols/Security/ieee_1609dot2_base_types_public_encryption_key.cc b/ccsrc/Protocols/Security/ieee_1609dot2_base_types_public_encryption_key.cc index 5732b4f796388fa0b87b1cbfe24a01fa4b042b9e..e5056fceda3f31fa09a84f3ff5be1a7745d48530 100644 --- a/ccsrc/Protocols/Security/ieee_1609dot2_base_types_public_encryption_key.cc +++ b/ccsrc/Protocols/Security/ieee_1609dot2_base_types_public_encryption_key.cc @@ -5,7 +5,6 @@ int ieee_1609dot2_base_types_public_encryption_key::encode(const Ieee1609Dot2BaseTypes::PublicEncryptionKey &p_public_encryption_key, OCTETSTRING &p_data) { loggers::get_instance().log(">>> ieee_1609dot2_base_types_public_encryption_key::encode: %s", p_public_encryption_key.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_public_encryption_key.encode(*p_public_encryption_key.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/ieee_1609dot2_base_types_public_verification_key.cc b/ccsrc/Protocols/Security/ieee_1609dot2_base_types_public_verification_key.cc index 421245d32ec0ed4eec0d30e0c1edbbbd9725ac94..dd10c83b6f16bf051ac1bcfe877bbb7ee761e67a 100644 --- a/ccsrc/Protocols/Security/ieee_1609dot2_base_types_public_verification_key.cc +++ b/ccsrc/Protocols/Security/ieee_1609dot2_base_types_public_verification_key.cc @@ -6,7 +6,6 @@ int ieee_1609dot2_base_types_public_verification_key::encode(const Ieee1609Dot2B OCTETSTRING & p_data) { loggers::get_instance().log(">>> ieee_1609dot2_base_types_public_verification_key::encode: %s", p_public_verification_key.get_descriptor()->name); - BITSTRING b; TTCN_EncDec::clear_error(); TTCN_Buffer buffer; p_public_verification_key.encode(*p_public_verification_key.get_descriptor(), buffer, TTCN_EncDec::CT_OER); diff --git a/ccsrc/Protocols/Security/module.mk b/ccsrc/Protocols/Security/module.mk index d1565ffef456675c38407c13449c2a3d3b90c645..35c24c171fccad48b9d19e2681f5fa4815904605 100644 --- a/ccsrc/Protocols/Security/module.mk +++ b/ccsrc/Protocols/Security/module.mk @@ -3,16 +3,14 @@ sources := certificates_loader.cc \ etsi_ts103097_data_codec.cc \ etsi_ts103097_tobesigned_certificate_codec.cc \ etsi_ts103097_tobesigned_data_codec.cc \ - hmac.cc \ ieee_1609dot2_base_types_public_encryption_key.cc \ ieee_1609dot2_base_types_public_verification_key.cc \ security_cache.cc \ security_db.cc \ security_db_record.cc \ security_ecc.cc \ - security_services.cc \ - sha256.cc \ - sha384.cc \ + security_services_its.cc \ + ifeq (AtsPki, $(ATS)) sources += http_etsi_ieee1609dot2_codec.cc \ @@ -29,6 +27,11 @@ sources += http_etsi_ieee1609dot2_codec.cc \ endif +ifeq (AtsMBR, $(ATS)) +sources += http_etsi_ieee1609dot2_codec.cc \ + +endif + ifeq (AtsRSUsSimulator, $(ATS)) sources += http_etsi_ieee1609dot2_codec.cc \ etsi_ts102941_base_types_public_keys.cc \ @@ -44,4 +47,5 @@ sources += http_etsi_ieee1609dot2_codec.cc \ endif -includes := . +includes := . ../../../titan-test-system-framework/ccsrc/security/include + diff --git a/ccsrc/Protocols/Security/security_cache.cc b/ccsrc/Protocols/Security/security_cache.cc index e1b631b3b18ff839df59ecc03a3f2a77547b4fc9..18fcf16fb3720078b7c39b8f607199a3e4fd438d 100644 --- a/ccsrc/Protocols/Security/security_cache.cc +++ b/ccsrc/Protocols/Security/security_cache.cc @@ -23,27 +23,7 @@ using namespace std; // Required for isnan() #include "loggers.hh" -bool security_cache_comp::operator()(const OCTETSTRING &p_lhs, const OCTETSTRING &p_rhs) const { - // loggers::get_instance().log_msg(">>> security_cache_comp::operator(): p_lhs= ", p_lhs); - // loggers::get_instance().log_msg(">>> security_cache_comp::operator(): p_rhs= ", p_rhs); - unsigned char *first1 = (unsigned char *)static_cast(p_lhs); - unsigned char *first2 = (unsigned char *)static_cast(p_rhs); - unsigned char *last1 = p_lhs.lengthof() + (unsigned char *)static_cast(p_lhs); - unsigned char *last2 = p_rhs.lengthof() + (unsigned char *)static_cast(p_rhs); - - while (first1 != last1) { - if ((first2 == last2) || (*first2 < *first1)) { - return false; - } else if (*first1 < *first2) { - return true; - } - ++first1; - ++first2; - } // End of 'while' statement - return (first2 != last2); -} - -security_cache::security_cache() : _certificates_idx(), _certificates(), _hashed_id8s() { loggers::get_instance().log(">>> security_cache::security_cache"); } // End of ctor +security_cache::security_cache() : _certificates() { loggers::get_instance().log(">>> security_cache::security_cache"); } // End of ctor security_cache::~security_cache() { loggers::get_instance().log(">>> security_cache::~security_cache"); @@ -53,8 +33,6 @@ security_cache::~security_cache() { int security_cache::clear() { loggers::get_instance().log(">>> security_cache::clear"); _certificates.clear(); // Smart pointers will do the job - _certificates_idx.clear(); - _hashed_id8s.clear(); return 0; } // End of clear method @@ -63,8 +41,9 @@ int security_cache::load_certificate(const std::string &p_certificate_id, const loggers::get_instance().log(">>> security_cache::load_certificate: '%s'", p_certificate_id.c_str()); // Sanity check - std::map::const_iterator s = _certificates_idx.find(p_certificate_id); - if (s == _certificates_idx.cend()) { + std::map& certificates = certificates_loader::get_instance().get_certificates(); + std::map::const_iterator s = certificates.find(p_certificate_id); + if (s == certificates.cend()) { loggers::get_instance().warning("security_cache::load_certificate: record not found"); return -1; } @@ -75,7 +54,8 @@ int security_cache::load_certificate(const std::string &p_certificate_id, const loggers::get_instance().warning("security_cache::load_certificate: Failed to load certificate"); return -1; } else { - it = _certificates.find(p_certificate_id); + *p_record = _certificates[p_certificate_id].get(); + return 0; } } @@ -88,8 +68,9 @@ int security_cache::get_certificate_id(const OCTETSTRING &p_hashed_id8, std::str loggers::get_instance().log_msg(">>> security_cache::get_certificate_id: ", p_hashed_id8); // Get the certificate id from the hashedid8 - std::map::const_iterator it = _hashed_id8s.find(p_hashed_id8); - if (it == _hashed_id8s.cend()) { + std::map& hashed_id8s = certificates_loader::get_instance().get_hashed_id8s(); + std::map::const_iterator it = hashed_id8s.find(p_hashed_id8); + if (it == hashed_id8s.cend()) { loggers::get_instance().warning("security_cache::get_certificate_id: record not found in index"); p_certificate_id = ""; return -1; @@ -119,7 +100,7 @@ int security_cache::get_certificate(const std::string &p_certificate_id, Ieee160 const security_db_record* record; if (load_certificate(p_certificate_id, &record) == -1) { - loggers::get_instance().warning("security_cache::get_private_key: Failed to load certificate"); + loggers::get_instance().warning("security_cache::get_certificate (1): Failed to load certificate"); return -1; } @@ -131,21 +112,15 @@ int security_cache::get_certificate(const std::string &p_certificate_id, Ieee160 int security_cache::get_certificate(const OCTETSTRING &p_hashed_id3, Ieee1609Dot2::CertificateBase &p_certificate) { loggers::get_instance().log_msg(">>> security_cache::get_certificate (2): ", p_hashed_id3); - std::map::const_iterator s; - for (s = _hashed_id8s.cbegin(); s != _hashed_id8s.cend(); ++s) { - if ((p_hashed_id3[2] == (s->first)[(s->first).lengthof() - 1]) && (p_hashed_id3[1] == (s->first)[(s->first).lengthof() - 2]) && - (p_hashed_id3[0] == (s->first)[(s->first).lengthof() - 3])) { - break; - } - } // End of 'for' statement - if (s == _hashed_id8s.cend()) { + std::string certificate_id; + if (get_certificate_hashed_id3(p_hashed_id3, certificate_id) == -1) { loggers::get_instance().warning("security_cache::get_certificate (2): hashedId3 does not match"); return -1; } const security_db_record* record; - if (load_certificate(s->second, &record) == -1) { - loggers::get_instance().warning("security_cache::get_private_key: Failed to load certificate"); + if (load_certificate(certificate_id, &record) == -1) { + loggers::get_instance().warning("security_cache::get_certificate (2): Failed to load certificate"); return -1; } @@ -157,14 +132,15 @@ int security_cache::get_certificate(const OCTETSTRING &p_hashed_id3, Ieee1609Dot int security_cache::get_certificate_hashed_id3(const OCTETSTRING &p_hashed_id3, std::string &p_certificate_id) const { loggers::get_instance().log_msg(">>> security_cache::get_certificate_hashed_id3: ", p_hashed_id3); + std::map& hashed_id8s = certificates_loader::get_instance().get_hashed_id8s(); std::map::const_iterator s; - for (s = _hashed_id8s.cbegin(); s != _hashed_id8s.cend(); ++s) { + for (s = hashed_id8s.cbegin(); s != hashed_id8s.cend(); ++s) { if ((p_hashed_id3[2] == (s->first)[(s->first).lengthof() - 1]) && (p_hashed_id3[1] == (s->first)[(s->first).lengthof() - 2]) && (p_hashed_id3[0] == (s->first)[(s->first).lengthof() - 3])) { break; } } // End of 'for' statement - if (s == _hashed_id8s.cend()) { + if (s == hashed_id8s.cend()) { loggers::get_instance().warning("security_cache::get_certificate_hashed_id3: hashedId3 does not match"); p_certificate_id = ""; return -1; @@ -175,6 +151,20 @@ int security_cache::get_certificate_hashed_id3(const OCTETSTRING &p_hashed_id3, return 0; } +int security_cache::get_signing_algorithm(const std::string &p_certificate_id, ec_elliptic_curves* p_signing_algorithm) { + loggers::get_instance().log(">>> security_cache::get_signing_algorithm: '%s'", p_certificate_id.c_str()); + + const security_db_record* record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("security_cache::get_signing_algorithm: Failed to load certificate"); + return -1; + } + + *p_signing_algorithm = record->signing_algorithm(); + + return 0; +} + int security_cache::get_issuer(const std::string &p_certificate_id, OCTETSTRING &p_hashed_id_issuer) { loggers::get_instance().log(">>> security_cache::get_issuer: '%s'", p_certificate_id.c_str()); @@ -192,8 +182,9 @@ int security_cache::get_issuer(const std::string &p_certificate_id, OCTETSTRING int security_cache::get_hashed_id(const std::string &p_certificate_id, OCTETSTRING &p_hashed_id) const { loggers::get_instance().log(">>> security_cache::get_hashed_id: '%s'", p_certificate_id.c_str()); - std::map::const_iterator it = _certificates_idx.find(p_certificate_id); - if (it == _certificates_idx.cend()) { + std::map& certificates = certificates_loader::get_instance().get_certificates(); + std::map::const_iterator it = certificates.find(p_certificate_id); + if (it == certificates.cend()) { loggers::get_instance().warning("security_cache::get_hashed_id: record not found"); p_hashed_id = OCTETSTRING(0, nullptr); return -1; @@ -201,6 +192,7 @@ int security_cache::get_hashed_id(const std::string &p_certificate_id, OCTETSTRI p_hashed_id = it->second; + loggers::get_instance().log_msg("<<< security_cache::get_hashed_id: ", p_hashed_id); return 0; } @@ -331,7 +323,7 @@ bool security_cache::fill_vector(OCTETSTRING &p_vector, const OCTETSTRING &p_org return false; } -int security_cache::store_certificate(const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, +int security_cache::store_certificate(const ec_elliptic_curves p_signing_algorithm, const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, const OCTETSTRING &p_public_key_y, const OCTETSTRING &p_public_compressed_key, const INTEGER &p_public_compressed_key_mode, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, const OCTETSTRING &p_hashed_id8, const OCTETSTRING &p_issuer, const OCTETSTRING &p_private_enc_key, @@ -372,7 +364,8 @@ int security_cache::store_certificate(const CHARSTRING &p_cert_id, const OCTETST etsi_ts103097_certificate_codec codec; codec.decode(p_cert, decoded_certificate); loggers::get_instance().log_msg("security_cache::store_certificate: Decoded certificate: ", decoded_certificate); - security_db_record *p = new security_db_record(key, // Certificate id + security_db_record *p = new security_db_record(p_signing_algorithm, // Signing algorithm + key, // Certificate id cert, // Certificate decoded_certificate, issuer, // Hashed ID for the issuer @@ -389,30 +382,17 @@ int security_cache::store_certificate(const CHARSTRING &p_cert_id, const OCTETST public_enc_comp_key // Public encryption compressed key, 33 or 49 bytes ); if (p == nullptr) { + loggers::get_instance().error("security_cache::store_certificate: Failed to allocate memory"); return -1; } + certificates_loader::get_instance().save_certificate(*p); + std::map>::const_iterator i = _certificates.find(key); if (i != _certificates.cend()) { _certificates.erase(i); } - _certificates.insert(std::pair>(key, std::unique_ptr(p))); - std::map::const_iterator h = _hashed_id8s.find(hashed_id8); - if (h != _hashed_id8s.cend()) { - loggers::get_instance().log_msg("security_cache::store_certificate: Replace entry in _hashed_id8s: ", h->first); - _hashed_id8s.erase(h); - } - std::map::const_iterator k = _certificates_idx.find(h->second); - if (k != _certificates_idx.cend()) { - loggers::get_instance().log("security_cache::store_certificate: Replace entry in _certificates_idx: %s", k->first.c_str()); - _certificates_idx.erase(k); - } - loggers::get_instance().log_msg("security_cache::store_certificate: Add entry ", hashed_id8); - loggers::get_instance().log("security_cache::store_certificate: Add entry for key %s", key.c_str()); - _hashed_id8s.insert(std::pair(hashed_id8, key)); - _certificates_idx.insert(std::pair(key, hashed_id8)); - return 0; } @@ -436,10 +416,16 @@ void security_cache::dump() const { loggers::get_instance().log_msg("security_cache::dump: public_enc_key_y = ", p->public_enc_key_y()); loggers::get_instance().log_msg("security_cache::dump: public_enc_comp_key = ", p->public_enc_comp_key()); } // End of 'for' statement - // for (std::map::const_iterator it = _hashed_id8s.cbegin(); it != _hashed_id8s.cend(); ++it) { - loggers::get_instance().log("security_cache::dump: Hashedid8 table length: %d", _hashed_id8s.size()); - for (std::map::const_iterator it = _hashed_id8s.cbegin(); it != _hashed_id8s.cend(); ++it) { + std::map& hashed_id8s = certificates_loader::get_instance().get_hashed_id8s(); + loggers::get_instance().log("security_cache::dump: Hashedid8 table length: %d", hashed_id8s.size()); + for (std::map::const_iterator it = hashed_id8s.cbegin(); it != hashed_id8s.cend(); ++it) { loggers::get_instance().log_msg("security_cache::dump: Hashedid8 key = ", it->first); loggers::get_instance().log("security_cache::dump: Hashedid8 idx ==> %s", it->second.c_str()); } // End of 'for' statement + std::map& certificates = certificates_loader::get_instance().get_certificates(); + loggers::get_instance().log("security_cache::dump: certificates table length: %d", certificates.size()); + for (std::map::const_iterator it = certificates.cbegin(); it != certificates.cend(); ++it) { + loggers::get_instance().log("security_cache::dump: certificates idx ==> %s", it->first.c_str()); + loggers::get_instance().log_msg("security_cache::dump: certificates key = ", it->second); + } // End of 'for' statement } // End of method dump diff --git a/ccsrc/Protocols/Security/security_cache.hh b/ccsrc/Protocols/Security/security_cache.hh index 6aed0146320d32bc5ac574b2410ea1208b3fa0b2..3adc29942b3fd9f630f3ffa81e1ca91e7806394c 100644 --- a/ccsrc/Protocols/Security/security_cache.hh +++ b/ccsrc/Protocols/Security/security_cache.hh @@ -22,10 +22,6 @@ class OCTETSTRING; //! TITAN forward declaration class INTEGER; //! TITAN forward declaration class CHARSTRING; //! TITAN forward declaration -struct security_cache_comp { - bool operator()(const OCTETSTRING &p_lhs, const OCTETSTRING &p_rhs) const; -}; - /*! * \class security_cache * \brief This class provides security record description for in memory security database. In memory mens there is no disk load/save mechanism @@ -35,13 +31,8 @@ class security_cache { protected: /*! \protectedsection */ // TODO Enforce with const security_cache_record, and const std::string - std::map _certificates_idx; //! List of the certificates indexed by the certificate identifier - std::map _hashed_id8s; //! List of the certificates indexed by the HashedId8 std::map> _certificates; //! List of the certificates indexed by the certificate identifier - // FIXME In _certificates: relace key by hashed_id8s: std::map> _certificates; - - public: /*! \publicsection */ /*! * \brief Default ctor @@ -92,6 +83,14 @@ public: /*! \publicsection */ * \return 0 on success, -1 otherwise */ int get_certificate_hashed_id3(const OCTETSTRING &p_hashed_id3, std::string &p_certificate_id) const; + /*! + * \fn int get_signing_algorithm(const std::string &p_certificate_id, ec_elliptic_curves* p_signing_algorithm); + * \brief Retrive the signing algorithm of the specified certificate (in case of Implicit certificate) + * \param[in] p_certificate_id The certificate name + * \param[out] p_hashed_id_issuer The HashedId8 of the isseur certificate + * \return 0 on success, -1 otherwise + */ + int get_signing_algorithm(const std::string &p_certificate_id, ec_elliptic_curves* p_signing_algorithm); /*! * \fn int get_issuer(const std::string &p_certificate_id, OCTETSTRING &p_hashed_id_issuer); * \brief Retrive the issuer of the specified certificate @@ -177,7 +176,7 @@ public: /*! \publicsection */ */ int get_public_enc_comp_key(const std::string &p_certificate_id, OCTETSTRING &p_public_enc_comp_key, INTEGER &p_enc_comp_mode); - virtual int store_certificate(const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, + virtual int store_certificate(const ec_elliptic_curves p_signing_algorithm, const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, const OCTETSTRING &p_public_key_y, const OCTETSTRING &p_public_compressed_key, const INTEGER &p_public_compressed_key_mode, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, const OCTETSTRING &p_hashid8, const OCTETSTRING &p_issuer, const OCTETSTRING &p_private_enc_key, const OCTETSTRING &p_public_enc_key_x, const OCTETSTRING &p_public_enc_key_y, diff --git a/ccsrc/Protocols/Security/security_db.cc b/ccsrc/Protocols/Security/security_db.cc index f61c1dd571b0b1046d65712ec3231c7acc5cfbfd..c6965191434029fd30ef1b46e8da19f71440edc7 100644 --- a/ccsrc/Protocols/Security/security_db.cc +++ b/ccsrc/Protocols/Security/security_db.cc @@ -30,7 +30,7 @@ int security_db::initialize_cache(const std::string &p_db_path) { } // TODO Build the maps of couple {HasehedId8, Certificate} - if (certificates_loader::get_instance().build_certificates_index(_certificates_idx, _hashed_id8s) == -1) { + if (certificates_loader::get_instance().build_certificates_index() == -1) { loggers::get_instance().log(">>> security_db::initialize_cache: certificates_loader::build_certificates_index method failed"); return -1; } @@ -38,14 +38,14 @@ int security_db::initialize_cache(const std::string &p_db_path) { return 0; } -int security_db::store_certificate(const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, +int security_db::store_certificate(const ec_elliptic_curves p_signing_algorithm, const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, const OCTETSTRING &p_public_key_y, const OCTETSTRING &p_public_compressed_key, const INTEGER &p_public_compressed_key_mode, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, const OCTETSTRING &p_hashed_id8, const OCTETSTRING &p_issuer, const OCTETSTRING &p_private_enc_key, const OCTETSTRING &p_public_enc_key_x, const OCTETSTRING &p_public_enc_key_y, const OCTETSTRING &p_public_enc_compressd_key, const INTEGER &p_public_enc_compressed_key_mode) { loggers::get_instance().log_msg(">>> security_db::store_certificate: ", p_cert_id); - if (security_cache::store_certificate(p_cert_id, p_cert, p_private_key, p_public_key_x, p_public_key_y, p_public_compressed_key, p_public_compressed_key_mode, + if (security_cache::store_certificate(p_signing_algorithm, p_cert_id, p_cert, p_private_key, p_public_key_x, p_public_key_y, p_public_compressed_key, p_public_compressed_key_mode, p_hash, p_hash_sha_256, p_hashed_id8, p_issuer, p_private_enc_key, p_public_enc_key_x, p_public_enc_key_y, p_public_enc_compressd_key, p_public_enc_compressed_key_mode) != 0) { return -1; diff --git a/ccsrc/Protocols/Security/security_db.hh b/ccsrc/Protocols/Security/security_db.hh index dd21a21ab13634a7259acca779a57de76d9b76f9..ad757df38e8ae2506c3bccc97a78181a2497e2eb 100644 --- a/ccsrc/Protocols/Security/security_db.hh +++ b/ccsrc/Protocols/Security/security_db.hh @@ -33,13 +33,13 @@ public: /*! \publicsection */ ~security_db(); /*! - * \fn int store_certificate(const CHARSTRING& p_cert_id, const OCTETSTRING& p_cert, const OCTETSTRING& p_private_key, const OCTETSTRING& p_public_key_x, + * \fn int store_certificate(const ec_elliptic_curves p_signing_algorithm, const CHARSTRING& p_cert_id, const OCTETSTRING& p_cert, const OCTETSTRING& p_private_key, const OCTETSTRING& p_public_key_x, * const OCTETSTRING& p_public_key_y, const OCTETSTRING& p_public_compressed_key, const INTEGER& p_public_compressed_key_mode, const OCTETSTRING& p_hashid8, * const OCTETSTRING& p_issuer, const OCTETSTRING& p_private_enc_key, const OCTETSTRING& p_public_enc_key_x, const OCTETSTRING& p_public_enc_key_y, const * OCTETSTRING& p_public_enc_compressed_key, const INTEGER& p_public_enc_compressed_key_mode); \brief Store a new certificate \param[in] p_cert_id The * certificate identifier \return 0 on success, -1 otherwise */ - int store_certificate(const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, + int store_certificate(const ec_elliptic_curves p_signing_algorithm, const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, const OCTETSTRING &p_public_key_y, const OCTETSTRING &p_public_compressed_key, const INTEGER &p_public_compressed_key_mode, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, const OCTETSTRING &p_hashid8, const OCTETSTRING &p_issuer, const OCTETSTRING &p_private_enc_key, const OCTETSTRING &p_public_enc_key_x, const OCTETSTRING &p_public_enc_key_y, diff --git a/ccsrc/Protocols/Security/security_db_record.cc b/ccsrc/Protocols/Security/security_db_record.cc index 3760651e03912290a230a14d81832781d5d0a63b..a7246349745ba407839a769c4bb8e1faf5831635 100644 --- a/ccsrc/Protocols/Security/security_db_record.cc +++ b/ccsrc/Protocols/Security/security_db_record.cc @@ -14,21 +14,21 @@ #include "sha256.hh" #include "sha384.hh" -security_db_record::security_db_record(const std::string &p_certificate_id, const OCTETSTRING &p_certificate, +security_db_record::security_db_record(const ec_elliptic_curves p_algorithm, const std::string &p_certificate_id, const OCTETSTRING &p_certificate, const Ieee1609Dot2::CertificateBase &p_decoded_certificate, const OCTETSTRING &p_hashed_id_issuer, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, const OCTETSTRING &p_hashed_id, const OCTETSTRING &p_pr_key, const OCTETSTRING &p_pu_key_x, const OCTETSTRING &p_pu_key_y, const OCTETSTRING &p_pu_comp_key, const OCTETSTRING &p_pr_enc_key, const OCTETSTRING &p_pu_enc_key_x, const OCTETSTRING &p_pu_enc_key_y, const OCTETSTRING &p_pu_enc_comp_key, const bool p_to_be_saved) - : _algorithm{ec_elliptic_curves::nist_p_256}, _certificate_id(p_certificate_id), _certificate(p_certificate), _hashed_id_issuer(p_hashed_id_issuer), + : _algorithm{p_algorithm}, _certificate_id(p_certificate_id), _certificate(p_certificate), _hashed_id_issuer(p_hashed_id_issuer), _hash(p_hash), _hash_sha_256(p_hash_sha_256), _hashed_id(p_hashed_id), _pr_key(p_pr_key), _pu_key_x(p_pu_key_x), _pu_key_y(p_pu_key_y), _pu_comp_key(p_pu_comp_key), _pr_enc_key(p_pr_enc_key), _pu_enc_key_x(p_pu_enc_key_x), _pu_enc_key_y(p_pu_enc_key_y), _pu_enc_comp_key(p_pu_enc_comp_key), - _to_be_saved(p_to_be_saved), _decoded_certificate(static_cast(p_decoded_certificate.clone())) {} + _to_be_saved(p_to_be_saved), _decoded_certificate(static_cast(p_decoded_certificate.clone())) {} security_db_record::~security_db_record() { if (_decoded_certificate != nullptr) { delete _decoded_certificate; } -}; +} const Ieee1609Dot2::CertificateBase &security_db_record::decoded_certificate() const { return *_decoded_certificate; } diff --git a/ccsrc/Protocols/Security/security_db_record.hh b/ccsrc/Protocols/Security/security_db_record.hh index 94fb41297d03bf2b8355303d9bca1422ed1d3f8d..f510f95118f58ea527cd2c662a465d1992bf1246 100644 --- a/ccsrc/Protocols/Security/security_db_record.hh +++ b/ccsrc/Protocols/Security/security_db_record.hh @@ -71,7 +71,7 @@ public: /*! \publicsection */ * \param[in] p_pu_enc_comp_key_y The public compressed coordinate encryption key * \param[in] p_to_be_saved Set to true to save on disk this certificate.Default: true */ - security_db_record(const std::string &p_certificate_id, const OCTETSTRING &p_certificate, const Ieee1609Dot2::CertificateBase &p_decoded_certificate, + security_db_record(const ec_elliptic_curves p_algorithm, const std::string &p_certificate_id, const OCTETSTRING &p_certificate, const Ieee1609Dot2::CertificateBase &p_decoded_certificate, const OCTETSTRING &p_hashed_id_issuer, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, const OCTETSTRING &p_hashed_id, const OCTETSTRING &p_pr_key, const OCTETSTRING &p_pu_key_x, const OCTETSTRING &p_pu_key_y, const OCTETSTRING &p_pu_comp_key, const OCTETSTRING &p_pr_enc_key, const OCTETSTRING &p_pu_enc_key_x, const OCTETSTRING &p_pu_enc_key_y, @@ -89,6 +89,14 @@ public: /*! \publicsection */ */ const Ieee1609Dot2::CertificateBase &decoded_certificate() const; + /*! + * \inline + * \fn const ec_elliptic_curves signing_algorithm() const; + * \brief Retrieve the signing algotrithm + * \return The signing algotrithm + */ + inline const ec_elliptic_curves signing_algorithm() const { return _algorithm; }; + /*! * \inline * \fn const std::string& certificate_id() const; diff --git a/ccsrc/Protocols/Security/security_ecc.cc b/ccsrc/Protocols/Security/security_ecc.cc index 0c27b9e206b0bf6309ebafef53193703a1a894b0..0c1cbf4cc0eca8dfbb43e098f1415c722d7db863 100644 --- a/ccsrc/Protocols/Security/security_ecc.cc +++ b/ccsrc/Protocols/Security/security_ecc.cc @@ -48,7 +48,7 @@ security_ecc::security_ecc(const ec_elliptic_curves p_elliptic_curve, const OCTE loggers::get_instance().log(">>> security_ecc::security_ecc (1): %d", static_cast(p_elliptic_curve)); // Sanity checks - if ((_elliptic_curve == ec_elliptic_curves::nist_p_256) || (_elliptic_curve == ec_elliptic_curves::brainpool_p_256_r1)) { + if ((_elliptic_curve == ec_elliptic_curves::nist_p_256) || (_elliptic_curve == ec_elliptic_curves::brainpool_p_256_r1) || (_elliptic_curve == ec_elliptic_curves::sm2_p_256)) { if (p_private_key.lengthof() != 32) { loggers::get_instance().error("security_ecc::security_ecc (1): Invalid public keys size"); } @@ -67,7 +67,7 @@ security_ecc::security_ecc(const ec_elliptic_curves p_elliptic_curve, const OCTE // Build private key BIGNUM *p = ::BN_new(); ::BN_bin2bn(static_cast(_pri_key), _pri_key.lengthof(), p); - // Build public keys + // Build public keys: Q=d*G, d is the priviate key (prime value) and G is the elliptic curve base point EC_POINT *ec_point = ::EC_POINT_new(_ec_group); ::EC_POINT_mul(_ec_group, ec_point, p, nullptr, nullptr, _bn_ctx); // Set private key @@ -135,7 +135,7 @@ security_ecc::security_ecc(const ec_elliptic_curves p_elliptic_curve, const OCTE loggers::get_instance().log(">>> security_ecc::security_ecc (2): %d", static_cast(p_elliptic_curve)); // Sanity checks - if ((_elliptic_curve == ec_elliptic_curves::nist_p_256) || (_elliptic_curve == ec_elliptic_curves::brainpool_p_256_r1)) { + if ((_elliptic_curve == ec_elliptic_curves::nist_p_256) || (_elliptic_curve == ec_elliptic_curves::brainpool_p_256_r1) || (_elliptic_curve == ec_elliptic_curves::sm2_p_256)) { if ((p_public_key_x.lengthof() != 32) || (p_public_key_y.lengthof() != 32)) { loggers::get_instance().error("security_ecc::security_ecc (2): Invalid public keys size"); } @@ -211,7 +211,7 @@ security_ecc::security_ecc(const ec_elliptic_curves p_elliptic_curve, const OCTE loggers::get_instance().log(">>> security_ecc::security_ecc (3): %d", static_cast(p_elliptic_curve)); // Sanity checks - if ((_elliptic_curve == ec_elliptic_curves::nist_p_256) || (_elliptic_curve == ec_elliptic_curves::brainpool_p_256_r1)) { + if ((_elliptic_curve == ec_elliptic_curves::nist_p_256) || (_elliptic_curve == ec_elliptic_curves::brainpool_p_256_r1) || (_elliptic_curve == ec_elliptic_curves::sm2_p_256)) { if (p_public_key_compressed.lengthof() != 32) { loggers::get_instance().error("security_ecc::security_ecc (3): Invalid public keys size"); } @@ -239,6 +239,8 @@ security_ecc::security_ecc(const ec_elliptic_curves p_elliptic_curve, const OCTE // No break; case ec_elliptic_curves::brainpool_p_256_r1: // No break; + case ec_elliptic_curves::sm2_p_256: + // No break; case ec_elliptic_curves::brainpool_p_384_r1: result = ::EC_POINT_set_compressed_coordinates_GFp( _ec_group, ec_point, compressed_key, (p_compressed_mode == ecc_compressed_mode::compressed_y_1) ? 1 : 0, _bn_ctx); // Use primary elliptic curve @@ -270,7 +272,7 @@ security_ecc::security_ecc(const ec_elliptic_curves p_elliptic_curve, const OCTE ::BN_bn2bin(xy, (unsigned char *)static_cast(v)); ::BN_clear_free(xy); xy = nullptr; - if ((v.lengthof() % 2) != 0) { // TODO Check alse xy[0] == 0x04 + if ((v.lengthof() % 2) != 0) { // TODO Check also xy[0] == 0x04 // Remove first byte loggers::get_instance().log_msg("security_ecc::security_ecc (3): Complete xy=", v); v = OCTETSTRING(v.lengthof() - 1, 1 + static_cast(v)); @@ -292,12 +294,13 @@ security_ecc::~security_ecc() { if (_ec_key != nullptr) { ::EC_KEY_free(_ec_key); + _ec_key = nullptr; } - if (_bn_ctx != nullptr) { + if (_bn_ctx != nullptr) {\ + ::BN_CTX_end(_bn_ctx); ::BN_CTX_free(_bn_ctx); + _bn_ctx = nullptr; } - - loggers::get_instance().log("<<< security_ecc::~security_ecc"); } // End of Destructor int security_ecc::generate() { @@ -306,7 +309,6 @@ int security_ecc::generate() { // Sanity check if (!::EC_KEY_generate_key(_ec_key)) { // Generate the private and public keys loggers::get_instance().error("security_ecc::generate: Failed to generate private/public keys"); - return -1; } BIGNUM * x = ::BN_new(); @@ -317,12 +319,14 @@ int security_ecc::generate() { switch (_elliptic_curve) { case ec_elliptic_curves::nist_p_256: // Use primary // No break; - case ec_elliptic_curves::nist_p_384: - // No break; case ec_elliptic_curves::brainpool_p_256_r1: + // No break; + case ec_elliptic_curves::sm2_p_256: size = 32; result = ::EC_POINT_get_affine_coordinates_GFp(_ec_group, ec_point, x, y, _bn_ctx); // Use primer on elliptic curve break; + case ec_elliptic_curves::nist_p_384: + // No break; case ec_elliptic_curves::brainpool_p_384_r1: size = 48; result = ::EC_POINT_get_affine_coordinates_GFp(_ec_group, ec_point, x, y, _bn_ctx); // Use primer on elliptic curve @@ -350,6 +354,7 @@ int security_ecc::generate() { int len = ::EC_POINT_point2oct(_ec_group, ec_point, POINT_CONVERSION_COMPRESSED, nullptr, 0, _bn_ctx); if (len == 0) { loggers::get_instance().warning("security_ecc::generate: Failed to generate x_coordinate compressed key"); + return -1; } _pub_key_compressed = int2oct(0, len); if (::EC_POINT_point2oct(_ec_group, ec_point, POINT_CONVERSION_COMPRESSED, (unsigned char *)static_cast(_pub_key_compressed), len, @@ -414,6 +419,8 @@ int security_ecc::generate_and_derive_ephemeral_key(const encryption_algotithm p case ec_elliptic_curves::nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve // No break; case ec_elliptic_curves::brainpool_p_256_r1: + // No break; + case ec_elliptic_curves::sm2_p_256: k_enc = 16; k_mac = 32; break; @@ -537,6 +544,8 @@ int security_ecc::generate_and_derive_ephemeral_key(const encryption_algotithm p case ec_elliptic_curves::nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve // No break; case ec_elliptic_curves::brainpool_p_256_r1: + // No break; + case ec_elliptic_curves::sm2_p_256: k_enc = 16; k_mac = 32; break; @@ -832,6 +841,7 @@ int security_ecc::sign(const OCTETSTRING &p_data, OCTETSTRING &p_r_sig, OCTETSTR return -1; } loggers::get_instance().log("security_ecc::sign: succeed"); + loggers::get_instance().log_msg("security_ecc::sign: signing private key: ", _pri_key); if (::ECDSA_do_verify(static_cast(p_data), p_data.lengthof(), signature, _ec_key) != 1) { loggers::get_instance().warning("security_ecc::sign: Signature not verified"); @@ -855,9 +865,71 @@ int security_ecc::sign(const OCTETSTRING &p_data, OCTETSTRING &p_r_sig, OCTETSTR return 0; } +int security_ecc::sign(const OCTETSTRING &p_data, const OCTETSTRING &p_entl_a, const OCTETSTRING &p_id, OCTETSTRING &p_r_sig, OCTETSTRING &p_s_sig) { + loggers::get_instance().log(">>> security_ecc::sign"); + loggers::get_instance().log_msg(">>> security_ecc::sign: p_data: ", p_data); + loggers::get_instance().log_msg(">>> security_ecc::sign: p_entl_a: ", p_entl_a); + loggers::get_instance().log_msg(">>> security_ecc::sign: p_id: ", p_id); + + // Sanity checks + if (_pri_key.lengthof() == 0) { // No private key + return -1; + } else if (p_data.lengthof() == 0) { + return -1; + } else if (p_entl_a.lengthof() == 0) { + return -1; + } else if (p_id.lengthof() == 0) { + return -1; + } + + // Build the message to sign - See P1609.2/D13, October 2022 Clause 5.3.1.3 SM2 + OCTETSTRING za = p_entl_a + p_id + OCTETSTRING(32, _a) + OCTETSTRING(32, _b) + OCTETSTRING(32, _xG) + OCTETSTRING(32, _yG) + _pub_key_x + _pub_key_y; + loggers::get_instance().log_msg("security_ecc::sign: za=", za); + // Compute H256(ZA) + OCTETSTRING h_za; + sha256 hash; + hash.generate(za, h_za); + loggers::get_instance().log_msg("security_ecc::sign: h_za=", h_za); + // Compute ZA||M + OCTETSTRING message_to_signed = h_za + p_data; + loggers::get_instance().log_msg("security_ecc::sign: message_to_signed=", message_to_signed); + // Compute digest based on Sm3 + OCTETSTRING digest; + if (compute_digest_sm3(message_to_signed, p_entl_a, p_id, digest) == -1) { + loggers::get_instance().log("security_ecc::sign: Failed to compute digest based on Sm3"); + return -1; + } + loggers::get_instance().log_msg("security_ecc::sign: Sm3 digest=", digest); + // Compute the signature + // FIXME Check returned values and cleanuo on error + EC_KEY* private_key; + ::EC_KEY_oct2priv(private_key, static_cast(_pri_key), _pri_key.lengthof()); + EVP_PKEY* private_evp_key = ::EVP_PKEY_new(); + ::EVP_PKEY_set1_EC_KEY(private_evp_key, private_key); + ::EVP_PKEY_set_alias_type(private_evp_key, EVP_PKEY_SM2); + EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); + ::EVP_MD_CTX_init(ctx); + ::EVP_SignInit_ex(ctx, ::EVP_sm3(), NULL); + ::EVP_SignUpdate(ctx, static_cast(digest), digest.lengthof()); + unsigned char signature[64] = { 0x00 }; + unsigned int signature_len = 64; + ::EVP_SignFinal(ctx, signature, &signature_len, private_evp_key); + + ::EVP_PKEY_free(private_evp_key); + ::EVP_MD_CTX_free(ctx); + ::EC_KEY_free(private_key); + + p_r_sig = OCTETSTRING(signature_len / 2, signature); + loggers::get_instance().log_msg("security_ecc::sign: r=", p_r_sig); + p_s_sig = OCTETSTRING(signature_len / 2, signature + signature_len / 2); + loggers::get_instance().log_msg("security_ecc::sign: s=", p_s_sig); + + return 0; +} + int security_ecc::sign_verif(const OCTETSTRING &p_data, const OCTETSTRING &p_signature) { - loggers::get_instance().log(">>> security_ecc::sign_verif"); loggers::get_instance().log_msg(">>> security_ecc::sign_verify: p_data: ", p_data); + loggers::get_instance().log_msg(">>> security_ecc::sign_verify: p_signature: ", p_signature); // Sanity checks if (p_data.lengthof() == 0) { @@ -878,6 +950,116 @@ int security_ecc::sign_verif(const OCTETSTRING &p_data, const OCTETSTRING &p_sig loggers::get_instance().log("security_ecc::sign_verif: %s", (result == 1) ? "succeed" : "failed"); return (result == 1) ? 0 : -1; } + +int security_ecc::sign_verif(const OCTETSTRING &p_data, const OCTETSTRING &p_entl_a, const OCTETSTRING &p_id, const OCTETSTRING &p_signature) { + loggers::get_instance().log_msg(">>> security_ecc::sign_verify (1): p_data: ", p_data); + loggers::get_instance().log_msg(">>> security_ecc::sign_verify (1): p_signature: ", p_signature); + + // Sanity checks + if (p_data.lengthof() == 0) { + return -1; + } + + // Build the signature + BIGNUM *r = ::BN_bin2bn(static_cast(p_signature), p_signature.lengthof() / 2, nullptr); + loggers::get_instance().log_to_hexa("security_ecc::sign_verify (1): r=", static_cast(p_signature), p_signature.lengthof() / 2); + BIGNUM *s = ::BN_bin2bn(static_cast(p_signature) + p_signature.lengthof() / 2, p_signature.lengthof() / 2, nullptr); + loggers::get_instance().log_to_hexa("security_ecc::sign_verify (1): s=", static_cast(p_signature) + p_signature.lengthof() / 2, + p_signature.lengthof() / 2); + // FIXME FSCOM + //loggers::get_instance().log("security_ecc::sign_verif: %s", (result == 1) ? "succeed" : "failed"); + //return (result == 1) ? 0 : -1; + return -1; +} + +int security_ecc::reconstruct_public_keys(const OCTETSTRING &p_cert_to_be_signed, const OCTETSTRING &p_issuer_public_key_x,const OCTETSTRING &p_issuer_public_key_y, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y, OCTETSTRING &p_public_key_compressed, INTEGER &p_public_key_compressed_mode) { + loggers::get_instance().log_msg(">>> security_ecc::reconstruct_public_keys: p_cert_to_be_signed: ", p_cert_to_be_signed); + + // Sanity checks + if ((p_issuer_public_key_x.lengthof() != 32) || (p_issuer_public_key_y.lengthof() != 32)) { + loggers::get_instance().error("security_ecc::reconstruct_public_keys: Invalid CA public keys size"); + } + + int fsize = (::EC_GROUP_get_degree(_ec_group) + 7) / 8; + loggers::get_instance().log("security_ecc::reconstruct_public_keys: fsize='%d'", fsize); + if (fsize != p_issuer_public_key_x.lengthof()) { + loggers::get_instance().warning("security_ecc::reconstruct_public_keys: key size mismatch"); + return -1; + } + if (fsize != p_cert_to_be_signed.lengthof()) { + loggers::get_instance().warning("security_ecc::reconstruct_public_keys: input hash size mismatch"); + return -1; + } + bn_print("security_ecc::reconstruct_public_keys: order=", ::EC_GROUP_get0_order(_ec_group)); + bn_print("security_ecc::reconstruct_public_keys: order=", ::EC_GROUP_get0_cofactor(_ec_group)); + + BIGNUM* H = ::BN_new(); + ::BN_bin2bn(static_cast(p_cert_to_be_signed), fsize, H); + //bn_print("security_ecc::reconstruct_public_keys: H(1)=", H); + ::BN_rshift1(H, H); // h: leftmost floor(log_2 n) bits of p_cert_to_be_signed + //bn_print("security_ecc::reconstruct_public_keys: H(2)=", H); + + // Build QCA + EC_POINT* QCA = ::EC_POINT_new(_ec_group); + bin_to_ec_point(p_issuer_public_key_x, p_issuer_public_key_y, &QCA); + //ec_point_print("security_ecc::reconstruct_public_keys: QCA:", QCA); + + // Public key reconstruction + // PU == _ec_key + //ec_point_print("security_ecc::reconstruct_public_keys: PU:", ::EC_KEY_get0_public_key(_ec_key)); + + // QU = h*PU + QCA + EC_POINT* QU = ::EC_POINT_new(_ec_group); + ::EC_POINT_mul(_ec_group, QU, NULL, ::EC_KEY_get0_public_key(_ec_key), H, _bn_ctx); + //ec_point_print("security_ecc::reconstruct_public_keys: QU (1):", QU); + ::EC_POINT_add(_ec_group, QU, QU, QCA, _bn_ctx); + //ec_point_print("security_ecc::reconstruct_public_keys: QU (2):", QU); + + // Set compressed public key + BIGNUM *xy = ::BN_new(); + ::EC_POINT_point2bn(_ec_group, QU, POINT_CONVERSION_COMPRESSED, xy, _bn_ctx); + loggers::get_instance().log("security_ecc::reconstruct_public_keys: compressed xy length: %d", BN_num_bytes(xy)); + if (BN_num_bytes(xy) == 0) { + ::BN_clear_free(xy); + loggers::get_instance().error("security_ecc::reconstruct_public_keys: Failed to generate compressed xy coordinates, check algorithms"); + } + OCTETSTRING v = int2oct(0, BN_num_bytes(xy)); + ::BN_bn2bin(xy, (unsigned char *)static_cast(v)); + p_public_key_compressed = OCTETSTRING(v.lengthof() - 1, static_cast(v) + 1); + p_public_key_compressed_mode = (*static_cast(v) == 0x02) ? 0 : 1; + // Set public keys + ::EC_POINT_point2bn(_ec_group, QU, POINT_CONVERSION_UNCOMPRESSED, xy, _bn_ctx); + if (BN_num_bytes(xy) == 0) { + ::BN_clear_free(xy); + loggers::get_instance().error("security_ecc::reconstruct_public_keys: Failed to generate xy coordinates, check algorithms"); + } + loggers::get_instance().log("security_ecc::reconstruct_public_keys: xy length: %d", BN_num_bytes(xy)); + // Generate X, Y coordinates + v = int2oct(0, BN_num_bytes(xy)); + ::BN_bn2bin(xy, (unsigned char *)static_cast(v)); + if ((v.lengthof() % 2) != 0) { // TODO Check also xy[0] == 0x04 + // Remove first byte + loggers::get_instance().log_msg("security_ecc::reconstruct_public_keys: Complete xy=", v); + v = OCTETSTRING(v.lengthof() - 1, 1 + static_cast(v)); + } + loggers::get_instance().log_msg("security_ecc::reconstruct_public_keys: xy=", v); + const int l = v.lengthof() / 2; + p_public_key_x = OCTETSTRING(l, static_cast(v)); + p_public_key_y = OCTETSTRING(l, l + static_cast(v)); + + ::BN_clear_free(H); + ::BN_clear_free(xy); + ::EC_POINT_free(QU); + ::EC_POINT_free(QCA); + + loggers::get_instance().log_msg("security_ecc::reconstruct_public_keys: p_public_key_x=", p_public_key_x); + loggers::get_instance().log_msg("security_ecc::reconstruct_public_keys: p_public_key_y=", p_public_key_y); + loggers::get_instance().log_msg("security_ecc::reconstruct_public_keys: p_public_key_compressed=", p_public_key_compressed); + loggers::get_instance().log_msg("security_ecc::reconstruct_public_keys: p_public_key_compressed_mode=", p_public_key_compressed_mode); + + return 0; +} + const int security_ecc::init() { loggers::get_instance().log(">>> security_ecc::init: %d", static_cast(_elliptic_curve)); @@ -899,6 +1081,9 @@ const int security_ecc::init() { case ec_elliptic_curves::brainpool_p_384_r1: result = ::OBJ_txt2nid("brainpoolP384r1"); break; + case ec_elliptic_curves::sm2_p_256: + result = ::OBJ_txt2nid("sm2"); + break; default: loggers::get_instance().error("security_ecc::init: Unsupported EC elliptic_curve"); } // End of 'switch' statement @@ -915,8 +1100,9 @@ const int security_ecc::init() { ::EC_KEY_set_asn1_flag(_ec_key, OPENSSL_EC_NAMED_CURVE); // Used to save and retrieve keys _ec_group = ::EC_KEY_get0_group(_ec_key); // Get pointer to the EC_GROUP _bn_ctx = ::BN_CTX_new(); + ::BN_CTX_start(_bn_ctx); - loggers::get_instance().log("<<< security_ecc::init: 0"); + //loggers::get_instance().log("<<< security_ecc::init: 0"); return 0; } // End of init @@ -933,28 +1119,14 @@ int security_ecc::bin_to_ec_point(const OCTETSTRING &p_public_key_x, const OCTET ::EC_POINT_bn2point(_ec_group, pubk_bn, *p_ec_point, _bn_ctx); ::BN_clear_free(pubk_bn); - // BIO *bio_out = nullptr; /* stdout */ - // bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); - // BIGNUM *x = BN_new(); - // BIGNUM *y = BN_new(); - - // if (EC_POINT_get_affine_coordinates_GFp(_ec_group, *p_ec_point, x, y, nullptr)) { - // BN_print_fp(stdout, x); - // putc('\n', stdout); - // BN_print_fp(stdout, y); - // putc('\n', stdout); - // } - // BN_free(x); BN_free(y); - return 0; } int security_ecc::public_key_to_bin(OCTETSTRING &p_bin_key) { // ec_key_public_key_to_bin - const EC_GROUP *ec_group = EC_KEY_get0_group(_ec_key); - const EC_POINT *pub = EC_KEY_get0_public_key(_ec_key); - BIGNUM *pub_bn = BN_new(); + const EC_POINT *pub = ::EC_KEY_get0_public_key(_ec_key); + BIGNUM *pub_bn = ::BN_new(); - ::EC_POINT_point2bn(ec_group, pub, POINT_CONVERSION_UNCOMPRESSED, pub_bn, _bn_ctx); + ::EC_POINT_point2bn(_ec_group, pub, POINT_CONVERSION_UNCOMPRESSED, pub_bn, _bn_ctx); p_bin_key = int2oct(0, BN_num_bytes(pub_bn)); ::BN_bn2bin(pub_bn, (unsigned char *)static_cast(p_bin_key)); @@ -963,6 +1135,23 @@ int security_ecc::public_key_to_bin(OCTETSTRING &p_bin_key) { // ec_key_public_k return 0; } +void security_ecc::ec_point_print(const std::string& p_label, const EC_POINT *p_key) { + BIGNUM * x = ::BN_new(); + BIGNUM * y = ::BN_new(); + ::EC_POINT_get_affine_coordinates(_ec_group, p_key, x, y, NULL); + char* sx = ::BN_bn2hex(x); + char* sy = ::BN_bn2hex(y); + loggers::get_instance().log("%sx=%s\ny=%s\n", p_label.c_str(), sx, sy); + free(sx); free(sy); + ::BN_free(x); ::BN_free(y); +} + +void security_ecc::bn_print(const std::string& p_label, const BIGNUM* p_num) { + char* s = ::BN_bn2hex(p_num); + loggers::get_instance().log("%s:%s", p_label.c_str(), s); + free(s); +} + int security_ecc::kdf2(const OCTETSTRING &p_secret_key, const OCTETSTRING &p_salt, const unsigned char p_hash_algorithm, const int p_key_length, OCTETSTRING &p_digest) { loggers::get_instance().log(">>> security_ecc::kdf2"); @@ -1008,3 +1197,42 @@ int security_ecc::kdf2_sha256(const OCTETSTRING &p_secret_key, const OCTETSTRING loggers::get_instance().log_msg("<<< security_ecc::kdf2_sha256: p_secret_key: ", p_digest); return 0; } + +int security_ecc::compute_digest_sm3(const OCTETSTRING &p_data, const OCTETSTRING &p_entl_a, const OCTETSTRING &p_id, OCTETSTRING &p_digest) { + loggers::get_instance().log(">>> security_ecc::compute_digest_sm3"); + loggers::get_instance().log_msg(">>> security_ecc::compute_digest_sm3: ", _pub_key_x); + loggers::get_instance().log_msg(">>> security_ecc::compute_digest_sm3: ", _pub_key_y); + + EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); + if (ctx == nullptr) { + loggers::get_instance().warning("ecurity_ecc::compute_digest_sm3: Failed to create context"); + return -1; + } + ::EVP_DigestInit_ex(ctx, ::EVP_sm3(), NULL); + ::EVP_DigestUpdate(ctx, static_cast(p_entl_a), p_entl_a.lengthof()); + ::EVP_DigestUpdate(ctx, static_cast(p_id), p_id.lengthof()); + ::EVP_DigestUpdate(ctx, _a, sizeof(_a)); + ::EVP_DigestUpdate(ctx, _b, sizeof(_b)); + ::EVP_DigestUpdate(ctx, _xG, sizeof(_xG)); + ::EVP_DigestUpdate(ctx, _yG, sizeof(_yG)); + ::EVP_DigestUpdate(ctx, static_cast(_pub_key_x), _pub_key_x.lengthof()); + ::EVP_DigestUpdate(ctx, static_cast(_pub_key_y), _pub_key_y.lengthof()); + unsigned char digest[32] = { 0x00 }; + ::EVP_DigestFinal_ex(ctx, digest, NULL); + ::EVP_MD_CTX_free(ctx); + + if ((ctx = ::EVP_MD_CTX_new()) == nullptr) { + loggers::get_instance().warning("ecurity_ecc::compute_digest_sm3: Failed to create context"); + return -1; + } + ::EVP_DigestInit_ex(ctx, ::EVP_sm3(), NULL); + ::EVP_DigestUpdate(ctx, digest, sizeof(digest)); + ::EVP_DigestUpdate(ctx, static_cast(p_data), p_data.lengthof()); + ::EVP_DigestFinal_ex(ctx, digest, NULL); + ::EVP_MD_CTX_free(ctx); + + p_digest = OCTETSTRING(sizeof(digest), static_cast(digest)); + + loggers::get_instance().log_msg("<<< security_ecc::compute_digest_sm3: p_secret_key: ", p_digest); + return 0; +} diff --git a/ccsrc/Protocols/Security/security_ecc.hh b/ccsrc/Protocols/Security/security_ecc.hh index 91d7bbbf6e5d0b00665175f892134bd92e4921f6..0d56fae2fcf242cf5f49904c5913b6c89abfaec4 100644 --- a/ccsrc/Protocols/Security/security_ecc.hh +++ b/ccsrc/Protocols/Security/security_ecc.hh @@ -24,7 +24,8 @@ enum class ec_elliptic_curves : unsigned char { // TODO Renamed into ecc_ellipti nist_p_256, /*!< NIST P-256, P-256, primve256v1 */ nist_p_384, /*!< NIST P-384, P-384, secp384r1 */ brainpool_p_256_r1, /*!< Brainpool P256r1 */ - brainpool_p_384_r1 /*!< Brainpool P384r1 */ + brainpool_p_384_r1, /*!< Brainpool P384r1 */ + sm2_p_256 /*!< Chinese SM2 */ }; // End of class ecc_elliptic_curves /*! @@ -36,7 +37,7 @@ enum class ecc_compressed_mode : unsigned char { }; // End of class ecc_compressed_mode /*! - * \enum Supported encryption algorithem + * \enum Supported encryption algorithm */ enum class encryption_algotithm : unsigned char { // TODO Renamed into ecc_encryption_algotithm aes_128_ccm, @@ -50,6 +51,16 @@ enum class encryption_algotithm : unsigned char { // TODO Renamed into ecc_encry * \brief This class implements the generation of a key pair private/public */ class security_ecc { + // FIXME Concatenate _a + _b + _xG + _yG for optimization + const unsigned char _a[32] = { 0x78, 0x79, 0x68, 0xB4, 0xFA, 0x32, 0xC3, 0xFD, 0x24, 0x17, 0x84, 0x2E, 0x73, 0xBB, 0xFE, 0xFF, 0x2F, 0x3C, 0x84, 0x8B, 0x68, 0x31, 0xD7, 0xE0, 0xEC, 0x65, 0x22, 0x8B, 0x39, 0x37, 0xE4, 0x98 }; + /*!< Elliptic curve equation parameters (a) - P1609.2/D13, October 2022 Clause 5.3.1.3 SM2 */ + const unsigned char _b[32] = { 0x63, 0xE4, 0xC6, 0xD3, 0xB2, 0x3B, 0x0C, 0x84, 0x9C, 0xF8, 0x42, 0x41, 0x48, 0x4B, 0xFE, 0x48, 0xF6, 0x1D, 0x59, 0xA5, 0xB1, 0x6B, 0xA0, 0x6E, 0x6E, 0x12, 0xD1, 0xDA, 0x27, 0xC5, 0x24, 0x9A }; + /*!< Elliptic curve equation parameters (b) - P1609.2/D13, October 2022 Clause 5.3.1.3 SM2 */ + const unsigned char _xG[32] = { 0x42, 0x1D, 0xEB, 0xD6, 0x1B, 0x62, 0xEA, 0xB6, 0x74, 0x64, 0x34, 0xEB, 0xC3, 0xCC, 0x31, 0x5E, 0x32, 0x22, 0x0B, 0x3B, 0xAD, 0xD5, 0x0B, 0xDC, 0x4C, 0x4E, 0x6C, 0x14, 0x7F, 0xED, 0xD4, 0x3D }; + /*!< x coordinate of the generating point. - P1609.2/D13, October 2022 Clause 5.3.1.3 SM2 */ + const unsigned char _yG[32] = { 0x06, 0x80, 0x51, 0x2B, 0xCB, 0xB4, 0x2C, 0x07, 0xD4, 0x73, 0x49, 0xD2, 0x15, 0x3B, 0x70, 0xC4, 0xE5, 0xD7, 0xFD, 0xFC, 0xBF, 0xA3, 0x6E, 0xA1, 0xA8, 0x58, 0x41, 0xB9, 0xE4, 0x6E, 0x09, 0xA2 }; + /*!< y coordinate of the generating point. - P1609.2/D13, October 2022 Clause 5.3.1.3 SM2 */ + ec_elliptic_curves _elliptic_curve; /*!< Selected elleptic curve */ encryption_algotithm _encryption_algotithm; /*!< Selected encryption algotithm */ EC_KEY * _ec_key; /*!< EC_KEY reference */ @@ -117,6 +128,17 @@ public: //! \publicsection * \return 0 on success, -1 otherwise */ int sign(const OCTETSTRING &p_data, OCTETSTRING &p_r_sig, OCTETSTRING &p_s_sig); + /*! + * \fn int sign(const OCTETSTRING& p_data, OCTETSTRING& p_r_sig, OCTETSTRING& p_s_sig); + * \brief Signed the data using ECDSA algorithm + * \param[in] p_data The data to be signed + * \param[in] p_entl_a + * \param[in] p_id + * \param[out] p_r_sig Part of the signature + * \param[out] p_s_sig Part of the signature + * \return 0 on success, -1 otherwise + */ + int sign(const OCTETSTRING &p_data, const OCTETSTRING &p_entl_a, const OCTETSTRING &p_id, OCTETSTRING &p_r_sig, OCTETSTRING &p_s_sig); /*! * \fn int sign_verif(const OCTETSTRING& p_data, const OCTETSTRING& p_signature); * \brief Verifiy an ECDSA signature @@ -125,6 +147,16 @@ public: //! \publicsection * \return 0 on success, -1 otherwise */ int sign_verif(const OCTETSTRING &p_data, const OCTETSTRING &p_signature); + /*! + * \fn int sign_verif(const OCTETSTRING& p_data, const OCTETSTRING& p_signature); + * \brief Verifiy an ECDSA signature + * \param[in] p_data The signed data + * \param[in] p_entl_a + * \param[in] p_id + * \param[in] p_signature The signature part, based on r_sig part and s_sig part + * \return 0 on success, -1 otherwise + */ + int sign_verif(const OCTETSTRING &p_data, const OCTETSTRING &p_entl_a, const OCTETSTRING &p_id, const OCTETSTRING &p_signature); /*! * \fn int generate_and_derive_ephemeral_key(const encryption_algotithm p_enc_algorithm, const OCTETSTRING& p_recipients_public_key_x, const OCTETSTRING& @@ -177,17 +209,27 @@ public: //! \publicsection OCTETSTRING &p_enc_message); /*! * \fn int decrypt(const encryption_algotithm p_enc_algorithm, const OCTETSTRING& p_key, const OCTETSTRING& p_nonce, const OCTETSTRING& p_tag, const - * OCTETSTRING& p_enc_message, OCTETSTRING& p_message); \brief Decryption using the specified parameters. \param[in] p_enc_algorithm The algorithm to use for - * the decryption \param[in] p_nonce The algorithm to use for the encryption \param[in] p_tag The algorithm to use for the encryption \param[in] p_enc_message - * The message to be decrypted \param[out] p_message The decrypted message \remark To get the generated symmetric encryption key, uses \see - * symmetric_encryption_key method \remark To get the generated nonce vector, uses \see nonce method \remark To get the generated tag, uses \see tag method + * OCTETSTRING& p_enc_message, OCTETSTRING& p_message); + * \brief Decryption using the specified parameters. + * \param[in] p_enc_algorithm The algorithm to use for + * the decryption + * \param[in] p_nonce The algorithm to use for the encryption + * \param[in] p_tag The algorithm to use for the encryption + * \param[in] p_enc_message + * The message to be decrypted \param[out] p_message The decrypted message + * \remark To get the generated symmetric encryption key, uses + * \see symmetric_encryption_key method \remark To get the generated nonce vector, uses + * \see nonce method \remark To get the generated tag, uses + * \see tag method * \return 0 on success, -1 otherwise */ int decrypt(const encryption_algotithm p_enc_algorithm, const OCTETSTRING &p_symmetric_key, const OCTETSTRING &p_nonce, const OCTETSTRING &p_tag, const OCTETSTRING &p_enc_message, OCTETSTRING &p_message); /*! * \fn int decrypt(const encryption_algotithm p_enc_algorithm, const OCTETSTRING& p_key, const OCTETSTRING& p_nonce, const OCTETSTRING& p_tag, const - * OCTETSTRING& p_enc_message, OCTETSTRING& p_message); \brief Decryption using default parameters. \param[in] p_tag The algorithm to use for the encryption + * OCTETSTRING& p_enc_message, OCTETSTRING& p_message); + * \brief Decryption using default parameters. + * \param[in] p_tag The algorithm to use for the encryption * \param[in] p_enc_message The message to be decrypted * \param[out] p_message The decrypted message * \remark To get the generated symmetric encryption key, uses \see symmetric_encryption_key method @@ -196,6 +238,13 @@ public: //! \publicsection * \return 0 on success, -1 otherwise */ int decrypt(const OCTETSTRING &p_tag, const OCTETSTRING &p_enc_message, OCTETSTRING &p_message); + /*! + * \fn int reconstruct_public_keys(const OCTETSTRING &p_cert_to_be_signed, const OCTETSTRING &p_issuer_public_key_x, const OCTETSTRING &p_issuer_public_key_y, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y, OCTETSTRING &p_public_key_compressed, INTEGER &p_public_key_compressed_mode); + * \brief Reconstruct the public keys of an implicit certificate. + * \remark The instance of security_ecc shall contain the reconstruction key + * \return 0 on success, -1 otherwise + */ + int reconstruct_public_keys(const OCTETSTRING &p_cert_to_be_signed, const OCTETSTRING &p_issuer_public_key_x,const OCTETSTRING &p_issuer_public_key_y, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y, OCTETSTRING &p_public_key_compressed, INTEGER &p_public_key_compressed_mode); inline const OCTETSTRING & private_key() const { return _pri_key; }; inline const OCTETSTRING & public_key_x() const { return _pub_key_x; }; @@ -237,6 +286,13 @@ private: //! \privatesection */ int public_key_to_bin(OCTETSTRING &p_bin_key); + void ec_point_print(const std::string& p_label, const EC_POINT *p_key); + + void bn_print(const std::string& p_label, const BIGNUM* p_num); + int kdf2(const OCTETSTRING &p_secret_key, const OCTETSTRING &p_salt, const unsigned char p_hash_algorithm, const int p_key_length, OCTETSTRING &p_digest); int kdf2_sha256(const OCTETSTRING &p_secret_key, const OCTETSTRING &p_salt, const int p_key_length, OCTETSTRING &p_digest); + + int compute_digest_sm3(const OCTETSTRING &p_data, const OCTETSTRING &p_entl_a, const OCTETSTRING &p_id, OCTETSTRING &p_digest); + }; // End of class security_ecc diff --git a/ccsrc/Protocols/Security/security_services.cc b/ccsrc/Protocols/Security/security_services.cc deleted file mode 100644 index 438493dbe1e83c7d3bdefd69e4b0148ff3fa3142..0000000000000000000000000000000000000000 --- a/ccsrc/Protocols/Security/security_services.cc +++ /dev/null @@ -1,1555 +0,0 @@ -#include - -#include - -#include "security_services.hh" - -using namespace std; // Required for isnan() -#include "etsi_ts103097_certificate_codec.hh" -#include "etsi_ts103097_data_codec.hh" -#include "etsi_ts103097_tobesigned_data_codec.hh" - -#include "security_ecc.hh" -#include "sha256.hh" -#include "sha384.hh" - -#include "base_time.hh" - -#include "params.hh" - -#include "loggers.hh" - -#include "converter.hh" - -security_services *security_services::instance = nullptr; - -security_services::security_services() - : _setup_done{false}, _ec_keys_enc(nullptr), _security_cache(new security_cache), _security_db(nullptr), _last_generation_time(0), - _unknown_certificate(0, nullptr), _requested_certificate(), _latitude(0), _longitude(0), _elevation(0), _geospacial() { - loggers::get_instance().log(">>> security_services::security_services"); - - //_geospacial.load_countries_map("/home/yann/dev/TTF0002_Its/ne-countries-50m.json"); // FIXME Use parameter - -} // End of ctor - -int security_services::setup(params_its &p_params) { // FIXME Rename this method - loggers::get_instance().log(">>> security_services::setup"); - _params = p_params; - _params.log(); - - if (_setup_done) { - loggers::get_instance().warning("security_services::setup: Already done"); - return 0; - } - - // Build the certificate caching - try { - _security_db.reset(new security_db(_params[params_its::sec_db_path])); - if (_security_db.get() == nullptr) { // Memory allocation issue - loggers::get_instance().warning("security_services::setup: _security_db pointer is NULL"); - return -1; - } - _setup_done = true; - } catch (...) { - loggers::get_instance().error("security_services::setup: Filesystem access error, terminate test suite on TTCN-3 error. Please check user name and paths " - "in the test suite configuration file."); - return -1; - } - - // Initialise encryption mechanism - params_its::const_iterator it = _params.find(params_its::cypher); - if (it == _params.cend()) { - _ec_keys_enc.reset(new security_ecc(ec_elliptic_curves::nist_p_256)); - _params.insert(std::pair(params_its::cypher, std::string("NISTP-256"))); - p_params.insert(std::pair(params_its::cypher, std::string("NISTP-256"))); - } else if (it->second.compare("NISTP-256")) { - _ec_keys_enc.reset(new security_ecc(ec_elliptic_curves::nist_p_256)); - } else if (it->second.compare("BP-256")) { - _ec_keys_enc.reset(new security_ecc(ec_elliptic_curves::brainpool_p_256_r1)); - } else { - loggers::get_instance().warning("security_services::setup: Failed to encode ToBeSignedData"); - return -1; - } - - return 0; -} - -int security_services::store_certificate(const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, - const OCTETSTRING &p_public_key_x, const OCTETSTRING &p_public_key_y, const OCTETSTRING &p_public_comp_key, - const INTEGER &p_public_comp_key_mode, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, - const OCTETSTRING &p_hashid8, const OCTETSTRING &p_issuer, const OCTETSTRING &p_private_enc_key, - const OCTETSTRING &p_public_enc_key_x, const OCTETSTRING &p_public_enc_key_y, - const OCTETSTRING &p_public_enc_compressed_key, const INTEGER &p_public_enc_key_compressed_mode) { - loggers::get_instance().log_msg(">>> security_services::store_certificate: ", p_cert_id); - - // Sanity checks - if (_security_db.get() == nullptr) { // Setup not called - loggers::get_instance().warning("security_services::store_certificate: Not initialised"); - return -1; - } - return _security_db.get()->store_certificate(p_cert_id, p_cert, p_private_key, p_public_key_x, p_public_key_y, p_public_comp_key, p_public_comp_key_mode, - p_hash, p_hash_sha_256, p_hashid8, p_issuer, p_private_enc_key, p_public_enc_key_x, p_public_enc_key_y, - p_public_enc_compressed_key, p_public_enc_key_compressed_mode); -} - -int security_services::verify_and_extract_gn_payload(const OCTETSTRING &p_secured_gn_payload, const bool p_verify, - Ieee1609Dot2::Ieee1609Dot2Data &p_ieee_1609dot2_data, OCTETSTRING &p_unsecured_gn_payload, - params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::verify_and_extract_gn_payload: ", p_secured_gn_payload); - - // Sanity checks - if (p_secured_gn_payload.lengthof() == 0) { - return -1; - } - - // Decode the secured message (OER encoding) - etsi_ts103097_data_codec codec; - codec.decode(p_secured_gn_payload, p_ieee_1609dot2_data, &p_params); - // Sanity checks - if (!p_ieee_1609dot2_data.is_bound()) { - loggers::get_instance().warning("security_services::verify_and_extract_gn_payload: Unbound value, discard it"); - return -1; - } - if (p_verify && ((unsigned int)(int)p_ieee_1609dot2_data.protocolVersion() != security_services::ProtocolVersion)) { - loggers::get_instance().warning("security_services::verify_and_extract_gn_payload: Wrong version protocol, discard it"); - return -1; - } - - return process_ieee_1609_dot2_content(p_ieee_1609dot2_data.content(), p_verify, p_unsecured_gn_payload, p_params); -} // End of method verify_and_extract_gn_payload - -int security_services::process_ieee_1609_dot2_content(const Ieee1609Dot2::Ieee1609Dot2Content &p_ieee_1609_dot2_content, const bool p_verify, - OCTETSTRING &p_unsecured_payload, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::process_ieee_1609_dot2_content: ", p_ieee_1609_dot2_content); - - if (p_ieee_1609_dot2_content.ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_unsecuredData)) { // Unsecured packet, End of recursivity - p_unsecured_payload = p_ieee_1609_dot2_content.unsecuredData(); - } else if (p_ieee_1609_dot2_content.ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_signedData)) { - const Ieee1609Dot2::SignedData &signedData = p_ieee_1609_dot2_content.signedData(); - if (process_ieee_1609_dot2_signed_data(signedData, p_verify, p_unsecured_payload, p_params) != 0) { - if (p_verify) { - return -1; - } - } - } else if (p_ieee_1609_dot2_content.ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_encryptedData)) { - const Ieee1609Dot2::EncryptedData &encrypted_data = p_ieee_1609_dot2_content.encryptedData(); - OCTETSTRING signed_payload; - if (process_ieee_1609_dot2_encrypted_data(encrypted_data, p_verify, signed_payload, p_params) != 0) { - return -1; - } - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_content: Decrypted payload: ", signed_payload); - Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data; // TODO Check if it could be reused - if (verify_and_extract_gn_payload(signed_payload, p_verify, ieee_1609dot2_data, p_unsecured_payload, p_params) != 0) { - if (p_verify) { - return -1; - } - } - } else if (p_ieee_1609_dot2_content.ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_signedCertificateRequest)) { - // Reset certificate timer - loggers::get_instance().log("security_services::process_ieee_1609_dot2_content: Set Certificate re-transmission flag and reset timer"); - _last_generation_time = 0; - return 0; - } else { // Shall never be reached - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_content: Undefined IEEE 1609.2 Content, discard it"); - if (p_verify) { - return -1; - } - } - - loggers::get_instance().log_msg("<<< security_services::process_ieee_1609_dot2_content: ", p_unsecured_payload); - return 0; -} // End of method process_ieee_1609_dot2_content - -int security_services::process_ieee_1609_dot2_signed_data(const Ieee1609Dot2::SignedData &p_signed_data, const bool p_verify, OCTETSTRING &p_unsecured_payload, - params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::process_ieee_1609_dot2_signed_data: ", p_signed_data); - - // Check the headerInfo content - const Ieee1609Dot2::HeaderInfo &header_info = p_signed_data.tbsData().headerInfo(); - p_params[params_its::its_aid] = std::to_string(header_info.psid().get_long_long_val()); - if (!header_info.generationTime().is_present()) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: HeaderInfo::GenerationTime field is missing"); - if (p_verify) { - return -1; - } - } else { - const OPTIONAL &v = dynamic_cast &>(header_info.generationTime()); // in microsecond - unsigned long long gt = ((INTEGER &)(*v.get_opt_value())).get_long_long_val(); - // Get current time timestamp - unsigned long long us = base_time::get_instance().get_its_current_time_us(); // in microsecond - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: generation time check %ld / %ld, delta = %f", gt, us, - abs((double)gt - (double)us)); - if (abs((double)gt - (double)us) >= 5000000.0) { // TODO Use a params for generation_time_epsilon, 5s differences - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Invalid generation time, discard it"); - if (p_verify) { - return -1; - } - } - } - - // Check p2pcdLearningRequest keys if present - if (header_info.p2pcdLearningRequest().is_present()) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: p2pcdLearningRequest not supported yet"); - // TODO Not supported by C-ITS Protocol - } - - // Check missingCrlIdentifier keys if present - if (header_info.missingCrlIdentifier().is_present()) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: missingCrlIdentifier not supported yet"); - // TODO Not supported by C-ITS Protocol - } - - // Check encryption keys if present - if (header_info.encryptionKey().is_present()) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: encryptionKey not supported yet"); - // TODO Not supported by C-ITS Protocol - } - - // Check request certificate - if (header_info.inlineP2pcdRequest().is_present()) { - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: inlineP2pcdRequest: ", header_info.inlineP2pcdRequest()); - const Ieee1609Dot2BaseTypes::SequenceOfHashedId3 &s = - static_cast(*header_info.inlineP2pcdRequest().get_opt_value()); - _requested_certificate.clear(); - for (int i = 0; i < s.lengthof(); i++) { - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: Add requested certificate= ", s[i]); - _requested_certificate.push_back(s[i]); - } // End of 'for' statement - } - - // Check requested certificate - if (header_info.requestedCertificate().is_present()) { - Ieee1609Dot2::CertificateBase requested_cert = header_info.requestedCertificate(); - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: ", requested_cert); - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: requestedCertificate not supported yet"); - // TODO Not supported by C-ITS Protocol - } - - // Check and extract unsecured payload - if (p_signed_data.tbsData().payload().data().is_present()) { - // Check protocol version - const OPTIONAL &v = - dynamic_cast &>(p_signed_data.tbsData().payload().data()); - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: SignedDataPayload.data=", v); - const Ieee1609Dot2::Ieee1609Dot2Data &ieee_1609dot2_data = static_cast(*v.get_opt_value()); - if (p_verify && ((unsigned int)(int)ieee_1609dot2_data.protocolVersion() != security_services::ProtocolVersion)) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Wrong version protocol, discard it"); - if (p_verify) { - return -1; - } - } - if (process_ieee_1609_dot2_content(ieee_1609dot2_data.content(), p_verify, p_unsecured_payload, p_params) != 0) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Failed to process SignedData, discard it"); - if (p_verify) { - return -1; - } - } - } else if (p_signed_data.tbsData().payload().extDataHash().is_present()) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Unsupported extDataHash, discard it"); - if (p_verify) { - return -1; - } - } else { // Shall not be reached - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Unsupported SignedDataPayload, discard it"); - return -1; - } - - // Encode the ToBeSignedData - etsi_ts103097_tobesigned_data_codec tbs_data_codec; - OCTETSTRING os; - tbs_data_codec.encode(p_signed_data.tbsData(), os); - if (os.lengthof() == 0) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Failed to encode ToBeSignedData"); - return -1; - } - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: encoded tbs_data=", os); - // Calculate the hash according to the hashId - OCTETSTRING hashed_data; - if (p_signed_data.hashId() == Ieee1609Dot2BaseTypes::HashAlgorithm::sha256) { - hash_sha256(os, hashed_data); - } else { - hash_sha384(os, hashed_data); - } - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: hashed_data=", hashed_data); - // Retrieve certificate identifier - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: signer=", p_signed_data.signer()); - std::string certificate_id; - int result = -1; - if (p_signed_data.signer().ischosen(Ieee1609Dot2::SignerIdentifier::ALT_digest)) { - // Retrieve the certificate identifier from digest - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: Retrieve the certificate identifier from digest"); - result = _security_db.get()->get_certificate_id(p_signed_data.signer().digest(), certificate_id); - if (result == -1) { - // Check in the cache - if (_security_cache.get()->get_certificate_id(p_signed_data.signer().digest(), certificate_id) == -1) { - // Unknown certificate, request it - const OCTETSTRING &os = p_signed_data.signer().digest(); - _unknown_certificate = OCTETSTRING(3, static_cast(os) + os.lengthof() - 3); - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Unknown certificate, request it"); - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: HashedId3: ", _unknown_certificate); - } - // Reset certificate timer - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: Set Certificate re-transmission flag and reset timer"); - _last_generation_time = 0; - - return -1; - } - } else if (p_signed_data.signer().ischosen(Ieee1609Dot2::SignerIdentifier::ALT_certificate) && (p_signed_data.signer().certificate().size_of() != 0)) { - // Extract the certificates - std::vector certificate_ids; - for (int i = 0; i < p_signed_data.signer().certificate().size_of(); i++) { - Ieee1609Dot2::CertificateBase cert = p_signed_data.signer().certificate()[i]; - // Retrieve ssps - OPTIONAL &v = cert.toBeSigned().appPermissions(); - if (v.is_present()) { - Ieee1609Dot2BaseTypes::SequenceOfPsidSsp psid_ssps = static_cast(*v.get_opt_value()); - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: psid_ssps size: %d", psid_ssps.lengthof()); - for (int i = 0; i < psid_ssps.lengthof(); i++) { - const Ieee1609Dot2BaseTypes::PsidSsp &psid_ssp = psid_ssps[i]; - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: Processing psid_ssp ", psid_ssp); - const OPTIONAL &s = psid_ssp.ssp(); - if (s.is_present()) { - const Ieee1609Dot2BaseTypes::ServiceSpecificPermissions &ssp = static_cast(s); - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: Processing ssp ", ssp); - params_its::const_iterator it = p_params.find(std::to_string(psid_ssp.psid())); - if (it == p_params.cend()) { - OCTETSTRING os; - if (ssp.ischosen(Ieee1609Dot2BaseTypes::ServiceSpecificPermissions::ALT_opaque)) { - os = ssp.opaque(); - } else { - os = ssp.bitmapSsp(); - } - p_params[params_its::ssp] = std::string(static_cast(oct2str(os))); - } - } - } // End of 'for' statement - } - - std::string certificate_id; - if (extract_and_store_certificate(cert, certificate_id) != 0) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Failed to store certificate"); - if (p_verify) { - return -1; - } - } - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: certificate_id: '%s'", certificate_id.c_str()); - certificate_ids.push_back(certificate_id); - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: certificate_ids size: %d", certificate_ids.size()); - } // End of 'for' statement - certificate_id = certificate_ids[0]; - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: After extract_and_store_certificate, certificate_id: '%s'", - certificate_id.c_str()); - } else { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Unsupported SignerIdentifier"); - return -1; - } - loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: certificate id = '%s'", certificate_id.c_str()); - // Verify the signature of the ToBeSignedData - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_signed_data: signature=", p_signed_data.signature__()); - result = -1; - if (p_signed_data.signature__().ischosen(Ieee1609Dot2BaseTypes::Signature::ALT_ecdsaNistP256Signature)) { - result = verify_sign_ecdsa_nistp256(hashed_data, p_signed_data.signature__(), certificate_id, p_params); - } else if (p_signed_data.signature__().ischosen(Ieee1609Dot2BaseTypes::Signature::ALT_ecdsaBrainpoolP256r1Signature)) { - result = verify_sign_ecdsa_brainpoolp256r1(hashed_data, p_signed_data.signature__(), certificate_id, p_params); - } else if (p_signed_data.signature__().ischosen(Ieee1609Dot2BaseTypes::Signature::ALT_ecdsaBrainpoolP384r1Signature)) { - result = verify_sign_ecdsa_brainpoolp384r1(hashed_data, p_signed_data.signature__(), certificate_id, p_params); - } else { - // TODO - loggers::get_instance().error("security_services::process_ieee_1609_dot2_signed_data: TODO"); - } - if (result != 0) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Failed to verify signature"); - return -1; - } - - loggers::get_instance().log_msg("<<< security_services::process_ieee_1609_dot2_signed_data: ", p_unsecured_payload); - return 0; -} // End of method process_ieee_1609_dot2_signed_data - -int security_services::process_ieee_1609_dot2_encrypted_data(const Ieee1609Dot2::EncryptedData &p_encrypted_data, const bool p_verify, - OCTETSTRING &p_unsecured_payload, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::process_ieee_1609_dot2_encrypted_data: ", p_encrypted_data); - - // 1. Retrieve the RecipientId - const Ieee1609Dot2::RecipientInfo & r = p_encrypted_data.recipients()[0]; // TODO Add multiple support of recipients - const Ieee1609Dot2BaseTypes::EciesP256EncryptedKey *ecies = nullptr; // TODO Use smart pointer - const OCTETSTRING * recipient_id = nullptr; // TODO Use smart pointer - if (r.ischosen(Ieee1609Dot2::RecipientInfo::ALT_certRecipInfo)) { - recipient_id = &r.certRecipInfo().recipientId(); - if (r.certRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_eciesNistP256)) { - ecies = &r.certRecipInfo().encKey().eciesNistP256(); - } else if (r.certRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_eciesBrainpoolP256r1)) { - ecies = &r.certRecipInfo().encKey().eciesBrainpoolP256r1(); - } else { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Unsupported encryption algorithm"); - return -1; - } - } else if (r.ischosen(Ieee1609Dot2::RecipientInfo::ALT_signedDataRecipInfo)) { - recipient_id = &r.signedDataRecipInfo().recipientId(); - if (r.signedDataRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_eciesNistP256)) { - ecies = &r.signedDataRecipInfo().encKey().eciesNistP256(); - } else if (r.signedDataRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_eciesBrainpoolP256r1)) { - ecies = &r.signedDataRecipInfo().encKey().eciesBrainpoolP256r1(); - } else { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Unsupported encryption algorithm"); - return -1; - } - } else { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Unsupported RecipientInfo variant"); - return -1; - } - if (!p_encrypted_data.ciphertext().ischosen(Ieee1609Dot2::SymmetricCiphertext::ALT_aes128ccm)) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Unsupported AES 128 algorithm"); - return -1; - } - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_encrypted_data: RecipientId= ", *recipient_id); - - // 2. Retrieve the certificate if present - std::string certificate_id; - OCTETSTRING p_enc_key; // The private encryption key - if (_security_db.get()->get_certificate_id(*recipient_id, certificate_id) == -1) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Unknown certificate"); - // Check if RecipientId is the hashed_id8 of the symetric AES keys - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_encrypted_data: AES Symmetric Keys= ", ecies->c()); - OCTETSTRING hashed_data; - hash_sha256(ecies->c(), hashed_data); - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_encrypted_data: Hash (AES Symmetric Keys)= ", hashed_data); - if (substr(hashed_data, hashed_data.lengthof() - 8, 8) != *recipient_id) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: RecipientId does not match HashedId8 of the symmetric key"); - return -1; - } else { - if (_security_db.get()->get_private_enc_key(p_params[params_its::certificate], p_enc_key) == -1) { - loggers::get_instance().warning( - "security_services::process_ieee_1609_dot2_encrypted_data: Failed to retrieve private encryption key for certificate %s", - p_params[params_its::certificate].c_str()); - return -1; - } - } - } else { - if (_security_db.get()->get_private_enc_key(certificate_id, p_enc_key) == -1) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Failed to retrieve private encryption key"); - return -1; - } - } - - // 3. Generate the shared secret value based on recipient's public ephemeral keys will be required - int result; - security_ecc ec(ec_elliptic_curves::nist_p_256, p_enc_key); - if (ecies->v().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { - result = ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ecies->v().uncompressedP256().x(), ecies->v().uncompressedP256().y(), - ecies->c(), p_encrypted_data.ciphertext().aes128ccm().nonce(), ecies->t(), OCTETSTRING(0, nullptr)); - } else if (ecies->v().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { - security_ecc ec_comp(ec_elliptic_curves::nist_p_256, ecies->v().compressed__y__0(), ecc_compressed_mode::compressed_y_0); - result = ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), ecies->c(), - p_encrypted_data.ciphertext().aes128ccm().nonce(), ecies->t(), OCTETSTRING(0, nullptr)); - } else if (ecies->v().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { - security_ecc ec_comp(ec_elliptic_curves::nist_p_256, ecies->v().compressed__y__1(), ecc_compressed_mode::compressed_y_1); - result = ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), ecies->c(), - p_encrypted_data.ciphertext().aes128ccm().nonce(), ecies->t(), OCTETSTRING(0, nullptr)); - } else { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Failed to decode Decrypt Ieee1609Dot2Data-Encrypted"); - return -1; - } - if (result == -1) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Failed to generate shared secret"); - return -1; - } - // 4. Decrypt the message - OCTETSTRING enc_message(p_encrypted_data.ciphertext().aes128ccm().ccmCiphertext().lengthof() - ec.tag().lengthof(), - static_cast(p_encrypted_data.ciphertext().aes128ccm().ccmCiphertext())); - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_encrypted_data: enc_message: ", enc_message); - OCTETSTRING tag(ec.tag().lengthof(), enc_message.lengthof() + static_cast(p_encrypted_data.ciphertext().aes128ccm().ccmCiphertext())); - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_encrypted_data: tag: ", tag); - if (ec.decrypt(tag, enc_message, p_unsecured_payload) == -1) { - loggers::get_instance().warning("security_services::process_ieee_1609_dot2_encrypted_data: Failed to generate shared secret"); - return -1; - } - loggers::get_instance().log_msg("security_services::process_ieee_1609_dot2_encrypted_data: ", p_unsecured_payload); - - return 0; -} // End of method process_ieee_1609_dot2_encrypted_data - -int security_services::secure_gn_payload(const OCTETSTRING &p_unsecured_gn_payload, OCTETSTRING &p_secured_gn_payload, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::secure_gn_payload: ", p_unsecured_gn_payload); - p_params.log(); - - OCTETSTRING signed_payload; - if (sign_payload(p_unsecured_gn_payload, signed_payload, p_params) != 0) { - p_secured_gn_payload = p_unsecured_gn_payload; - loggers::get_instance().warning("security_services::secure_gn_payload: Failed to signed payload"); - return -1; - } - - if (_params[params_its::encrypted_mode].compare("1") == 0) { - if (encrypt_gn_payload(signed_payload, p_secured_gn_payload, p_params) != 0) { - p_secured_gn_payload = signed_payload; - loggers::get_instance().warning("security_services::secure_gn_payload: Failed to encrypt payload"); - return -1; - } - } else { // No encryption required - loggers::get_instance().log("security_services::secure_gn_payload: Encryption mode not set"); - p_secured_gn_payload = signed_payload; - } - - return 0; -} - -int security_services::sign_payload(const OCTETSTRING &p_unsecured_gn_payload, OCTETSTRING &p_signed_gn_payload, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::sign_payload: ", p_unsecured_gn_payload); - - // Set unsecured data - Ieee1609Dot2::Ieee1609Dot2Content unsecured_data_content; - unsecured_data_content.unsecuredData() = p_unsecured_gn_payload; - Ieee1609Dot2::Ieee1609Dot2Data unsecured_data(ProtocolVersion, unsecured_data_content); - // Set hash algorithm - Ieee1609Dot2BaseTypes::HashAlgorithm hashId(Ieee1609Dot2BaseTypes::HashAlgorithm::sha256); - if (p_params[params_its::hash].compare("SHA-384") == 0) { - hashId = Ieee1609Dot2BaseTypes::HashAlgorithm::sha384; - } - // Set SignedDataPayload - Ieee1609Dot2::SignedDataPayload payload; - payload.data() = unsecured_data; - payload.extDataHash().set_to_omit(); - Ieee1609Dot2::HeaderInfo header_info; - // Set secured field according to the payload! - header_info.psid() = converter::get_instance().string_to_int(p_params[params_its::its_aid]); - header_info.expiryTime().set_to_omit(); - // Force certificate? - boolean force_certificate = false; - params_its::const_iterator it = p_params.find(params_its::force_certificate); - if (it != p_params.cend()) { - force_certificate = true; - } - if (p_params[params_its::its_aid].compare("37") == 0) { // Only used by AtsRSUSimulator to add location header - // Mandatory for DENM payload - OPTIONAL location(Ieee1609Dot2BaseTypes::ThreeDLocation(_latitude, _longitude, _elevation)); - header_info.generationLocation() = location; - loggers::get_instance().log_msg("security_services::sign_payload: generationLocation: ", header_info.generationLocation()); - } else { - header_info.generationLocation().set_to_omit(); - } - header_info.p2pcdLearningRequest().set_to_omit(); - header_info.missingCrlIdentifier().set_to_omit(); - if (_params[params_its::encrypted_mode].compare("1") == 0) { - // TODO Set the encrytion key. Not supported yet, need to clarify mechanism, see IEEE Std 1609.2-20XX Clause 6.3.9 HeaderInfo - header_info.encryptionKey().set_to_omit(); - } else { - header_info.encryptionKey().set_to_omit(); - } - it = p_params.find(params_its::payload_type); - if (it != p_params.cend()) { - loggers::get_instance().log("security_services::sign_payload: Payload type: %s", it->second.c_str()); - if (it->second.compare("1") == 0) { // DENM - OPTIONAL location(Ieee1609Dot2BaseTypes::ThreeDLocation(_latitude, _longitude, _elevation)); - loggers::get_instance().log_msg("security_services::sign_payload: generationLocation: ", location); - header_info.generationLocation() = location; - loggers::get_instance().log_msg("security_services::sign_payload: generationLocation: ", header_info.generationLocation()); - } else if (it->second.compare("2") == 0) { // CAM - // Noting to do - } else { - // Noting to do - } - } else { // Process it as a GeoNetworking payload - loggers::get_instance().log("security_services::sign_payload: Payload type not set"); - // Noting to do - } - unsigned long long us = base_time::get_instance().get_its_current_time_us(); - loggers::get_instance().log("security_services::sign_payload: HeaderInfo timestamp: %ld", us); - INTEGER i; - i.set_long_long_val(us); - header_info.generationTime() = OPTIONAL(i); - loggers::get_instance().log("security_services::sign_payload: Final HeaderInfo timestamp: %ld", us); - // Check if a certificate shall be requested - if (_unknown_certificate.lengthof() == 3) { // HashedId3 of a requested certificate - Ieee1609Dot2BaseTypes::SequenceOfHashedId3 s; - s[0] = _unknown_certificate; - header_info.inlineP2pcdRequest() = OPTIONAL(s); - _unknown_certificate = OCTETSTRING(0, nullptr); - } else { - header_info.inlineP2pcdRequest().set_to_omit(); - } - // Check if a certificate shall be provided - if (_requested_certificate.size() != 0) { - Ieee1609Dot2::CertificateBase c; - const Ieee1609Dot2BaseTypes::HashedId3 &hashed_id3 = _requested_certificate[0]; - _security_db->get_certificate(hashed_id3, c); - header_info.requestedCertificate() = OPTIONAL(c); - } else { - header_info.requestedCertificate().set_to_omit(); - } - header_info.pduFunctionalType().set_to_omit(); - header_info.contributedExtensions().set_to_omit(); - - Ieee1609Dot2::ToBeSignedData tbs_data; - tbs_data.payload() = payload; - tbs_data.headerInfo() = header_info; - loggers::get_instance().log_msg("security_services::sign_payload: tbs_data=", tbs_data); - // Sign the ToBeSignedData data structure - Ieee1609Dot2BaseTypes::Signature signature; - if (sign_tbs_data(tbs_data, hashId, signature, p_params) != 0) { - loggers::get_instance().warning("security_services::sign_payload: Failed to secure payload"); - return -1; - } - Ieee1609Dot2::SignerIdentifier signer; - loggers::get_instance().log("security_services::sign_payload: us = %ld - _last_generation_time = %ld - us - _last_generation_time = %ld", us, - _last_generation_time, us - _last_generation_time); - std::string certificate_id = p_params[params_its::certificate]; - loggers::get_instance().log("security_services::sign_payload: certificate_id = %s", certificate_id.c_str()); - if (((unsigned int)(us - _last_generation_time) >= 1000000 * 0.95) || force_certificate) { // Need to add certificate every 1s - loggers::get_instance().log("security_services::sign_payload: Need to add certificate"); - Ieee1609Dot2::CertificateBase cert; - if (_security_db->get_certificate(certificate_id, cert) != 0) { - loggers::get_instance().warning("security_services:sign_payload: Failed to secure payload"); - return -1; - } - loggers::get_instance().log_msg("security_services::sign_payload: cert= ", cert); - Ieee1609Dot2::SequenceOfCertificate sequenceOfCertificate; - sequenceOfCertificate[0] = cert; - signer.certificate() = sequenceOfCertificate; - // Reset send certificate timer - _last_generation_time = us; - loggers::get_instance().log("security_services::sign_payload: Reset send certificate timer, signer= ", signer); - } else { - loggers::get_instance().log("security_services::sign_payload: Add digest"); - OCTETSTRING digest; - if (_security_db->get_hashed_id(certificate_id, digest) != 0) { - loggers::get_instance().warning("security_services::sign_payload: Failed to secure payload"); - return -1; - } - signer.digest() = digest; - } - Ieee1609Dot2::SignedData signed_data(hashId, tbs_data, signer, signature); - loggers::get_instance().log_msg("security_services::sign_payload: signed_data=", signed_data); - Ieee1609Dot2::Ieee1609Dot2Content ieee_dot2_content; - ieee_dot2_content.signedData() = signed_data; - Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data(security_services::ProtocolVersion, ieee_dot2_content); - loggers::get_instance().log_msg("security_services::sign_payload: ieee_1609dot2_data=", ieee_1609dot2_data); - etsi_ts103097_data_codec codec; - codec.encode(ieee_1609dot2_data, p_signed_gn_payload); - if (!p_signed_gn_payload.is_bound()) { - loggers::get_instance().warning("security_services::sign_payload: Failed to encode Ieee1609Dot2Data"); - return -1; - } - - return 0; -} - -int security_services::encrypt_gn_payload(const OCTETSTRING &p_unsecured_gn_payload, OCTETSTRING &p_enc_gn_payload, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::encrypt_gn_payload: ", p_unsecured_gn_payload); - - // Sanity checks - if (_ec_keys_enc.get() == nullptr) { - loggers::get_instance().warning("security_services::encrypt_gn_payload: Encryption not initialised"); - return -1; - } - params_its::const_iterator it = p_params.find(params_its::peer_certificate); - if (it == p_params.cend()) { - loggers::get_instance().warning("security_services::encrypt_gn_payload: Encryption impossible without a peer_certificte indication in parameters"); - return -1; - } - std::string certificate_id = it->second; - loggers::get_instance().log("security_services::encrypt_gn_payload: Peer CertificateId=%s", certificate_id.c_str()); - - // 1. Retrieve recipient's public keys - OCTETSTRING r_public_key_x; - OCTETSTRING r_public_key_y; - if (_security_db.get()->get_public_enc_keys(certificate_id, r_public_key_x, r_public_key_y) == -1) { - loggers::get_instance().warning("security_services::encrypt_gn_payload: Failed to retrieve recipient's public keys"); - // TODO Setup request certificate mechanism - return -1; - } - loggers::get_instance().log_msg("security_services::encrypt_gn_payload: r_public_key_x=", r_public_key_x); - loggers::get_instance().log_msg("security_services::encrypt_gn_payload: r_public_key_y=", r_public_key_y); - - // 2. Generate new Private/Public ephemeral keys - if (_ec_keys_enc.get()->generate() == -1) { - loggers::get_instance().warning("security_services::encrypt_gn_payload: Failed to generate ephemeral keys"); - return -1; - } - - // 3. Generate and derive shared secret - if (_ec_keys_enc.get()->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, r_public_key_x, r_public_key_y, OCTETSTRING(0, nullptr)) == -1) { - loggers::get_instance().warning("security_services::encrypt_gn_payload: Failed to generate and derive secret key"); - return -1; - } - - // 4. Buil curve data structure in canonical form - Ieee1609Dot2BaseTypes::EccP256CurvePoint eccP256CurvePoint; - if (_ec_keys_enc.get()->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) { - eccP256CurvePoint.compressed__y__0() = _ec_keys_enc.get()->public_key_compressed(); - } else if (_ec_keys_enc.get()->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_1) { - eccP256CurvePoint.compressed__y__1() = _ec_keys_enc.get()->public_key_compressed(); - } else { - eccP256CurvePoint.uncompressedP256().x() = _ec_keys_enc.get()->public_key_x(); - eccP256CurvePoint.uncompressedP256().y() = _ec_keys_enc.get()->public_key_y(); - } - Ieee1609Dot2BaseTypes::EciesP256EncryptedKey ecies_key(eccP256CurvePoint, _ec_keys_enc.get()->encrypted_symmetric_key(), _ec_keys_enc.get()->tag()); - loggers::get_instance().log_msg("security_services::encrypt_gn_payload: ecies_key=", ecies_key); - - // 5. AES-128 encryption of the data - OCTETSTRING enc_message; - if (_ec_keys_enc.get()->encrypt(encryption_algotithm::aes_128_ccm, _ec_keys_enc.get()->symmetric_encryption_key(), _ec_keys_enc.get()->nonce(), - p_unsecured_gn_payload, enc_message) == -1) { - loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to encrypt message"); - return -1; - } - OCTETSTRING nonce = _ec_keys_enc.get()->nonce(); - OCTETSTRING tag = _ec_keys_enc.get()->tag(); - Ieee1609Dot2::AesCcmCiphertext aes_128_ccm(nonce, enc_message + tag); // Add tag at the end of the ciphered text - // 6. Build SymmetricCiphertext - Ieee1609Dot2::SymmetricCiphertext cipher_text; - cipher_text.aes128ccm() = aes_128_ccm; - loggers::get_instance().log_msg("security_services::encrypt_gn_payload: aes_128_ccm=", cipher_text); - - // 7. Build the recipient_id - OCTETSTRING recipient_id; - _security_db.get()->get_hashed_id(certificate_id, recipient_id); // SHA-256 of the certificate which contain the recipient's public keys - - // 8. Build the encryption data - Ieee1609Dot2::EncryptedDataEncryptionKey enc_data_key; - if (_params[params_its::cypher].compare("NISTP-256") == 0) { - enc_data_key.eciesNistP256() = ecies_key; - } else if (_params[params_its::cypher].compare("BP-256") == 0) { - enc_data_key.eciesBrainpoolP256r1() = ecies_key; - } - loggers::get_instance().log_msg("security_services::encrypt_gn_payload: enc_data_key=", enc_data_key); - - // 9. Finalise the encryption - Ieee1609Dot2::PKRecipientInfo cert_recipient_info(recipient_id, enc_data_key); - Ieee1609Dot2::RecipientInfo recipient_info; - recipient_info.certRecipInfo() = cert_recipient_info; - Ieee1609Dot2::SequenceOfRecipientInfo recipients; - recipients[0] = recipient_info; - Ieee1609Dot2::EncryptedData encrypted_data(recipients, cipher_text); - loggers::get_instance().log_msg("security_services::encrypt_gn_payload: encrypted_data=", encrypted_data); - - // 10. Encode it - Ieee1609Dot2::Ieee1609Dot2Content ieee_dot2_content; - ieee_dot2_content.encryptedData() = encrypted_data; - Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data(security_services::ProtocolVersion, ieee_dot2_content); - loggers::get_instance().log_msg("security_services::encrypt_gn_payload: ieee_1609dot2_data=", ieee_1609dot2_data); - etsi_ts103097_data_codec codec; - codec.encode(ieee_1609dot2_data, p_enc_gn_payload); - if (!p_enc_gn_payload.is_bound()) { - loggers::get_instance().warning("security_services::encrypt_gn_payload: Failed to encode Ieee1609Dot2Data"); - return -1; - } - loggers::get_instance().log_msg("security_services::encrypt_gn_payload: Encoded ieee_1609dot2_data=", p_enc_gn_payload); - - return 0; -} - -int security_services::decrypt_gn_payload(const OCTETSTRING &p_enc_gn_payload, OCTETSTRING &p_unsecured_gn_payload, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::decrypt_gn_payload: ", p_enc_gn_payload); - - // Sanity checks - if (_ec_keys_enc.get() == nullptr) { - loggers::get_instance().warning("security_services::decrypt_gn_payload: Encryption not initialised"); - return -1; - } - - // 1. Decode the IEEE 1609dot2Data-Encrypted - Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data; - etsi_ts103097_data_codec codec; - codec.decode(p_enc_gn_payload, ieee_1609dot2_data); - if (!ieee_1609dot2_data.is_bound()) { - loggers::get_instance().warning("security_services::decrypt_gn_payload: Failed to decode Ieee1609Dot2Data-Encrypted"); - return -1; - } - loggers::get_instance().log_msg("security_services::decrypt_gn_payload: Ieee1609Dot2Data-Encrypted=", ieee_1609dot2_data); - - if (!ieee_1609dot2_data.content().ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_encryptedData)) { - loggers::get_instance().warning("security_services::decrypt_gn_payload: Failed to decode Decrypt Ieee1609Dot2Data-Encrypted"); - return -1; - } - if (process_ieee_1609_dot2_encrypted_data(ieee_1609dot2_data.content().encryptedData(), true, p_unsecured_gn_payload, p_params) == -1) { - loggers::get_instance().warning("security_services::decrypt_gn_payload: Failed to decode Decrypt Ieee1609Dot2Data-Encrypted"); - return -1; - } - loggers::get_instance().log_msg("security_services::decrypt_gn_payload: Encoded ieee_1609dot2_data=", p_unsecured_gn_payload); - - return 0; -} - -/*int security_services::sign_tbs_data(const Ieee1609Dot2::ToBeSignedData &p_tbs_data, const Ieee1609Dot2BaseTypes::HashAlgorithm &p_hashAlgorithm, - const OCTETSTRING &p_private_key, Ieee1609Dot2BaseTypes::Signature &p_signature, - params_its &p_params) { // TODO Refine function - loggers::get_instance().log_msg(">>> security_services::sign_tbs_data: ", p_tbs_data); - - // Encode the ToBeSignedData - etsi_ts103097_tobesigned_data_codec tbs_data_codec; - OCTETSTRING os; - tbs_data_codec.encode(p_tbs_data, os); - if (os.lengthof() == 0) { - loggers::get_instance().warning("security_services::sign_tbs_data: Failed to encode ToBeSignedData"); - return -1; - } - loggers::get_instance().log_msg("security_services::sign_tbs_data: encoded tbs_data=", os); - // Hash ToBeSignedData - OCTETSTRING hashed_data; - OCTETSTRING hash_issuer; - if (p_hashAlgorithm == Ieee1609Dot2BaseTypes::HashAlgorithm::sha256) { - sha256 hash; - hash.generate(os, hashed_data); - hash_issuer = hash.get_sha256_empty_string(); - } else { - sha384 hash; - hash.generate(os, hashed_data); - hash_issuer = hash.get_sha384_empty_string(); - } - loggers::get_instance().log_msg("security_services::sign_tbs_data: encoded hashed_data=", hashed_data); - loggers::get_instance().log_msg("security_services::sign_tbs_data: encoded hashed_issuer=", hash_issuer); - // Sign ToBeSignedData - loggers::get_instance().log("security_services::sign_tbs_data: encoded params_its::signature = '%s'", - p_params[params_its::signature].c_str()); // TODO this parameter is useless, use content of the certificate - loggers::get_instance().log("security_services::sign_tbs_data: encoded params_its::certificate = '%s'", p_params[params_its::certificate].c_str()); - if (p_params[params_its::signature].compare("NISTP-256") == 0) { - // Hash ( Hash (Data input) || Hash ("") ) - OCTETSTRING os = hashed_data + hash_issuer; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::sign_tbs_data: hash: ", os); - OCTETSTRING hashed_data; - hash_sha256(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - security_ecc k(ec_elliptic_curves::nist_p_256, p_private_key); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashed_data, r_sig, s_sig) != 0) { - loggers::get_instance().warning("security_services::sign_tbs_data: Failed to sign payload"); - return -1; - } - Ieee1609Dot2BaseTypes::EccP256CurvePoint ep; - ep.x__only() = r_sig; - p_signature.ecdsaNistP256Signature() = Ieee1609Dot2BaseTypes::EcdsaP256Signature(ep, s_sig); - loggers::get_instance().log_msg("security_services::sign_tbs_data: signature=", p_signature); - } // TODO To be done - - return 0; -}*/ - -int security_services::sign_tbs_data(const Ieee1609Dot2::ToBeSignedData &p_tbs_data, const Ieee1609Dot2BaseTypes::HashAlgorithm &p_hashAlgorithm, - Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::sign_tbs_data: ", p_tbs_data); - - // Get certificate - loggers::get_instance().log("security_services::sign_tbs_data: encoded params_its::certificate = '%s'", p_params[params_its::certificate].c_str()); - Ieee1609Dot2::CertificateBase decoded_certificate; - // Set signature type - _security_db.get()->get_certificate(p_params[params_its::certificate], decoded_certificate); - std::string sig("NISTP-256"); - if (decoded_certificate.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_verificationKey)) { - if (decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP384)) { - sig.assign("NISTP-384"); - } else if (decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP256r1)) { - sig.assign("BP-256"); - } else if (decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP384r1)) { - sig.assign("BP-384"); - } - } - loggers::get_instance().log("security_services::sign_tbs_data: sig = '%s'", sig.c_str()); - params_its::const_iterator it = p_params.find(params_its::signature); - if (it == p_params.cend()) { - p_params.insert(std::pair(params_its::signature, sig)); - } else { - p_params[params_its::signature] = sig; - } - loggers::get_instance().log("security_services::sign_tbs_data: encoded params_its::signature = '%s'", p_params[params_its::signature].c_str()); - - // Encode the ToBeSignedData - etsi_ts103097_tobesigned_data_codec tbs_data_codec; - OCTETSTRING os; - tbs_data_codec.encode(p_tbs_data, os); - if (os.lengthof() == 0) { - loggers::get_instance().warning("security_services::sign_tbs_data: Failed to encode ToBeSignedData"); - return -1; - } - loggers::get_instance().log_msg("security_services::sign_tbs_data: encoded tbs_data=", os); - // Hash ToBeSignedData - OCTETSTRING hashed_data; - if (p_hashAlgorithm == Ieee1609Dot2BaseTypes::HashAlgorithm::sha256) { - hash_sha256(os, hashed_data); - } else { - hash_sha384(os, hashed_data); - } - loggers::get_instance().log_msg("security_services::sign_tbs_data: encoded hashed_data=", hashed_data); - // Sign ToBeSignedData - int result = -1; - loggers::get_instance().log("security_services::sign_tbs_data: encoded params_its::signature = '%s'", - p_params[params_its::signature].c_str()); // TODO this parameter is useless, use content of the certificate - loggers::get_instance().log("security_services::sign_tbs_data: encoded params_its::certificate = '%s'", p_params[params_its::certificate].c_str()); - if (p_params[params_its::signature].compare("NISTP-256") == 0) { - result = sign_ecdsa_nistp256(hashed_data, p_signature, p_params); - } else if (p_params[params_its::signature].compare("NISTP-384") == 0) { - result = sign_ecdsa_nistp384(hashed_data, p_signature, p_params); - } else if (p_params[params_its::signature].compare("BP-256") == 0) { - result = sign_ecdsa_brainpoolp256r1(hashed_data, p_signature, p_params); - } else if (p_params[params_its::signature].compare("BP-384") == 0) { - result = sign_ecdsa_brainpoolp384r1(hashed_data, p_signature, p_params); - } else { - loggers::get_instance().error("security_services::sign_tbs_data: Unsupported signature algorithm"); - result = -1; - } - if (result != 0) { - loggers::get_instance().warning("security_services::sign_tbs_data: Failed to sign payload"); - return -1; - } - - return 0; -} - -int security_services::hash_sha256(const OCTETSTRING &p_data, OCTETSTRING &p_hash_data) { - loggers::get_instance().log_msg(">>> security_services::hash_sha256: ", p_data); - - sha256 hash; - return hash.generate(p_data, p_hash_data); -} - -int security_services::hash_sha384(const OCTETSTRING &p_data, OCTETSTRING &p_hash_data) { - loggers::get_instance().log_msg(">>> security_services::hash_sha384: ", p_data); - - sha384 hash; - return hash.generate(p_data, p_hash_data); -} - -int security_services::sign_ecdsa_nistp256(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::sign_ecdsa_nistp256: ", p_hash); - - std::string certificate_id = p_params[params_its::certificate]; - loggers::get_instance().log("security_services::sign_ecdsa_nistp256: encoded certificate_id = '%s'", certificate_id.c_str()); - OCTETSTRING pkey; - if (_security_db->get_private_key(certificate_id, pkey) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_nistp256: Failed to get private key"); - return -1; - } - // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - OCTETSTRING hash_cert; - if (_security_db->get_hash(certificate_id, hash_cert) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_nistp256: Failed to get whole hash certificate"); - return -1; - } - loggers::get_instance().log_msg("security_services::sign_ecdsa_nistp256: hash_issuer: ", hash_cert); - OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::sign_ecdsa_nistp256: hash: ", os); - OCTETSTRING hashed_data; - hash_sha256(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - security_ecc k(ec_elliptic_curves::nist_p_256, pkey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashed_data, r_sig, s_sig) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_nistp256: Failed to sign payload"); - return -1; - } - Ieee1609Dot2BaseTypes::EccP256CurvePoint ep; - ep.x__only() = r_sig; - p_signature.ecdsaNistP256Signature() = Ieee1609Dot2BaseTypes::EcdsaP256Signature(ep, s_sig); - loggers::get_instance().log_msg("security_services::sign_ecdsa_nistp256: signature=", p_signature); - - return 0; -} - -int security_services::sign_ecdsa_nistp384(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::sign_ecdsa_nistp384: ", p_hash); - - std::string certificate_id = p_params[params_its::certificate]; - loggers::get_instance().log("security_services::sign_ecdsa_nistp384: encoded certificate_id = '%s'", certificate_id.c_str()); - OCTETSTRING pkey; - if (_security_db->get_private_key(certificate_id, pkey) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_nistp384: Failed to get private key"); - return -1; - } - // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - OCTETSTRING hash_cert; - if (_security_db->get_hash(certificate_id, hash_cert) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_nistp384: Failed to get whole hash certificate"); - return -1; - } - loggers::get_instance().log_msg("security_services::sign_ecdsa_nistp384: hash_issuer: ", hash_cert); - OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::sign_ecdsa_nistp384: hash: ", os); - OCTETSTRING hashed_data; - hash_sha384(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - security_ecc k(ec_elliptic_curves::nist_p_384, pkey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashed_data, r_sig, s_sig) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_nistp384: Failed to sign payload"); - return -1; - } - Ieee1609Dot2BaseTypes::EccP384CurvePoint ep; - ep.x__only() = r_sig; - p_signature.ecdsaNistP384Signature() = Ieee1609Dot2BaseTypes::EcdsaP384Signature(ep, s_sig); - loggers::get_instance().log_msg("security_services::sign_ecdsa_nistp384: signature=", p_signature); - - return 0; -} - -int security_services::verify_sign_ecdsa_nistp256(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, - const std::string &p_certificate_id, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::verify_sign_ecdsa_nistp256:", p_hash); - loggers::get_instance().log(">>> security_services::verify_sign_ecdsa_nistp256: %s", p_certificate_id.c_str()); - - OCTETSTRING public_key_x; - OCTETSTRING public_key_y; - if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_nistp256 (%s): Failed to get public keys", p_certificate_id.c_str()); - return -1; - } - - // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - OCTETSTRING issuer; // Hash (Signer identifier input) - if (_security_db->get_hash(p_certificate_id, issuer) != 0) { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_nistp256 (%s): Failed to get hash of the issuer certificate", - p_certificate_id.c_str()); - return -1; - } - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_nistp256: hash_issuer: ", issuer); - OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_nistp256: hash: ", hash_data); - OCTETSTRING hash_to_be_verified; - hash_sha256(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_nistp256: hash_to_be_verified: ", hash_to_be_verified); - - // Build the signature - OCTETSTRING signature; - if (p_signature.ecdsaNistP256Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_x__only)) { - signature = p_signature.ecdsaNistP256Signature().rSig().x__only() + p_signature.ecdsaNistP256Signature().sSig(); - } else if (p_signature.ecdsaNistP256Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { - signature = p_signature.ecdsaNistP256Signature().rSig().compressed__y__0() + p_signature.ecdsaNistP256Signature().sSig(); - } else if (p_signature.ecdsaNistP256Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { - signature = p_signature.ecdsaNistP256Signature().rSig().compressed__y__1() + p_signature.ecdsaNistP256Signature().sSig(); - } else if (p_signature.ecdsaNistP256Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { - signature = p_signature.ecdsaNistP256Signature().rSig().uncompressedP256().x() + p_signature.ecdsaNistP256Signature().rSig().uncompressedP256().y() + - p_signature.ecdsaNistP256Signature().sSig(); - } else { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_nistp256 (%s): Invalid curve point", p_certificate_id.c_str()); - return -1; - } - security_ecc k(ec_elliptic_curves::nist_p_256, public_key_x, public_key_y); - if (k.sign_verif(hash_to_be_verified, signature) == 0) { - return 0; - } - - return -1; -} - -int security_services::verify_sign_ecdsa_nistp384(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, - const std::string &p_certificate_id, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::verify_sign_ecdsa_nistp384:", p_hash); - loggers::get_instance().log(">>> security_services::verify_sign_ecdsa_nistp384: %s", p_certificate_id.c_str()); - - OCTETSTRING public_key_x; - OCTETSTRING public_key_y; - if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_nistp384 (%s): Failed to get public keys", p_certificate_id.c_str()); - return -1; - } - - // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - OCTETSTRING issuer; // Hash (Signer identifier input) - if (_security_db->get_hash(p_certificate_id, issuer) != 0) { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_nistp384 (%s): Failed to get hash of the issuer certificate", - p_certificate_id.c_str()); - return -1; - } - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_nistp384: hash_issuer: ", issuer); - OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_nistp384: hash: ", hash_data); - OCTETSTRING hash_to_be_verified; - hash_sha384(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_nistp384: hash_to_be_verified: ", hash_to_be_verified); - - // Build the signature - OCTETSTRING signature; - if (p_signature.ecdsaNistP384Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_x__only)) { - signature = p_signature.ecdsaNistP384Signature().rSig().x__only() + p_signature.ecdsaNistP384Signature().sSig(); - } else if (p_signature.ecdsaNistP384Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { - signature = p_signature.ecdsaNistP384Signature().rSig().compressed__y__0() + p_signature.ecdsaNistP384Signature().sSig(); - } else if (p_signature.ecdsaNistP384Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { - signature = p_signature.ecdsaNistP384Signature().rSig().compressed__y__1() + p_signature.ecdsaNistP384Signature().sSig(); - } else if (p_signature.ecdsaNistP384Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { - signature = p_signature.ecdsaNistP384Signature().rSig().uncompressedP384().x() + p_signature.ecdsaNistP384Signature().rSig().uncompressedP384().y() + - p_signature.ecdsaNistP384Signature().sSig(); - } else { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_nistp384 (%s): Invalid curve point", p_certificate_id.c_str()); - return -1; - } - security_ecc k(ec_elliptic_curves::nist_p_384, public_key_x, public_key_y); - if (k.sign_verif(hash_to_be_verified, signature) == 0) { - return 0; - } - - return -1; -} - -int security_services::sign_ecdsa_brainpoolp256r1(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::sign_ecdsa_brainpoolp256r1: ", p_hash); - - std::string certificate_id = p_params[params_its::certificate]; - loggers::get_instance().log("security_services::sign_ecdsa_brainpoolp256r1: encoded certificate_id = '%s'", certificate_id.c_str()); - OCTETSTRING pkey; - if (_security_db->get_private_key(certificate_id, pkey) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_brainpoolp256r1: Failed to get private key"); - return -1; - } - // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - OCTETSTRING hash_cert; - if (_security_db->get_hash(certificate_id, hash_cert) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_brainpoolp256r1: Failed to get whole hash certificate"); - return -1; - } - loggers::get_instance().log_msg("security_services::sign_ecdsa_brainpoolp256r1: hash_issuer: ", hash_cert); - OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::sign_ecdsa_brainpoolp256r1: hash: ", os); - OCTETSTRING hashed_data; - hash_sha256(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, pkey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashed_data, r_sig, s_sig) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_brainpoolp256r1: Failed to sign payload"); - return -1; - } - Ieee1609Dot2BaseTypes::EccP256CurvePoint ep; - ep.x__only() = r_sig; - p_signature.ecdsaBrainpoolP256r1Signature() = Ieee1609Dot2BaseTypes::EcdsaP256Signature(ep, s_sig); - loggers::get_instance().log_msg("security_services::sign_ecdsa_brainpoolp256r1: signature=", p_signature); - - return 0; -} - -int security_services::verify_sign_ecdsa_brainpoolp256r1(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, - const std::string &p_certificate_id, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::verify_sign_ecdsa_brainpoolp256r1:", p_hash); - loggers::get_instance().log(">>> security_services::verify_sign_ecdsa_brainpoolp256r1: %s", p_certificate_id.c_str()); - - OCTETSTRING public_key_x; - OCTETSTRING public_key_y; - if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_brainpoolp256r1 (%s): Failed to get public keys", p_certificate_id.c_str()); - return -1; - } - - // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - OCTETSTRING issuer; // Hash (Signer identifier input) - if (_security_db->get_hash(p_certificate_id, issuer) != 0) { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_brainpoolp256r1 (%s): Failed to get hash of the issuer certificate", - p_certificate_id.c_str()); - return -1; - } - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_brainpoolp256r1: hash_issuer: ", issuer); - OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_brainpoolp256r1: hash: ", hash_data); - OCTETSTRING hash_to_be_verified; - hash_sha256(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_brainpoolp256r1: hash_to_be_verified: ", hash_to_be_verified); - - // Build the signature - OCTETSTRING signature; - if (p_signature.ecdsaBrainpoolP256r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_x__only)) { - signature = p_signature.ecdsaBrainpoolP256r1Signature().rSig().x__only() + p_signature.ecdsaBrainpoolP256r1Signature().sSig(); - } else if (p_signature.ecdsaBrainpoolP256r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { - signature = p_signature.ecdsaBrainpoolP256r1Signature().rSig().compressed__y__0() + p_signature.ecdsaBrainpoolP256r1Signature().sSig(); - } else if (p_signature.ecdsaBrainpoolP256r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { - signature = p_signature.ecdsaBrainpoolP256r1Signature().rSig().compressed__y__1() + p_signature.ecdsaBrainpoolP256r1Signature().sSig(); - } else if (p_signature.ecdsaBrainpoolP256r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { - signature = p_signature.ecdsaBrainpoolP256r1Signature().rSig().uncompressedP256().x() + - p_signature.ecdsaBrainpoolP256r1Signature().rSig().uncompressedP256().y() + p_signature.ecdsaBrainpoolP256r1Signature().sSig(); - } else { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_brainpoolp256r1 (%s): Invalid curve point", p_certificate_id.c_str()); - return -1; - } - security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, public_key_x, public_key_y); - if (k.sign_verif(hash_to_be_verified, signature) == 0) { - return 0; - } - - return -1; -} - -int security_services::sign_ecdsa_brainpoolp384r1(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::sign_ecdsa_brainpoolp384r1: ", p_hash); - - std::string certificate_id = p_params[params_its::certificate]; - loggers::get_instance().log("security_services::sign_ecdsa_brainpoolp384r1: encoded certificate_id = '%s'", certificate_id.c_str()); - OCTETSTRING pkey; - if (_security_db->get_private_key(certificate_id, pkey) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_brainpoolp384r1: Failed to get private key"); - return -1; - } - // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - OCTETSTRING hash_cert; - if (_security_db->get_hash(certificate_id, hash_cert) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_brainpoolp384r1: Failed to get whole hash certificate"); - return -1; - } - loggers::get_instance().log_msg("security_services::sign_ecdsa_brainpoolp384r1: hash_issuer: ", hash_cert); - OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::sign_ecdsa_brainpoolp384r1: hash: ", os); - OCTETSTRING hashed_data; - hash_sha384(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, pkey); - OCTETSTRING r_sig; - OCTETSTRING s_sig; - if (k.sign(hashed_data, r_sig, s_sig) != 0) { - loggers::get_instance().warning("security_services::sign_ecdsa_brainpoolp384r1: Failed to sign payload"); - return -1; - } - Ieee1609Dot2BaseTypes::EccP384CurvePoint ep; - ep.x__only() = r_sig; - p_signature.ecdsaBrainpoolP384r1Signature() = Ieee1609Dot2BaseTypes::EcdsaP384Signature(ep, s_sig); - loggers::get_instance().log_msg("security_services::sign_ecdsa_brainpoolp384r1: signature=", p_signature); - - return 0; -} - -int security_services::verify_sign_ecdsa_brainpoolp384r1(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, - const std::string &p_certificate_id, params_its &p_params) { - loggers::get_instance().log_msg(">>> security_services::verify_sign_ecdsa_brainpoolp384r1:", p_hash); - loggers::get_instance().log(">>> security_services::verify_sign_ecdsa_brainpoolp384r1: %s", p_certificate_id.c_str()); - - OCTETSTRING public_key_x; - OCTETSTRING public_key_y; - if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_brainpoolp384r1 (%s): Failed to get public keys", p_certificate_id.c_str()); - return -1; - } - - // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - OCTETSTRING issuer; // Hash (Signer identifier input) - if (_security_db->get_hash(p_certificate_id, issuer) != 0) { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_brainpoolp384r1 (%s): Failed to get hash of the issuer certificate", - p_certificate_id.c_str()); - return -1; - } - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_brainpoolp384r1: hash_issuer: ", issuer); - OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_brainpoolp384r1: hash: ", hash_data); - OCTETSTRING hash_to_be_verified; - hash_sha384(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - loggers::get_instance().log_msg("security_services::verify_sign_ecdsa_brainpoolp384r1: hash_to_be_verified: ", hash_to_be_verified); - - // Build the signature - OCTETSTRING signature; - if (p_signature.ecdsaBrainpoolP384r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_x__only)) { - signature = p_signature.ecdsaBrainpoolP384r1Signature().rSig().x__only() + p_signature.ecdsaBrainpoolP384r1Signature().sSig(); - } else if (p_signature.ecdsaBrainpoolP384r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { - signature = p_signature.ecdsaBrainpoolP384r1Signature().rSig().compressed__y__0() + p_signature.ecdsaBrainpoolP384r1Signature().sSig(); - } else if (p_signature.ecdsaBrainpoolP384r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { - signature = p_signature.ecdsaBrainpoolP384r1Signature().rSig().compressed__y__1() + p_signature.ecdsaBrainpoolP384r1Signature().sSig(); - } else if (p_signature.ecdsaBrainpoolP384r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { - signature = p_signature.ecdsaBrainpoolP384r1Signature().rSig().uncompressedP384().x() + - p_signature.ecdsaBrainpoolP384r1Signature().rSig().uncompressedP384().y() + p_signature.ecdsaBrainpoolP384r1Signature().sSig(); - } else { - loggers::get_instance().warning("security_services::verify_sign_ecdsa_brainpoolp384r1 (%s): Invalid curve point", p_certificate_id.c_str()); - return -1; - } - security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, public_key_x, public_key_y); - if (k.sign_verif(hash_to_be_verified, signature) == 0) { - return 0; - } - - return -1; -} - -int security_services::extract_verification_keys(const Ieee1609Dot2::CertificateBase &p_cert, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y, - OCTETSTRING &p_public_comp_key, INTEGER &p_public_comp_key_mode) { - loggers::get_instance().log("security_services::extract_verification_keys"); - - if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP256)) { - if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { - p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().compressed__y__0(); - security_ecc ecc(ec_elliptic_curves::nist_p_256, p_public_comp_key, ecc_compressed_mode::compressed_y_0); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - p_public_comp_key_mode = INTEGER(0); - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().ischosen( - Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { - p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().compressed__y__1(); - security_ecc ecc(ec_elliptic_curves::nist_p_256, p_public_comp_key, ecc_compressed_mode::compressed_y_1); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - p_public_comp_key_mode = INTEGER(1); - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().ischosen( - Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { - security_ecc ecc(ec_elliptic_curves::nist_p_256, p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().x(), - p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().y()); - p_public_comp_key = ecc.public_key_compressed(); - p_public_comp_key_mode = INTEGER((int)ecc.public_key_compressed_mode()); - p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().x(); - p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().y(); - } else { - loggers::get_instance().error("security_services::extract_verification_keys: Unsupported ecdsaNistP256 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().get_selection()); - return -1; - } - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP256r1)) { - if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().ischosen( - Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { - p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().compressed__y__0(); - security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p_public_comp_key, ecc_compressed_mode::compressed_y_0); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - p_public_comp_key_mode = INTEGER(0); - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().ischosen( - Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { - p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().compressed__y__1(); - security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p_public_comp_key, ecc_compressed_mode::compressed_y_1); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - p_public_comp_key_mode = INTEGER(1); - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().ischosen( - Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { - p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().uncompressedP256().x(); - p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().uncompressedP256().y(); - } else { - loggers::get_instance().error("security_services::extract_verification_keys: Unsupported ecdsaBrainpoolP256r1 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().get_selection()); - return -1; - } - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP384r1)) { - if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().ischosen( - Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { - p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().compressed__y__0(); - security_ecc ecc(ec_elliptic_curves::brainpool_p_384_r1, p_public_comp_key, ecc_compressed_mode::compressed_y_0); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - p_public_comp_key_mode = INTEGER(0); - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().ischosen( - Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { - p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().compressed__y__1(); - security_ecc ecc(ec_elliptic_curves::brainpool_p_384_r1, p_public_comp_key, ecc_compressed_mode::compressed_y_1); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - p_public_comp_key_mode = INTEGER(1); - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().ischosen( - Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { - p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().uncompressedP384().x(); - p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().uncompressedP384().y(); - } else { - loggers::get_instance().error("security_services::extract_verification_keys: Unsupported ecdsaBrainpoolP384r1 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().get_selection()); - return -1; - } - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP384)) { - if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().ischosen( - Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { - p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().compressed__y__0(); - security_ecc ecc(ec_elliptic_curves::nist_p_384, p_public_comp_key, ecc_compressed_mode::compressed_y_0); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - p_public_comp_key_mode = INTEGER(0); - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().ischosen( - Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { - p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().compressed__y__1(); - security_ecc ecc(ec_elliptic_curves::nist_p_384, p_public_comp_key, ecc_compressed_mode::compressed_y_1); - p_public_key_x = ecc.public_key_x(); - p_public_key_y = ecc.public_key_y(); - p_public_comp_key_mode = INTEGER(1); - } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().ischosen( - Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { - p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().uncompressedP384().x(); - p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().uncompressedP384().y(); - } else { - loggers::get_instance().error("security_services::extract_verification_keys: Unsupported ecdsaNistP384 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().get_selection()); - return -1; - } - } else { - loggers::get_instance().error("security_services::extract_verification_keys: Unsupported VerificationKey curve %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().get_selection()); - return -1; - } - - return 0; -} - -int security_services::extract_encryption_keys(const Ieee1609Dot2::CertificateBase &p_cert, OCTETSTRING &p_public_enc_key_x, OCTETSTRING &p_public_enc_key_y, - OCTETSTRING &p_public_enc_comp_key, INTEGER &p_public_enc_comp_key_mode) { - loggers::get_instance().log("security_services::extract_encryption_keys"); - - if (p_cert.toBeSigned().encryptionKey().ispresent()) { - const Ieee1609Dot2BaseTypes::PublicEncryptionKey &p = static_cast(p_cert.toBeSigned().encryptionKey()); - if (p.publicKey().ischosen(Ieee1609Dot2BaseTypes::BasePublicEncryptionKey::ALT_eciesNistP256)) { - if (p.publicKey().eciesNistP256().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { - p_public_enc_comp_key = p.publicKey().eciesNistP256().compressed__y__0(); - security_ecc ecc(ec_elliptic_curves::nist_p_256, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_0); - p_public_enc_key_x = ecc.public_key_x(); - p_public_enc_key_y = ecc.public_key_y(); - p_public_enc_comp_key_mode = INTEGER(0); - } else if (p.publicKey().eciesNistP256().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { - const OCTETSTRING &p_public_enc_comp_key = p.publicKey().eciesNistP256().compressed__y__1(); - security_ecc ecc(ec_elliptic_curves::nist_p_256, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_1); - p_public_enc_key_x = ecc.public_key_x(); - p_public_enc_key_y = ecc.public_key_y(); - p_public_enc_comp_key_mode = INTEGER(1); - } else if (p.publicKey().eciesNistP256().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { - p_public_enc_key_x = p.publicKey().eciesNistP256().uncompressedP256().x(); - p_public_enc_key_y = p.publicKey().eciesNistP256().uncompressedP256().y(); - } else { - loggers::get_instance().error("security_services::extract_encryption_keys: Unsupported EncryptionKey"); - return -1; - } - } else if (p.publicKey().ischosen(Ieee1609Dot2BaseTypes::BasePublicEncryptionKey::ALT_eciesBrainpoolP256r1)) { - if (p.publicKey().eciesBrainpoolP256r1().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { - p_public_enc_comp_key = p.publicKey().eciesBrainpoolP256r1().compressed__y__0(); - security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_0); - p_public_enc_key_x = ecc.public_key_x(); - p_public_enc_key_y = ecc.public_key_y(); - p_public_enc_comp_key_mode = INTEGER(0); - } else if (p.publicKey().eciesBrainpoolP256r1().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { - p_public_enc_comp_key = p.publicKey().eciesBrainpoolP256r1().compressed__y__1(); - security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_1); - p_public_enc_key_x = ecc.public_key_x(); - p_public_enc_key_y = ecc.public_key_y(); - p_public_enc_comp_key_mode = INTEGER(1); - } else if (p.publicKey().eciesBrainpoolP256r1().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { - p_public_enc_key_x = p.publicKey().eciesBrainpoolP256r1().uncompressedP256().x(); - p_public_enc_key_y = p.publicKey().eciesBrainpoolP256r1().uncompressedP256().y(); - } else { - loggers::get_instance().error("security_services::extract_encryption_keys: Unsupported EncryptionKey"); - return -1; - } - } else { - loggers::get_instance().error("security_services::extract_encryption_keys: Unsupported EncryptionKey"); - return -1; - } - } else { - loggers::get_instance().warning("security_services::extract_encryption_keys: EncryptionKey omitted"); - p_public_enc_key_x = OCTETSTRING(0, nullptr); - p_public_enc_key_y = OCTETSTRING(0, nullptr); - p_public_enc_comp_key = OCTETSTRING(0, nullptr); - return 0; // Normal termination - } - - return 0; -} // End of method extract_encryption_keys - -int security_services::extract_and_store_certificate(const Ieee1609Dot2::CertificateBase &p_certificate, std::string &p_certificate_id) { - loggers::get_instance().log_msg(">>> security_services::extract_and_store_certificate: ", p_certificate); - - // Encode certificate - etsi_ts103097_certificate_codec codec; - OCTETSTRING enc_cert; - codec.encode(p_certificate, enc_cert); - if (enc_cert.lengthof() == 0) { - loggers::get_instance().warning("security_services::extract_and_store_certificate: Failed to encode certificate"); - return -1; - } - loggers::get_instance().log_msg("security_services::extract_and_store_certificate: Encoded certificate=", enc_cert); - OCTETSTRING hash_cert_sha_256; - hash_sha256(enc_cert, hash_cert_sha_256); - loggers::get_instance().log_msg("security_services::extract_and_store_certificate: hash_cert_sha_256= ", hash_cert_sha_256); - int result = -1; - if (p_certificate.issuer().ischosen(Ieee1609Dot2::IssuerIdentifier::ALT_sha256AndDigest)) { - // Calculate the hash according to the hashId - OCTETSTRING hash_cert(hash_cert_sha_256); - loggers::get_instance().log_msg("security_services::extract_and_store_certificate: hash_cert= ", hash_cert); - const OCTETSTRING hashed_id8 = substr(hash_cert, hash_cert.lengthof() - 8, 8); - // Retrieve the certificate identifier from digest - loggers::get_instance().log_msg("security_services::extract_and_store_certificate: Retrieve the certificate identifier from digest: ", hashed_id8); - result = _security_db.get()->get_certificate_id(hashed_id8, p_certificate_id); - if (result == -1) { // Not found in current DB - if (_security_cache.get()->get_certificate_id(hashed_id8, p_certificate_id) == -1) { // Not found in TS cache - loggers::get_instance().log_msg("security_services::extract_and_store_certificate: Store new certificate in cache: ", p_certificate); - // const std::vector v(static_cast(hashed_id8), static_cast(hashed_id8) + - // hashed_id8.lengthof()); p_certificate_id = converter::get_instance().bytes_to_hexa(v); - p_certificate_id = std::string(static_cast(hex2str(oct2hex(hashed_id8)))); - // Add it into the cache - OCTETSTRING public_key_x, public_key_y, public_comp_key; - INTEGER public_comp_key_mode; - if (extract_verification_keys(p_certificate, public_key_x, public_key_y, public_comp_key, public_comp_key_mode) == -1) { - loggers::get_instance().error("security_services::extract_and_store_certificate: Unsupported EncryptionKey"); - return -1; - } - // Add encryption keys - OCTETSTRING public_enc_key_x, public_enc_key_y, public_enc_comp_key; - INTEGER public_enc_comp_key_mode; - if (extract_encryption_keys(p_certificate, public_enc_key_x, public_enc_key_y, public_enc_comp_key, public_enc_comp_key_mode) == -1) { - loggers::get_instance().error("security_services::extract_and_store_certificate: Unsupported EncryptionKey"); - return -1; - } - // And store it into the cache - _security_cache.get()->store_certificate(CHARSTRING(p_certificate_id.c_str()), enc_cert, int2oct(0, 32), // No way to get the private key here - public_key_x, public_key_y, public_comp_key, public_comp_key_mode, hash_cert, hash_cert_sha_256, hashed_id8, - p_certificate.issuer().sha256AndDigest(), OCTETSTRING(0, nullptr), // Encryption private not used - public_enc_key_x, public_enc_key_y, public_enc_comp_key, public_enc_comp_key_mode); - } - } - } else if (p_certificate.issuer().ischosen(Ieee1609Dot2::IssuerIdentifier::ALT_sha384AndDigest)) { - // Calculate the hash according to the hashId - OCTETSTRING hash_cert; - hash_sha384(enc_cert, hash_cert); - loggers::get_instance().log_msg("security_services::extract_and_store_certificate: hash_cert= ", hash_cert); - const OCTETSTRING hashed_id8 = substr(hash_cert, hash_cert.lengthof() - 8, 8); - // Retrieve the certificate identifier from digest - loggers::get_instance().log("security_services::extract_and_store_certificate: Retrieve the certificate identifier from digest"); - result = _security_db.get()->get_certificate_id(hashed_id8, p_certificate_id); - if (result == -1) { - if (_security_cache.get()->get_certificate_id(hashed_id8, p_certificate_id) == -1) { - loggers::get_instance().log_msg("security_services::extract_and_store_certificate: Store new certificate in cache: ", p_certificate); - // const std::vector v(static_cast(hashed_id8), static_cast(hashed_id8) + - // hashed_id8.lengthof()); p_certificate_id = converter::get_instance().bytes_to_hexa(v); - p_certificate_id = std::string(static_cast(hex2str(oct2hex(hashed_id8)))); - // Add it into the cache - OCTETSTRING public_key_x, public_key_y, public_comp_key; - INTEGER public_comp_key_mode; - if (extract_verification_keys(p_certificate, public_key_x, public_key_y, public_comp_key, public_comp_key_mode) == -1) { - loggers::get_instance().error("security_services::extract_and_store_certificate: Unsupported EncryptionKey"); - return -1; - } - // Add encryption keys - OCTETSTRING public_enc_key_x, public_enc_key_y, public_enc_comp_key; - INTEGER public_enc_comp_key_mode; - if (extract_encryption_keys(p_certificate, public_enc_key_x, public_enc_key_y, public_enc_comp_key, public_enc_comp_key_mode) == -1) { - loggers::get_instance().error("security_services::extract_and_store_certificate: Unsupported EncryptionKey"); - return -1; - } - // And store it into the cache - _security_cache.get()->store_certificate(CHARSTRING(p_certificate_id.c_str()), enc_cert, int2oct(0, 48), // No way to get the private key here - public_key_x, public_key_y, public_comp_key, public_comp_key_mode, hash_cert, hash_cert_sha_256, hashed_id8, - p_certificate.issuer().sha384AndDigest(), OCTETSTRING(0, nullptr), // Encryption private not used - public_enc_key_x, public_enc_key_y, public_enc_comp_key, public_enc_comp_key_mode); - } - } - } else { - loggers::get_instance().error("security_services::extract_and_store_certificate: Unsupported issuer"); - return -1; - } - - return 0; -} // End of method extract_and_store_certificate - -int security_services::read_certificate(const CHARSTRING &p_certificate_id, OCTETSTRING &p_certificate) const { - return _security_db.get()->get_certificate(std::string(static_cast(p_certificate_id)), p_certificate); -} - -int security_services::read_certificate_digest(const CHARSTRING &p_certificate_id, OCTETSTRING &p_digest) const { - return _security_db.get()->get_hashed_id(std::string(static_cast(p_certificate_id)), p_digest); -} - -int security_services::read_certificate_hash(const CHARSTRING &p_certificate_id, OCTETSTRING &p_hash) const { - return _security_db.get()->get_hash(std::string(static_cast(p_certificate_id)), p_hash); -} - -int security_services::read_certificate_hash_sha_256(const CHARSTRING &p_certificate_id, OCTETSTRING &p_hash) const { - return _security_db.get()->get_hash_sha_256(std::string(static_cast(p_certificate_id)), p_hash); -} - -int security_services::read_certificate_from_digest(const OCTETSTRING &p_digest, CHARSTRING &p_certificate_id) const { - std::string certificate_id; - if (_security_db.get()->get_certificate_id(p_digest, certificate_id) != -1) { - p_certificate_id = CHARSTRING(certificate_id.c_str()); - return 0; - } - return -1; -} - -int security_services::read_certificate_from_hashed_id3(const OCTETSTRING &p_digest, CHARSTRING &p_certificate_id) const { - std::string certificate_id; - if (_security_db.get()->get_certificate_hashed_id3(p_digest, certificate_id) != -1) { - p_certificate_id = CHARSTRING(certificate_id.c_str()); - return 0; - } - return -1; -} - -int security_services::read_private_key(const CHARSTRING &p_certificate_id, OCTETSTRING &p_private_key) const { - return _security_db.get()->get_private_key(std::string(static_cast(p_certificate_id)), p_private_key); -} - -int security_services::read_private_enc_key(const CHARSTRING &p_certificate_id, OCTETSTRING &p_private_enc_key) const { - return _security_db.get()->get_private_enc_key(std::string(static_cast(p_certificate_id)), p_private_enc_key); -} diff --git a/ccsrc/Protocols/Security/security_services_its.cc b/ccsrc/Protocols/Security/security_services_its.cc new file mode 100644 index 0000000000000000000000000000000000000000..1d7041e84e57c9147154bc17c42bbc30bdae58e9 --- /dev/null +++ b/ccsrc/Protocols/Security/security_services_its.cc @@ -0,0 +1,1863 @@ +#include + +#include + +#include "security_services_its.hh" + +using namespace std; // Required for isnan() +#include "etsi_ts103097_certificate_codec.hh" +#include "etsi_ts103097_data_codec.hh" +#include "etsi_ts103097_tobesigned_data_codec.hh" +#include "etsi_ts103097_tobesigned_certificate_codec.hh" + +#include "security_ecc.hh" +#include "sha256.hh" +#include "sha384.hh" + +#include "base_time.hh" + +#include "params.hh" + +#include "loggers.hh" + +#include "converter.hh" + +security_services_its *security_services_its::instance = nullptr; + +security_services_its::security_services_its() + : _setup_done{false}, _ec_keys_enc(nullptr), _security_cache(new security_cache), _security_db(nullptr), _last_generation_time(0), + _unknown_certificate(0, nullptr), _requested_certificate(), _latitude(0), _longitude(0), _elevation(0), _geospacial() { + loggers::get_instance().log(">>> security_services_its::security_services_its"); + + //_geospacial.load_countries_map("$HOME/dev/TS.ITS/ne-countries-50m.json"); // FIXME Use parameter + +} // End of ctor + +int security_services_its::setup(params_its &p_params) { // FIXME Rename this method + loggers::get_instance().log(">>> security_services_its::setup"); + _params = p_params; + _params.log(); + + if (_setup_done) { + loggers::get_instance().warning("security_services_its::setup: Already done"); + return 0; + } + + // Build the certificate caching + try { + _security_db.reset(new security_db(_params[params_its::sec_db_path])); + if (_security_db.get() == nullptr) { // Memory allocation issue + loggers::get_instance().warning("security_services_its::setup: _security_db pointer is NULL"); + return -1; + } + _setup_done = true; + } catch (...) { + loggers::get_instance().error("security_services_its::setup: Filesystem access error, terminate test suite on TTCN-3 error. Please check user name and paths " + "in the test suite configuration file."); + return -1; + } + + // Initialise encryption mechanism + params_its::const_iterator it = _params.find(params_its::cypher); + if (it == _params.cend()) { + _ec_keys_enc.reset(new security_ecc(ec_elliptic_curves::nist_p_256)); + _params.insert(std::pair(params_its::cypher, std::string("NISTP-256"))); + p_params.insert(std::pair(params_its::cypher, std::string("NISTP-256"))); + } else if (it->second.compare("NISTP-256")) { + _ec_keys_enc.reset(new security_ecc(ec_elliptic_curves::nist_p_256)); + } else if (it->second.compare("BP-256")) { + _ec_keys_enc.reset(new security_ecc(ec_elliptic_curves::brainpool_p_256_r1)); + } else if (it->second.compare("SM2P-256")) { + _ec_keys_enc.reset(new security_ecc(ec_elliptic_curves::sm2_p_256)); + } else { + loggers::get_instance().warning("security_services_its::setup: Failed to encode ToBeSignedData"); + return -1; + } + + return 0; +} + +int security_services_its::store_certificate(const ec_elliptic_curves p_signing_algorithm, const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, + const OCTETSTRING &p_public_key_x, const OCTETSTRING &p_public_key_y, const OCTETSTRING &p_public_comp_key, + const INTEGER &p_public_comp_key_mode, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, + const OCTETSTRING &p_hashid8, const OCTETSTRING &p_issuer, const OCTETSTRING &p_private_enc_key, + const OCTETSTRING &p_public_enc_key_x, const OCTETSTRING &p_public_enc_key_y, + const OCTETSTRING &p_public_enc_compressed_key, const INTEGER &p_public_enc_key_compressed_mode) { + loggers::get_instance().log_msg(">>> security_services_its::store_certificate: ", p_cert_id); + + // Sanity checks + if (_security_db.get() == nullptr) { // Setup not called + loggers::get_instance().warning("security_services_its::store_certificate: Not initialised"); + return -1; + } + return _security_db.get()->store_certificate(p_signing_algorithm, p_cert_id, p_cert, p_private_key, p_public_key_x, p_public_key_y, p_public_comp_key, p_public_comp_key_mode, + p_hash, p_hash_sha_256, p_hashid8, p_issuer, p_private_enc_key, p_public_enc_key_x, p_public_enc_key_y, + p_public_enc_compressed_key, p_public_enc_key_compressed_mode); +} + +int security_services_its::verify_and_extract_gn_payload(const OCTETSTRING &p_secured_gn_payload, const bool p_verify, + Ieee1609Dot2::Ieee1609Dot2Data &p_ieee_1609dot2_data, OCTETSTRING &p_unsecured_gn_payload, + params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::verify_and_extract_gn_payload: ", p_secured_gn_payload); + + // Sanity checks + if (p_secured_gn_payload.lengthof() == 0) { + return -1; + } + + // Decode the secured message (OER encoding) + etsi_ts103097_data_codec codec; + codec.decode(p_secured_gn_payload, p_ieee_1609dot2_data, &p_params); + // Sanity checks + if (!p_ieee_1609dot2_data.is_bound()) { + loggers::get_instance().warning("security_services_its::verify_and_extract_gn_payload: Unbound value, discard it"); + return -1; + } + if (p_verify && ((unsigned int)(int)p_ieee_1609dot2_data.protocolVersion() != security_services_its::ProtocolVersion)) { + loggers::get_instance().warning("security_services_its::verify_and_extract_gn_payload: Wrong version protocol, discard it"); + return -1; + } + + return process_ieee_1609_dot2_content(p_ieee_1609dot2_data.content(), p_verify, p_unsecured_gn_payload, p_params); +} // End of method verify_and_extract_gn_payload + +int security_services_its::process_ieee_1609_dot2_content(const Ieee1609Dot2::Ieee1609Dot2Content &p_ieee_1609_dot2_content, const bool p_verify, + OCTETSTRING &p_unsecured_payload, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::process_ieee_1609_dot2_content: ", p_ieee_1609_dot2_content); + + if (p_ieee_1609_dot2_content.ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_unsecuredData)) { // Unsecured packet, End of recursivity + p_unsecured_payload = p_ieee_1609_dot2_content.unsecuredData(); + } else if (p_ieee_1609_dot2_content.ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_signedData)) { + const Ieee1609Dot2::SignedData &signedData = p_ieee_1609_dot2_content.signedData(); + if (process_ieee_1609_dot2_signed_data(signedData, p_verify, p_unsecured_payload, p_params) != 0) { + if (p_verify) { + return -1; + } + } + } else if (p_ieee_1609_dot2_content.ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_encryptedData)) { + const Ieee1609Dot2::EncryptedData &encrypted_data = p_ieee_1609_dot2_content.encryptedData(); + OCTETSTRING signed_payload; + if (process_ieee_1609_dot2_encrypted_data(encrypted_data, p_verify, signed_payload, p_params) != 0) { + return -1; + } + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_content: Decrypted payload: ", signed_payload); + Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data; // TODO Check if it could be reused + if (verify_and_extract_gn_payload(signed_payload, p_verify, ieee_1609dot2_data, p_unsecured_payload, p_params) != 0) { + if (p_verify) { + return -1; + } + } + } else if (p_ieee_1609_dot2_content.ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_signedCertificateRequest)) { + // Reset certificate timer + loggers::get_instance().log("security_services_its::process_ieee_1609_dot2_content: Set Certificate re-transmission flag and reset timer"); + _last_generation_time = 0; + return 0; + } else { // Shall never be reached + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_content: Undefined IEEE 1609.2 Content, discard it"); + if (p_verify) { + return -1; + } + } + + loggers::get_instance().log_msg("<<< security_services_its::process_ieee_1609_dot2_content: ", p_unsecured_payload); + return 0; +} // End of method process_ieee_1609_dot2_content + +int security_services_its::process_ieee_1609_dot2_signed_data(const Ieee1609Dot2::SignedData &p_signed_data, const bool p_verify, OCTETSTRING &p_unsecured_payload, + params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::process_ieee_1609_dot2_signed_data: ", p_signed_data); + + // Check the headerInfo content + const Ieee1609Dot2::HeaderInfo &header_info = p_signed_data.tbsData().headerInfo(); + p_params[params_its::its_aid] = std::to_string(header_info.psid().get_long_long_val()); + if (!header_info.generationTime().is_present()) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: HeaderInfo::GenerationTime field is missing"); + if (p_verify) { + return -1; + } + } else { + const OPTIONAL &v = dynamic_cast &>(header_info.generationTime()); // in microsecond + unsigned long long gt = ((INTEGER &)(*v.get_opt_value())).get_long_long_val(); + // Get current time timestamp + unsigned long long us = base_time::get_instance().get_its_current_time_us(); // in microsecond + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: generation time check %ld / %ld, delta = %f, comp = %x", gt, us, + abs((double)gt - (double)us), (abs((double)gt - (double)us) >= 30000000.0)); + if (abs((double)gt - (double)us) >= 30000000.0) { // TODO Use a params for generation_time_epsilon, 30s differences + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Invalid generation time, discard it"); + if (p_verify) { + return -1; + } + } + } + + // Check p2pcdLearningRequest keys if present + if (header_info.p2pcdLearningRequest().is_present()) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: p2pcdLearningRequest not supported yet"); + // TODO Not supported by C-ITS Protocol + } + + // Check missingCrlIdentifier keys if present + if (header_info.missingCrlIdentifier().is_present()) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: missingCrlIdentifier not supported yet"); + // TODO Not supported by C-ITS Protocol + } + + // Check encryption keys if present + if (header_info.encryptionKey().is_present()) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: encryptionKey not supported yet"); + // TODO Not supported by C-ITS Protocol + } + + // Check request certificate + if (header_info.inlineP2pcdRequest().is_present()) { + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_signed_data: inlineP2pcdRequest: ", header_info.inlineP2pcdRequest()); + const Ieee1609Dot2BaseTypes::SequenceOfHashedId3 &s = + static_cast(*header_info.inlineP2pcdRequest().get_opt_value()); + _requested_certificate.clear(); + for (int i = 0; i < s.lengthof(); i++) { + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_signed_data: Add requested certificate= ", s[i]); + _requested_certificate.push_back(s[i]); + } // End of 'for' statement + } + + // Check requested certificate + if (header_info.requestedCertificate().is_present()) { + Ieee1609Dot2::CertificateBase requested_cert = header_info.requestedCertificate(); + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: ", requested_cert); + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: requestedCertificate not supported yet"); + // TODO Not supported by C-ITS Protocol + } + + // Check and extract unsecured payload + if (p_signed_data.tbsData().payload().data().is_present()) { + // Check protocol version + const OPTIONAL &v = + dynamic_cast &>(p_signed_data.tbsData().payload().data()); + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_signed_data: SignedDataPayload.data=", v); + const Ieee1609Dot2::Ieee1609Dot2Data &ieee_1609dot2_data = static_cast(*v.get_opt_value()); + if (p_verify && ((unsigned int)(int)ieee_1609dot2_data.protocolVersion() != security_services_its::ProtocolVersion)) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Wrong version protocol, discard it"); + if (p_verify) { + return -1; + } + } + if (process_ieee_1609_dot2_content(ieee_1609dot2_data.content(), p_verify, p_unsecured_payload, p_params) != 0) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Failed to process SignedData, discard it"); + if (p_verify) { + return -1; + } + } + } else if (p_signed_data.tbsData().payload().extDataHash().is_present()) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Unsupported extDataHash, discard it"); + if (p_verify) { + return -1; + } + } else { // Shall not be reached + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Unsupported SignedDataPayload, discard it"); + return -1; + } + + // Encode the ToBeSignedData + etsi_ts103097_tobesigned_data_codec tbs_data_codec; + OCTETSTRING os; + tbs_data_codec.encode(p_signed_data.tbsData(), os); + if (os.lengthof() == 0) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Failed to encode ToBeSignedData"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_signed_data: encoded tbs_data=", os); + // Calculate the hash according to the hashId + OCTETSTRING hashed_data; + if (p_signed_data.hashId() == Ieee1609Dot2BaseTypes::HashAlgorithm::sha256) { + hash_sha256(os, hashed_data); + } else { + hash_sha384(os, hashed_data); + } + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_signed_data: hashed_data=", hashed_data); + // Retrieve certificate identifier + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_signed_data: signer=", p_signed_data.signer()); + std::string certificate_id; + int result = -1; + if (p_signed_data.signer().ischosen(Ieee1609Dot2::SignerIdentifier::ALT_digest)) { + // Retrieve the certificate identifier from digest + result = _security_db.get()->get_certificate_id(p_signed_data.signer().digest(), certificate_id); + if (result == -1) { + // Check in the cache + if (_security_cache.get()->get_certificate_id(p_signed_data.signer().digest(), certificate_id) == -1) { + // Unknown certificate, request it + const OCTETSTRING &os = p_signed_data.signer().digest(); + _unknown_certificate = OCTETSTRING(3, static_cast(os) + os.lengthof() - 3); + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Unknown certificate, request it"); + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_signed_data: HashedId3: ", _unknown_certificate); + } + // Reset certificate timer + loggers::get_instance().log("security_services_its::process_ieee_1609_dot2_signed_data: Set Certificate re-transmission flag and reset timer"); + _last_generation_time = 0; + + return -1; + } else { + Ieee1609Dot2::CertificateBase certificate; + _security_cache.get()->get_certificate(certificate_id, certificate); + // Retrieve ssps + OPTIONAL &v = certificate.toBeSigned().appPermissions(); + if (v.is_present()) { + Ieee1609Dot2BaseTypes::SequenceOfPsidSsp psid_ssps = static_cast(*v.get_opt_value()); + retrieve_ssps(psid_ssps, p_params); + } + } + } else if (p_signed_data.signer().ischosen(Ieee1609Dot2::SignerIdentifier::ALT_certificate) && (p_signed_data.signer().certificate().size_of() != 0)) { + // Extract the certificates + std::vector certificate_ids; + for (int i = 0; i < p_signed_data.signer().certificate().size_of(); i++) { + Ieee1609Dot2::CertificateBase cert = p_signed_data.signer().certificate()[i]; + // Retrieve ssps + OPTIONAL &v = cert.toBeSigned().appPermissions(); + if (v.is_present()) { + Ieee1609Dot2BaseTypes::SequenceOfPsidSsp psid_ssps = static_cast(*v.get_opt_value()); + retrieve_ssps(psid_ssps, p_params); + } + + std::string certificate_id; + if (extract_and_store_certificate(cert, certificate_id) != 0) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Failed to store certificate"); + if (p_verify) { + return -1; + } + } + loggers::get_instance().log("security_services_its::process_ieee_1609_dot2_signed_data: certificate_id: '%s'", certificate_id.c_str()); + certificate_ids.push_back(certificate_id); + loggers::get_instance().log("security_services_its::process_ieee_1609_dot2_signed_data: certificate_ids size: %d", certificate_ids.size()); + } // End of 'for' statement + certificate_id = certificate_ids[0]; + loggers::get_instance().log("security_services_its::process_ieee_1609_dot2_signed_data: After extract_and_store_certificate, certificate_id: '%s'", + certificate_id.c_str()); + } else { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Unsupported SignerIdentifier"); + return -1; + } + loggers::get_instance().log("security_services_its::process_ieee_1609_dot2_signed_data: certificate id = '%s'", certificate_id.c_str()); + + // Verify the signature of the ToBeSignedData + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_signed_data: signature=", p_signed_data.signature__()); + result = -1; + if (p_signed_data.signature__().ischosen(Ieee1609Dot2BaseTypes::Signature::ALT_ecdsaNistP256Signature)) { + result = verify_sign_ecdsa_nistp256(hashed_data, p_signed_data.signature__(), certificate_id, p_params); + } else if (p_signed_data.signature__().ischosen(Ieee1609Dot2BaseTypes::Signature::ALT_ecdsaNistP384Signature)) { + result = verify_sign_ecdsa_nistp384(hashed_data, p_signed_data.signature__(), certificate_id, p_params); + } else if (p_signed_data.signature__().ischosen(Ieee1609Dot2BaseTypes::Signature::ALT_ecdsaBrainpoolP256r1Signature)) { + result = verify_sign_ecdsa_brainpoolp256r1(hashed_data, p_signed_data.signature__(), certificate_id, p_params); + } else if (p_signed_data.signature__().ischosen(Ieee1609Dot2BaseTypes::Signature::ALT_ecdsaBrainpoolP384r1Signature)) { + result = verify_sign_ecdsa_brainpoolp384r1(hashed_data, p_signed_data.signature__(), certificate_id, p_params); + } else if (p_signed_data.signature__().ischosen(Ieee1609Dot2BaseTypes::Signature::ALT_sm2Signature)) { + result = verify_sign_ecdsa_sm2p256(hashed_data, p_signed_data.signature__(), certificate_id, p_params); + } else { + // TODO + loggers::get_instance().error("security_services_its::process_ieee_1609_dot2_signed_data: TODO"); + } + if (result != 0) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_signed_data: Failed to verify signature"); + return -1; + } + + loggers::get_instance().log_msg("<<< security_services_its::process_ieee_1609_dot2_signed_data: ", p_unsecured_payload); + return 0; +} // End of method process_ieee_1609_dot2_signed_data + +int security_services_its::retrieve_ssps(const Ieee1609Dot2BaseTypes::SequenceOfPsidSsp& p_psid_ssps, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::retrieve_ssps: ", p_psid_ssps); + loggers::get_instance().log(">>> security_services_its::retrieve_ssps: psid_ssps size: %d", p_psid_ssps.lengthof()); + for (int i = 0; i < p_psid_ssps.lengthof(); i++) { + const Ieee1609Dot2BaseTypes::PsidSsp &psid_ssp = p_psid_ssps[i]; + loggers::get_instance().log_msg("security_services_its::retrieve_ssps: Processing psid_ssp ", psid_ssp); + const OPTIONAL &s = psid_ssp.ssp(); + if (s.is_present()) { + const Ieee1609Dot2BaseTypes::ServiceSpecificPermissions &ssp = static_cast(s); + loggers::get_instance().log_msg("security_services_its::retrieve_ssps: Processing ssp ", ssp); + params_its::const_iterator it = p_params.find(std::to_string(psid_ssp.psid())); + if (it == p_params.cend()) { + OCTETSTRING os; + if (ssp.ischosen(Ieee1609Dot2BaseTypes::ServiceSpecificPermissions::ALT_opaque)) { + os = ssp.opaque(); + } else { + os = ssp.bitmapSsp(); + } + p_params[params_its::ssp] = std::string(static_cast(oct2str(os))); + } + } + } // End of 'for' statement + + return 0; +} // End of method retrieve_ssps + +int security_services_its::process_ieee_1609_dot2_encrypted_data(const Ieee1609Dot2::EncryptedData &p_encrypted_data, const bool p_verify, + OCTETSTRING &p_unsecured_payload, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::process_ieee_1609_dot2_encrypted_data: ", p_encrypted_data); + + // 1. Retrieve the RecipientId + const Ieee1609Dot2::RecipientInfo & r = p_encrypted_data.recipients()[0]; // TODO Add multiple support of recipients + const Ieee1609Dot2BaseTypes::EciesP256EncryptedKey *ecies = nullptr; // TODO Use smart pointer + const OCTETSTRING * recipient_id = nullptr; // TODO Use smart pointer + if (r.ischosen(Ieee1609Dot2::RecipientInfo::ALT_certRecipInfo)) { + recipient_id = &r.certRecipInfo().recipientId(); + if (r.certRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_eciesNistP256)) { + ecies = &r.certRecipInfo().encKey().eciesNistP256(); + } else if (r.certRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_eciesBrainpoolP256r1)) { + ecies = &r.certRecipInfo().encKey().eciesBrainpoolP256r1(); + // } else if (r.certRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_ecencSm2256)) { // FIXME FSCOM + // ecies = &r.certRecipInfo().encKey().ecencSm2256(); + } else { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Unsupported encryption algorithm"); + return -1; + } + } else if (r.ischosen(Ieee1609Dot2::RecipientInfo::ALT_signedDataRecipInfo)) { + recipient_id = &r.signedDataRecipInfo().recipientId(); + if (r.signedDataRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_eciesNistP256)) { + ecies = &r.signedDataRecipInfo().encKey().eciesNistP256(); + } else if (r.signedDataRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_eciesBrainpoolP256r1)) { + ecies = &r.signedDataRecipInfo().encKey().eciesBrainpoolP256r1(); + // } else if (r.signedDataRecipInfo().encKey().ischosen(Ieee1609Dot2::EncryptedDataEncryptionKey::ALT_ecencSm2256)) { // FIXME FSCOM + // Ieee1609Dot2BaseTypes::EcencP256EncryptedKey& e = r.signedDataRecipInfo().encKey().ecencSm2256(); + // ecies. = &r.signedDataRecipInfo().encKey().ecencSm2256(); + } else { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Unsupported encryption algorithm"); + return -1; + } + } else { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Unsupported RecipientInfo variant"); + return -1; + } + if (!p_encrypted_data.ciphertext().ischosen(Ieee1609Dot2::SymmetricCiphertext::ALT_aes128ccm)) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Unsupported AES 128 algorithm"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_encrypted_data: RecipientId= ", *recipient_id); + + // 2. Retrieve the certificate if present + std::string certificate_id; + OCTETSTRING p_enc_key; // The private encryption key + if (_security_db.get()->get_certificate_id(*recipient_id, certificate_id) == -1) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Unknown certificate"); + // Check if RecipientId is the hashed_id8 of the symetric AES keys + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_encrypted_data: AES Symmetric Keys= ", ecies->c()); + OCTETSTRING hashed_data; + hash_sha256(ecies->c(), hashed_data); + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_encrypted_data: Hash (AES Symmetric Keys)= ", hashed_data); + if (substr(hashed_data, hashed_data.lengthof() - 8, 8) != *recipient_id) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: RecipientId does not match HashedId8 of the symmetric key"); + return -1; + } else { + if (_security_db.get()->get_private_enc_key(p_params[params_its::certificate], p_enc_key) == -1) { + loggers::get_instance().warning( + "security_services_its::process_ieee_1609_dot2_encrypted_data: Failed to retrieve private encryption key for certificate %s", + p_params[params_its::certificate].c_str()); + return -1; + } + } + } else { + if (_security_db.get()->get_private_enc_key(certificate_id, p_enc_key) == -1) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Failed to retrieve private encryption key"); + return -1; + } + } + + // 3. Generate the shared secret value based on recipient's public ephemeral keys will be required + int result; + security_ecc ec(ec_elliptic_curves::nist_p_256, p_enc_key); + if (ecies->v().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + result = ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ecies->v().uncompressedP256().x(), ecies->v().uncompressedP256().y(), + ecies->c(), p_encrypted_data.ciphertext().aes128ccm().nonce(), ecies->t(), OCTETSTRING(0, nullptr)); + } else if (ecies->v().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + security_ecc ec_comp(ec_elliptic_curves::nist_p_256, ecies->v().compressed__y__0(), ecc_compressed_mode::compressed_y_0); + result = ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), ecies->c(), + p_encrypted_data.ciphertext().aes128ccm().nonce(), ecies->t(), OCTETSTRING(0, nullptr)); + } else if (ecies->v().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + security_ecc ec_comp(ec_elliptic_curves::nist_p_256, ecies->v().compressed__y__1(), ecc_compressed_mode::compressed_y_1); + result = ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), ecies->c(), + p_encrypted_data.ciphertext().aes128ccm().nonce(), ecies->t(), OCTETSTRING(0, nullptr)); + } else { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Failed to decode Decrypt Ieee1609Dot2Data-Encrypted"); + return -1; + } + if (result == -1) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Failed to generate shared secret"); + return -1; + } + // 4. Decrypt the message + OCTETSTRING enc_message(p_encrypted_data.ciphertext().aes128ccm().ccmCiphertext().lengthof() - ec.tag().lengthof(), + static_cast(p_encrypted_data.ciphertext().aes128ccm().ccmCiphertext())); + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_encrypted_data: enc_message: ", enc_message); + OCTETSTRING tag(ec.tag().lengthof(), enc_message.lengthof() + static_cast(p_encrypted_data.ciphertext().aes128ccm().ccmCiphertext())); + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_encrypted_data: tag: ", tag); + if (ec.decrypt(tag, enc_message, p_unsecured_payload) == -1) { + loggers::get_instance().warning("security_services_its::process_ieee_1609_dot2_encrypted_data: Failed to generate shared secret"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::process_ieee_1609_dot2_encrypted_data: ", p_unsecured_payload); + + return 0; +} // End of method process_ieee_1609_dot2_encrypted_data + +int security_services_its::secure_gn_payload(const OCTETSTRING &p_unsecured_gn_payload, OCTETSTRING &p_secured_gn_payload, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::secure_gn_payload: ", p_unsecured_gn_payload); + p_params.log(); + + OCTETSTRING signed_payload; + if (sign_payload(p_unsecured_gn_payload, signed_payload, p_params) != 0) { + p_secured_gn_payload = p_unsecured_gn_payload; + loggers::get_instance().warning("security_services_its::secure_gn_payload: Failed to signed payload"); + return -1; + } + + if (_params[params_its::encrypted_mode].compare("1") == 0) { + if (encrypt_gn_payload(signed_payload, p_secured_gn_payload, p_params) != 0) { + p_secured_gn_payload = signed_payload; + loggers::get_instance().warning("security_services_its::secure_gn_payload: Failed to encrypt payload"); + return -1; + } + } else { // No encryption required + loggers::get_instance().log("security_services_its::secure_gn_payload: Encryption mode not set"); + p_secured_gn_payload = signed_payload; + } + + return 0; +} + +int security_services_its::sign_payload(const OCTETSTRING &p_unsecured_gn_payload, OCTETSTRING &p_signed_gn_payload, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::sign_payload: ", p_unsecured_gn_payload); + + // Set unsecured data + Ieee1609Dot2::Ieee1609Dot2Content unsecured_data_content; + unsecured_data_content.unsecuredData() = p_unsecured_gn_payload; + Ieee1609Dot2::Ieee1609Dot2Data unsecured_data(ProtocolVersion, unsecured_data_content); + // Set hash algorithm + Ieee1609Dot2BaseTypes::HashAlgorithm hashId(Ieee1609Dot2BaseTypes::HashAlgorithm::sha256); + if (p_params[params_its::hash].compare("SHA-384") == 0) { + hashId = Ieee1609Dot2BaseTypes::HashAlgorithm::sha384; + } + // Set SignedDataPayload + Ieee1609Dot2::SignedDataPayload payload; + payload.data() = unsecured_data; + payload.extDataHash().set_to_omit(); + payload.omitted().set_to_omit(); + Ieee1609Dot2::HeaderInfo header_info; + // Set secured field according to the payload! + header_info.psid() = converter::get_instance().string_to_int(p_params[params_its::its_aid]); + header_info.expiryTime().set_to_omit(); + // Force certificate? + boolean force_certificate = false; + params_its::const_iterator it = p_params.find(params_its::force_certificate); + if (it != p_params.cend()) { + force_certificate = true; + } + loggers::get_instance().log("security_services_its::sign_payload: force_certificate='%d", force_certificate); + if (p_params[params_its::its_aid].compare("37") == 0) { // Only used by AtsRSUSimulator to add location header + // Mandatory for DENM payload + OPTIONAL location(Ieee1609Dot2BaseTypes::ThreeDLocation(_latitude, _longitude, _elevation)); + header_info.generationLocation() = location; + loggers::get_instance().log_msg("security_services_its::sign_payload: generationLocation: ", header_info.generationLocation()); + } else { + header_info.generationLocation().set_to_omit(); + } + header_info.p2pcdLearningRequest().set_to_omit(); + header_info.missingCrlIdentifier().set_to_omit(); + if (_params[params_its::encrypted_mode].compare("1") == 0) { + // TODO Set the encrytion key. Not supported yet, need to clarify mechanism, see IEEE Std 1609.2-20XX Clause 6.3.9 HeaderInfo + header_info.encryptionKey().set_to_omit(); + } else { + header_info.encryptionKey().set_to_omit(); + } + it = p_params.find(params_its::payload_type); + if (it != p_params.cend()) { + loggers::get_instance().log("security_services_its::sign_payload: Payload type: %s", it->second.c_str()); + if (it->second.compare("1") == 0) { // DENM + OPTIONAL location(Ieee1609Dot2BaseTypes::ThreeDLocation(_latitude, _longitude, _elevation)); + loggers::get_instance().log_msg("security_services_its::sign_payload: generationLocation: ", location); + header_info.generationLocation() = location; + loggers::get_instance().log_msg("security_services_its::sign_payload: generationLocation: ", header_info.generationLocation()); + } else if (it->second.compare("2") == 0) { // CAM + // Noting to do + } else { + // Noting to do + } + } else { // Process it as a GeoNetworking payload + loggers::get_instance().log("security_services_its::sign_payload: Payload type not set"); + // Noting to do + } + unsigned long long us = base_time::get_instance().get_its_current_time_us(); + loggers::get_instance().log("security_services_its::sign_payload: HeaderInfo timestamp: %ld", us); + INTEGER i; + i.set_long_long_val(us); + header_info.generationTime() = OPTIONAL(i); + loggers::get_instance().log("security_services_its::sign_payload: Final HeaderInfo timestamp: %ld", us); + // Check if a certificate shall be requested + if (_unknown_certificate.lengthof() == 3) { // HashedId3 of a requested certificate + Ieee1609Dot2BaseTypes::SequenceOfHashedId3 s; + s[0] = _unknown_certificate; + header_info.inlineP2pcdRequest() = OPTIONAL(s); + _unknown_certificate = OCTETSTRING(0, nullptr); + } else { + header_info.inlineP2pcdRequest().set_to_omit(); + } + // Check if a certificate shall be provided + if (_requested_certificate.size() != 0) { + Ieee1609Dot2::CertificateBase c; + const Ieee1609Dot2BaseTypes::HashedId3 &hashed_id3 = _requested_certificate[0]; + _security_db->get_certificate(hashed_id3, c); + header_info.requestedCertificate() = OPTIONAL(c); + } else { + header_info.requestedCertificate().set_to_omit(); + } + header_info.pduFunctionalType().set_to_omit(); + header_info.contributedExtensions().set_to_omit(); + + Ieee1609Dot2::ToBeSignedData tbs_data; + tbs_data.payload() = payload; + tbs_data.headerInfo() = header_info; + loggers::get_instance().log_msg("security_services_its::sign_payload: tbs_data=", tbs_data); + // Sign the ToBeSignedData data structure + Ieee1609Dot2BaseTypes::Signature signature; + if (sign_tbs_data(tbs_data, hashId, signature, p_params) != 0) { + loggers::get_instance().warning("security_services_its::sign_payload: Failed to secure payload"); + return -1; + } + Ieee1609Dot2::SignerIdentifier signer; + loggers::get_instance().log("security_services_its::sign_payload: us = %ld - _last_generation_time = %ld - us - _last_generation_time = %ld", us, + _last_generation_time, us - _last_generation_time); + std::string certificate_id = p_params[params_its::certificate]; + loggers::get_instance().log("security_services_its::sign_payload: certificate_id = %s", certificate_id.c_str()); + if (((unsigned int)(us - _last_generation_time) >= 1000000 * 0.95) || force_certificate) { // Need to add certificate every 1s + loggers::get_instance().log("security_services_its::sign_payload: Need to add certificate"); + Ieee1609Dot2::CertificateBase cert; + if (_security_db->get_certificate(certificate_id, cert) != 0) { + loggers::get_instance().warning("security_services_its:sign_payload: Failed to secure payload"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::sign_payload: cert= ", cert); + Ieee1609Dot2::SequenceOfCertificate sequenceOfCertificate; + sequenceOfCertificate[0] = cert; + signer.certificate() = sequenceOfCertificate; + // Reset send certificate timer + _last_generation_time = us; + loggers::get_instance().log("security_services_its::sign_payload: Reset send certificate timer, signer= ", signer); + } else { + loggers::get_instance().log("security_services_its::sign_payload: Add digest"); + OCTETSTRING digest; + if (_security_db->get_hashed_id(certificate_id, digest) != 0) { + loggers::get_instance().warning("security_services_its::sign_payload: Failed to secure payload"); + return -1; + } + signer.digest() = digest; + } + Ieee1609Dot2::SignedData signed_data(hashId, tbs_data, signer, signature); + loggers::get_instance().log_msg("security_services_its::sign_payload: signed_data=", signed_data); + Ieee1609Dot2::Ieee1609Dot2Content ieee_dot2_content; + ieee_dot2_content.signedData() = signed_data; + Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data(security_services_its::ProtocolVersion, ieee_dot2_content); + loggers::get_instance().log_msg("security_services_its::sign_payload: ieee_1609dot2_data=", ieee_1609dot2_data); + etsi_ts103097_data_codec codec; + codec.encode(ieee_1609dot2_data, p_signed_gn_payload); + if (!p_signed_gn_payload.is_bound()) { + loggers::get_instance().warning("security_services_its::sign_payload: Failed to encode Ieee1609Dot2Data"); + return -1; + } + + return 0; +} + +int security_services_its::encrypt_gn_payload(const OCTETSTRING &p_unsecured_gn_payload, OCTETSTRING &p_enc_gn_payload, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::encrypt_gn_payload: ", p_unsecured_gn_payload); + + // Sanity checks + if (_ec_keys_enc.get() == nullptr) { + loggers::get_instance().warning("security_services_its::encrypt_gn_payload: Encryption not initialised"); + return -1; + } + params_its::const_iterator it = p_params.find(params_its::peer_certificate); + if (it == p_params.cend()) { + loggers::get_instance().warning("security_services_its::encrypt_gn_payload: Encryption impossible without a peer_certificte indication in parameters"); + return -1; + } + std::string certificate_id = it->second; + loggers::get_instance().log("security_services_its::encrypt_gn_payload: Peer CertificateId=%s", certificate_id.c_str()); + + // 1. Retrieve recipient's public keys + OCTETSTRING r_public_key_x; + OCTETSTRING r_public_key_y; + if (_security_db.get()->get_public_enc_keys(certificate_id, r_public_key_x, r_public_key_y) == -1) { + loggers::get_instance().warning("security_services_its::encrypt_gn_payload: Failed to retrieve recipient's public keys"); + // TODO Setup request certificate mechanism + return -1; + } + loggers::get_instance().log_msg("security_services_its::encrypt_gn_payload: r_public_key_x=", r_public_key_x); + loggers::get_instance().log_msg("security_services_its::encrypt_gn_payload: r_public_key_y=", r_public_key_y); + + // 2. Generate new Private/Public ephemeral keys + if (_ec_keys_enc.get()->generate() == -1) { + loggers::get_instance().warning("security_services_its::encrypt_gn_payload: Failed to generate ephemeral keys"); + return -1; + } + + // 3. Generate and derive shared secret + if (_ec_keys_enc.get()->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, r_public_key_x, r_public_key_y, OCTETSTRING(0, nullptr)) == -1) { + loggers::get_instance().warning("security_services_its::encrypt_gn_payload: Failed to generate and derive secret key"); + return -1; + } + + // 4. Buil curve data structure in canonical form + Ieee1609Dot2BaseTypes::EccP256CurvePoint eccP256CurvePoint; + if (_ec_keys_enc.get()->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) { + eccP256CurvePoint.compressed__y__0() = _ec_keys_enc.get()->public_key_compressed(); + } else if (_ec_keys_enc.get()->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_1) { + eccP256CurvePoint.compressed__y__1() = _ec_keys_enc.get()->public_key_compressed(); + } else { + eccP256CurvePoint.uncompressedP256().x() = _ec_keys_enc.get()->public_key_x(); + eccP256CurvePoint.uncompressedP256().y() = _ec_keys_enc.get()->public_key_y(); + } + Ieee1609Dot2BaseTypes::EciesP256EncryptedKey ecies_key(eccP256CurvePoint, _ec_keys_enc.get()->encrypted_symmetric_key(), _ec_keys_enc.get()->tag()); + loggers::get_instance().log_msg("security_services_its::encrypt_gn_payload: ecies_key=", ecies_key); + + // 5. AES-128 encryption of the data + OCTETSTRING enc_message; + if (_ec_keys_enc.get()->encrypt(encryption_algotithm::aes_128_ccm, _ec_keys_enc.get()->symmetric_encryption_key(), _ec_keys_enc.get()->nonce(), + p_unsecured_gn_payload, enc_message) == -1) { + loggers::get_instance().warning("fx__encryptWithEciesNistp256WithSha256: Failed to encrypt message"); + return -1; + } + OCTETSTRING nonce = _ec_keys_enc.get()->nonce(); + OCTETSTRING tag = _ec_keys_enc.get()->tag(); + Ieee1609Dot2::One28BitCcmCiphertext aes_128_ccm(nonce, enc_message + tag); // Add tag at the end of the ciphered text + // 6. Build SymmetricCiphertext + Ieee1609Dot2::SymmetricCiphertext cipher_text; + cipher_text.aes128ccm() = aes_128_ccm; + loggers::get_instance().log_msg("security_services_its::encrypt_gn_payload: aes_128_ccm=", cipher_text); + + // 7. Build the recipient_id + OCTETSTRING recipient_id; + _security_db.get()->get_hashed_id(certificate_id, recipient_id); // SHA-256 of the certificate which contain the recipient's public keys + + // 8. Build the encryption data + Ieee1609Dot2::EncryptedDataEncryptionKey enc_data_key; + if (_params[params_its::cypher].compare("NISTP-256") == 0) { + enc_data_key.eciesNistP256() = ecies_key; + } else if (_params[params_its::cypher].compare("BP-256") == 0) { + enc_data_key.eciesBrainpoolP256r1() = ecies_key; + // } else if (_params[params_its::cypher].compare("SM2P-256") == 0) { // FIXME FSCOM + // enc_data_key.ecencSm2256() = ecies_key; + } + loggers::get_instance().log_msg("security_services_its::encrypt_gn_payload: enc_data_key=", enc_data_key); + + // 9. Finalise the encryption + Ieee1609Dot2::PKRecipientInfo cert_recipient_info(recipient_id, enc_data_key); + Ieee1609Dot2::RecipientInfo recipient_info; + recipient_info.certRecipInfo() = cert_recipient_info; + Ieee1609Dot2::SequenceOfRecipientInfo recipients; + recipients[0] = recipient_info; + Ieee1609Dot2::EncryptedData encrypted_data(recipients, cipher_text); + loggers::get_instance().log_msg("security_services_its::encrypt_gn_payload: encrypted_data=", encrypted_data); + + // 10. Encode it + Ieee1609Dot2::Ieee1609Dot2Content ieee_dot2_content; + ieee_dot2_content.encryptedData() = encrypted_data; + Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data(security_services_its::ProtocolVersion, ieee_dot2_content); + loggers::get_instance().log_msg("security_services_its::encrypt_gn_payload: ieee_1609dot2_data=", ieee_1609dot2_data); + etsi_ts103097_data_codec codec; + codec.encode(ieee_1609dot2_data, p_enc_gn_payload); + if (!p_enc_gn_payload.is_bound()) { + loggers::get_instance().warning("security_services_its::encrypt_gn_payload: Failed to encode Ieee1609Dot2Data"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::encrypt_gn_payload: Encoded ieee_1609dot2_data=", p_enc_gn_payload); + + return 0; +} + +int security_services_its::decrypt_gn_payload(const OCTETSTRING &p_enc_gn_payload, OCTETSTRING &p_unsecured_gn_payload, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::decrypt_gn_payload: ", p_enc_gn_payload); + + // Sanity checks + if (_ec_keys_enc.get() == nullptr) { + loggers::get_instance().warning("security_services_its::decrypt_gn_payload: Encryption not initialised"); + return -1; + } + + // 1. Decode the IEEE 1609dot2Data-Encrypted + Ieee1609Dot2::Ieee1609Dot2Data ieee_1609dot2_data; + etsi_ts103097_data_codec codec; + codec.decode(p_enc_gn_payload, ieee_1609dot2_data); + if (!ieee_1609dot2_data.is_bound()) { + loggers::get_instance().warning("security_services_its::decrypt_gn_payload: Failed to decode Ieee1609Dot2Data-Encrypted"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::decrypt_gn_payload: Ieee1609Dot2Data-Encrypted=", ieee_1609dot2_data); + + if (!ieee_1609dot2_data.content().ischosen(Ieee1609Dot2::Ieee1609Dot2Content::ALT_encryptedData)) { + loggers::get_instance().warning("security_services_its::decrypt_gn_payload: Failed to decode Decrypt Ieee1609Dot2Data-Encrypted"); + return -1; + } + if (process_ieee_1609_dot2_encrypted_data(ieee_1609dot2_data.content().encryptedData(), true, p_unsecured_gn_payload, p_params) == -1) { + loggers::get_instance().warning("security_services_its::decrypt_gn_payload: Failed to decode Decrypt Ieee1609Dot2Data-Encrypted"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::decrypt_gn_payload: Encoded ieee_1609dot2_data=", p_unsecured_gn_payload); + + return 0; +} + +/*int security_services_its::sign_tbs_data(const Ieee1609Dot2::ToBeSignedData &p_tbs_data, const Ieee1609Dot2BaseTypes::HashAlgorithm &p_hashAlgorithm, + const OCTETSTRING &p_private_key, Ieee1609Dot2BaseTypes::Signature &p_signature, + params_its &p_params) { // TODO Refine function + loggers::get_instance().log_msg(">>> security_services_its::sign_tbs_data: ", p_tbs_data); + + // Encode the ToBeSignedData + etsi_ts103097_tobesigned_data_codec tbs_data_codec; + OCTETSTRING os; + tbs_data_codec.encode(p_tbs_data, os); + if (os.lengthof() == 0) { + loggers::get_instance().warning("security_services_its::sign_tbs_data: Failed to encode ToBeSignedData"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::sign_tbs_data: encoded tbs_data=", os); + // Hash ToBeSignedData + OCTETSTRING hashed_data; + OCTETSTRING hash_issuer; + if (p_hashAlgorithm == Ieee1609Dot2BaseTypes::HashAlgorithm::sha256) { + sha256 hash; + hash.generate(os, hashed_data); + hash_issuer = hash.get_sha256_empty_string(); + } else { + sha384 hash; + hash.generate(os, hashed_data); + hash_issuer = hash.get_sha384_empty_string(); + } + loggers::get_instance().log_msg("security_services_its::sign_tbs_data: encoded hashed_data=", hashed_data); + loggers::get_instance().log_msg("security_services_its::sign_tbs_data: encoded hashed_issuer=", hash_issuer); + // Sign ToBeSignedData + loggers::get_instance().log("security_services_its::sign_tbs_data: encoded params_its::signature = '%s'", + p_params[params_its::signature].c_str()); // TODO this parameter is useless, use content of the certificate + loggers::get_instance().log("security_services_its::sign_tbs_data: encoded params_its::certificate = '%s'", p_params[params_its::certificate].c_str()); + if (p_params[params_its::signature].compare("NISTP-256") == 0) { + // Hash ( Hash (Data input) || Hash ("") ) + OCTETSTRING os = hashed_data + hash_issuer; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::sign_tbs_data: hash: ", os); + OCTETSTRING hashed_data; + hash_sha256(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + security_ecc k(ec_elliptic_curves::nist_p_256, p_private_key); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashed_data, r_sig, s_sig) != 0) { + loggers::get_instance().warning("security_services_its::sign_tbs_data: Failed to sign payload"); + return -1; + } + Ieee1609Dot2BaseTypes::EccP256CurvePoint ep; + ep.x__only() = r_sig; + p_signature.ecdsaNistP256Signature() = Ieee1609Dot2BaseTypes::EcdsaP256Signature(ep, s_sig); + loggers::get_instance().log_msg("security_services_its::sign_tbs_data: signature=", p_signature); + } // TODO To be done + + return 0; +}*/ + +int security_services_its::sign_tbs_data(const Ieee1609Dot2::ToBeSignedData &p_tbs_data, const Ieee1609Dot2BaseTypes::HashAlgorithm &p_hashAlgorithm, + Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::sign_tbs_data: ", p_tbs_data); + + // Get certificate + loggers::get_instance().log("security_services_its::sign_tbs_data: encoded params_its::certificate = '%s'", p_params[params_its::certificate].c_str()); + Ieee1609Dot2::CertificateBase decoded_certificate; + // Set signature type + _security_db.get()->get_certificate(p_params[params_its::certificate], decoded_certificate); + loggers::get_instance().log_msg("security_services_its::sign_tbs_data: Got certificate: ", decoded_certificate); + std::string sig("NISTP-256"); + if (decoded_certificate.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_verificationKey)) { + if (decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP384)) { + sig.assign("NISTP-384"); + } else if (decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP256r1)) { + sig.assign("BP-256"); + } else if (decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP384r1)) { + sig.assign("BP-384"); + } else if (decoded_certificate.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecsigSm2)) { + sig.assign("SM2P-256"); + } + } else if (decoded_certificate.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_reconstructionValue)) { + ec_elliptic_curves signing_algorithm; + if (_security_db.get()->get_signing_algorithm(p_params[params_its::certificate], &signing_algorithm) == -1) { + loggers::get_instance().warning("security_services_its::sign_tbs_data: Failed to retrieve signing algorithm (Implicit certificate)"); + return -1; + } + if (signing_algorithm == ec_elliptic_curves::brainpool_p_256_r1) { + sig.assign("BP-256"); + } // Default: NISTP-256 + } + loggers::get_instance().log("security_services_its::sign_tbs_data: sig = '%s'", sig.c_str()); + params_its::const_iterator it = p_params.find(params_its::signature); + if (it == p_params.cend()) { + p_params.insert(std::pair(params_its::signature, sig)); + } else { + p_params[params_its::signature] = sig; + } + loggers::get_instance().log("security_services_its::sign_tbs_data: encoded params_its::signature = '%s'", p_params[params_its::signature].c_str()); + + // Encode the ToBeSignedData + etsi_ts103097_tobesigned_data_codec tbs_data_codec; + OCTETSTRING os; + tbs_data_codec.encode(p_tbs_data, os); + if (os.lengthof() == 0) { + loggers::get_instance().warning("security_services_its::sign_tbs_data: Failed to encode ToBeSignedData"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::sign_tbs_data: encoded tbs_data=", os); + // Hash ToBeSignedData + OCTETSTRING hashed_data; + if (p_hashAlgorithm == Ieee1609Dot2BaseTypes::HashAlgorithm::sha256) { + hash_sha256(os, hashed_data); + } else { + hash_sha384(os, hashed_data); + } + loggers::get_instance().log_msg("security_services_its::sign_tbs_data: encoded hashed_data=", hashed_data); + // Sign ToBeSignedData + int result = -1; + loggers::get_instance().log("security_services_its::sign_tbs_data: encoded params_its::signature = '%s'", + p_params[params_its::signature].c_str()); // TODO this parameter is useless, use content of the certificate + loggers::get_instance().log("security_services_its::sign_tbs_data: encoded params_its::certificate = '%s'", p_params[params_its::certificate].c_str()); + if (p_params[params_its::signature].compare("NISTP-256") == 0) { + result = sign_ecdsa_nistp256(hashed_data, p_signature, p_params); + } else if (p_params[params_its::signature].compare("NISTP-384") == 0) { + result = sign_ecdsa_nistp384(hashed_data, p_signature, p_params); + } else if (p_params[params_its::signature].compare("BP-256") == 0) { + result = sign_ecdsa_brainpoolp256r1(hashed_data, p_signature, p_params); + } else if (p_params[params_its::signature].compare("BP-384") == 0) { + result = sign_ecdsa_brainpoolp384r1(hashed_data, p_signature, p_params); + } else if (p_params[params_its::signature].compare("SM2P-256") == 0) { + result = sign_ecdsa_sm2p256(hashed_data, p_signature, p_params); + } else { + loggers::get_instance().error("security_services_its::sign_tbs_data: Unsupported signature algorithm"); + result = -1; + } + if (result != 0) { + loggers::get_instance().warning("security_services_its::sign_tbs_data: Failed to sign payload"); + return -1; + } + + return 0; +} + +int security_services_its::hash_sha256(const OCTETSTRING &p_data, OCTETSTRING &p_hash_data) { + loggers::get_instance().log_msg(">>> security_services_its::hash_sha256: ", p_data); + + sha256 hash; + return hash.generate(p_data, p_hash_data); +} + +int security_services_its::hash_sha384(const OCTETSTRING &p_data, OCTETSTRING &p_hash_data) { + loggers::get_instance().log_msg(">>> security_services_its::hash_sha384: ", p_data); + + sha384 hash; + return hash.generate(p_data, p_hash_data); +} + +int security_services_its::sign_ecdsa_nistp256(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::sign_ecdsa_nistp256: ", p_hash); + + std::string certificate_id = p_params[params_its::certificate]; + loggers::get_instance().log("security_services_its::sign_ecdsa_nistp256: encoded certificate_id = '%s'", certificate_id.c_str()); + OCTETSTRING pkey; + if (_security_db->get_private_key(certificate_id, pkey) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_nistp256: Failed to get private key"); + return -1; + } + // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING hash_cert; + if (_security_db->get_hash(certificate_id, hash_cert) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_nistp256: Failed to get whole hash certificate"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_nistp256: hash_issuer: ", hash_cert); + OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_nistp256: hash: ", os); + OCTETSTRING hashed_data; + hash_sha256(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + security_ecc k(ec_elliptic_curves::nist_p_256, pkey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashed_data, r_sig, s_sig) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_nistp256: Failed to sign payload"); + return -1; + } + Ieee1609Dot2BaseTypes::EccP256CurvePoint ep; + ep.x__only() = r_sig; + p_signature.ecdsaNistP256Signature() = Ieee1609Dot2BaseTypes::EcdsaP256Signature(ep, s_sig); + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_nistp256: signature=", p_signature); + + return 0; +} + +int security_services_its::sign_ecdsa_nistp384(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::sign_ecdsa_nistp384: ", p_hash); + + std::string certificate_id = p_params[params_its::certificate]; + loggers::get_instance().log("security_services_its::sign_ecdsa_nistp384: encoded certificate_id = '%s'", certificate_id.c_str()); + OCTETSTRING pkey; + if (_security_db->get_private_key(certificate_id, pkey) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_nistp384: Failed to get private key"); + return -1; + } + // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING hash_cert; + if (_security_db->get_hash(certificate_id, hash_cert) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_nistp384: Failed to get whole hash certificate"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_nistp384: hash_issuer: ", hash_cert); + OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_nistp384: hash: ", os); + OCTETSTRING hashed_data; + hash_sha384(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + security_ecc k(ec_elliptic_curves::nist_p_384, pkey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashed_data, r_sig, s_sig) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_nistp384: Failed to sign payload"); + return -1; + } + Ieee1609Dot2BaseTypes::EccP384CurvePoint ep; + ep.x__only() = r_sig; + p_signature.ecdsaNistP384Signature() = Ieee1609Dot2BaseTypes::EcdsaP384Signature(ep, s_sig); + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_nistp384: signature=", p_signature); + + return 0; +} + +int security_services_its::verify_sign_ecdsa_nistp256(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, + const std::string &p_certificate_id, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::verify_sign_ecdsa_nistp256:", p_hash); + loggers::get_instance().log(">>> security_services_its::verify_sign_ecdsa_nistp256: %s", p_certificate_id.c_str()); + + OCTETSTRING public_key_x; + OCTETSTRING public_key_y; + if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_nistp256 (%s): Failed to get public keys", p_certificate_id.c_str()); + return -1; + } + + // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING issuer; // Hash (Signer identifier input) + if (_security_db->get_hash(p_certificate_id, issuer) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_nistp256 (%s): Failed to get hash of the issuer certificate", + p_certificate_id.c_str()); + return -1; + } + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_nistp256: hash_issuer: ", issuer); + OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_nistp256: hash: ", hash_data); + OCTETSTRING hash_to_be_verified; + hash_sha256(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_nistp256: hash_to_be_verified: ", hash_to_be_verified); + + // Build the signature + OCTETSTRING signature; + if (p_signature.ecdsaNistP256Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_x__only)) { + signature = p_signature.ecdsaNistP256Signature().rSig().x__only() + p_signature.ecdsaNistP256Signature().sSig(); + } else if (p_signature.ecdsaNistP256Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + signature = p_signature.ecdsaNistP256Signature().rSig().compressed__y__0() + p_signature.ecdsaNistP256Signature().sSig(); + } else if (p_signature.ecdsaNistP256Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + signature = p_signature.ecdsaNistP256Signature().rSig().compressed__y__1() + p_signature.ecdsaNistP256Signature().sSig(); + } else if (p_signature.ecdsaNistP256Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + signature = p_signature.ecdsaNistP256Signature().rSig().uncompressedP256().x() + p_signature.ecdsaNistP256Signature().rSig().uncompressedP256().y() + + p_signature.ecdsaNistP256Signature().sSig(); + } else { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_nistp256 (%s): Invalid curve point", p_certificate_id.c_str()); + return -1; + } + security_ecc k(ec_elliptic_curves::nist_p_256, public_key_x, public_key_y); + if (k.sign_verif(hash_to_be_verified, signature) == 0) { + return 0; + } + + return -1; +} + +int security_services_its::verify_sign_ecdsa_nistp384(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, + const std::string &p_certificate_id, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::verify_sign_ecdsa_nistp384:", p_hash); + loggers::get_instance().log(">>> security_services_its::verify_sign_ecdsa_nistp384: %s", p_certificate_id.c_str()); + + OCTETSTRING public_key_x; + OCTETSTRING public_key_y; + if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_nistp384 (%s): Failed to get public keys", p_certificate_id.c_str()); + return -1; + } + + // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING issuer; // Hash (Signer identifier input) + if (_security_db->get_hash(p_certificate_id, issuer) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_nistp384 (%s): Failed to get hash of the issuer certificate", + p_certificate_id.c_str()); + return -1; + } + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_nistp384: hash_issuer: ", issuer); + OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_nistp384: hash: ", hash_data); + OCTETSTRING hash_to_be_verified; + hash_sha384(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_nistp384: hash_to_be_verified: ", hash_to_be_verified); + + // Build the signature + OCTETSTRING signature; + if (p_signature.ecdsaNistP384Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_x__only)) { + signature = p_signature.ecdsaNistP384Signature().rSig().x__only() + p_signature.ecdsaNistP384Signature().sSig(); + } else if (p_signature.ecdsaNistP384Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { + signature = p_signature.ecdsaNistP384Signature().rSig().compressed__y__0() + p_signature.ecdsaNistP384Signature().sSig(); + } else if (p_signature.ecdsaNistP384Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { + signature = p_signature.ecdsaNistP384Signature().rSig().compressed__y__1() + p_signature.ecdsaNistP384Signature().sSig(); + } else if (p_signature.ecdsaNistP384Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { + signature = p_signature.ecdsaNistP384Signature().rSig().uncompressedP384().x() + p_signature.ecdsaNistP384Signature().rSig().uncompressedP384().y() + + p_signature.ecdsaNistP384Signature().sSig(); + } else { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_nistp384 (%s): Invalid curve point", p_certificate_id.c_str()); + return -1; + } + security_ecc k(ec_elliptic_curves::nist_p_384, public_key_x, public_key_y); + if (k.sign_verif(hash_to_be_verified, signature) == 0) { + return 0; + } + + return -1; +} + +int security_services_its::sign_ecdsa_brainpoolp256r1(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::sign_ecdsa_brainpoolp256r1: ", p_hash); + + std::string certificate_id = p_params[params_its::certificate]; + loggers::get_instance().log("security_services_its::sign_ecdsa_brainpoolp256r1: encoded certificate_id = '%s'", certificate_id.c_str()); + OCTETSTRING pkey; + if (_security_db->get_private_key(certificate_id, pkey) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_brainpoolp256r1: Failed to get private key"); + return -1; + } + // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING hash_cert; + if (_security_db->get_hash(certificate_id, hash_cert) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_brainpoolp256r1: Failed to get whole hash certificate"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_brainpoolp256r1: hash_issuer: ", hash_cert); + OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_brainpoolp256r1: hash: ", os); + OCTETSTRING hashed_data; + hash_sha256(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, pkey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashed_data, r_sig, s_sig) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_brainpoolp256r1: Failed to sign payload"); + return -1; + } + Ieee1609Dot2BaseTypes::EccP256CurvePoint ep; + ep.x__only() = r_sig; + p_signature.ecdsaBrainpoolP256r1Signature() = Ieee1609Dot2BaseTypes::EcdsaP256Signature(ep, s_sig); + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_brainpoolp256r1: signature=", p_signature); + + return 0; +} + +int security_services_its::verify_sign_ecdsa_brainpoolp256r1(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, + const std::string &p_certificate_id, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::verify_sign_ecdsa_brainpoolp256r1:", p_hash); + loggers::get_instance().log(">>> security_services_its::verify_sign_ecdsa_brainpoolp256r1: %s", p_certificate_id.c_str()); + + OCTETSTRING public_key_x; + OCTETSTRING public_key_y; + if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_brainpoolp256r1 (%s): Failed to get public keys", p_certificate_id.c_str()); + return -1; + } + + // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING issuer; // Hash (Signer identifier input) + if (_security_db->get_hash(p_certificate_id, issuer) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_brainpoolp256r1 (%s): Failed to get hash of the issuer certificate", + p_certificate_id.c_str()); + return -1; + } + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_brainpoolp256r1: hash_issuer: ", issuer); + OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_brainpoolp256r1: hash: ", hash_data); + OCTETSTRING hash_to_be_verified; + hash_sha256(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_brainpoolp256r1: hash_to_be_verified: ", hash_to_be_verified); + + // Build the signature + OCTETSTRING signature; + if (p_signature.ecdsaBrainpoolP256r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_x__only)) { + signature = p_signature.ecdsaBrainpoolP256r1Signature().rSig().x__only() + p_signature.ecdsaBrainpoolP256r1Signature().sSig(); + } else if (p_signature.ecdsaBrainpoolP256r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + signature = p_signature.ecdsaBrainpoolP256r1Signature().rSig().compressed__y__0() + p_signature.ecdsaBrainpoolP256r1Signature().sSig(); + } else if (p_signature.ecdsaBrainpoolP256r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + signature = p_signature.ecdsaBrainpoolP256r1Signature().rSig().compressed__y__1() + p_signature.ecdsaBrainpoolP256r1Signature().sSig(); + } else if (p_signature.ecdsaBrainpoolP256r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + signature = p_signature.ecdsaBrainpoolP256r1Signature().rSig().uncompressedP256().x() + + p_signature.ecdsaBrainpoolP256r1Signature().rSig().uncompressedP256().y() + p_signature.ecdsaBrainpoolP256r1Signature().sSig(); + } else { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_brainpoolp256r1 (%s): Invalid curve point", p_certificate_id.c_str()); + return -1; + } + security_ecc k(ec_elliptic_curves::brainpool_p_256_r1, public_key_x, public_key_y); + if (k.sign_verif(hash_to_be_verified, signature) == 0) { + return 0; + } + + return -1; +} + +int security_services_its::sign_ecdsa_brainpoolp384r1(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::sign_ecdsa_brainpoolp384r1: ", p_hash); + + std::string certificate_id = p_params[params_its::certificate]; + loggers::get_instance().log("security_services_its::sign_ecdsa_brainpoolp384r1: encoded certificate_id = '%s'", certificate_id.c_str()); + OCTETSTRING pkey; + if (_security_db->get_private_key(certificate_id, pkey) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_brainpoolp384r1: Failed to get private key"); + return -1; + } + // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING hash_cert; + if (_security_db->get_hash(certificate_id, hash_cert) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_brainpoolp384r1: Failed to get whole hash certificate"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_brainpoolp384r1: hash_issuer: ", hash_cert); + OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_brainpoolp384r1: hash: ", os); + OCTETSTRING hashed_data; + hash_sha384(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, pkey); + OCTETSTRING r_sig; + OCTETSTRING s_sig; + if (k.sign(hashed_data, r_sig, s_sig) != 0) { + loggers::get_instance().warning("security_services_its::sign_ecdsa_brainpoolp384r1: Failed to sign payload"); + return -1; + } + Ieee1609Dot2BaseTypes::EccP384CurvePoint ep; + ep.x__only() = r_sig; + p_signature.ecdsaBrainpoolP384r1Signature() = Ieee1609Dot2BaseTypes::EcdsaP384Signature(ep, s_sig); + loggers::get_instance().log_msg("security_services_its::sign_ecdsa_brainpoolp384r1: signature=", p_signature); + + return 0; +} + +int security_services_its::verify_sign_ecdsa_brainpoolp384r1(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, + const std::string &p_certificate_id, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::verify_sign_ecdsa_brainpoolp384r1:", p_hash); + loggers::get_instance().log(">>> security_services_its::verify_sign_ecdsa_brainpoolp384r1: %s", p_certificate_id.c_str()); + + OCTETSTRING public_key_x; + OCTETSTRING public_key_y; + if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_brainpoolp384r1 (%s): Failed to get public keys", p_certificate_id.c_str()); + return -1; + } + + // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING issuer; // Hash (Signer identifier input) + if (_security_db->get_hash(p_certificate_id, issuer) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_brainpoolp384r1 (%s): Failed to get hash of the issuer certificate", + p_certificate_id.c_str()); + return -1; + } + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_brainpoolp384r1: hash_issuer: ", issuer); + OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_brainpoolp384r1: hash: ", hash_data); + OCTETSTRING hash_to_be_verified; + hash_sha384(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_brainpoolp384r1: hash_to_be_verified: ", hash_to_be_verified); + + // Build the signature + OCTETSTRING signature; + if (p_signature.ecdsaBrainpoolP384r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_x__only)) { + signature = p_signature.ecdsaBrainpoolP384r1Signature().rSig().x__only() + p_signature.ecdsaBrainpoolP384r1Signature().sSig(); + } else if (p_signature.ecdsaBrainpoolP384r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { + signature = p_signature.ecdsaBrainpoolP384r1Signature().rSig().compressed__y__0() + p_signature.ecdsaBrainpoolP384r1Signature().sSig(); + } else if (p_signature.ecdsaBrainpoolP384r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { + signature = p_signature.ecdsaBrainpoolP384r1Signature().rSig().compressed__y__1() + p_signature.ecdsaBrainpoolP384r1Signature().sSig(); + } else if (p_signature.ecdsaBrainpoolP384r1Signature().rSig().ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { + signature = p_signature.ecdsaBrainpoolP384r1Signature().rSig().uncompressedP384().x() + + p_signature.ecdsaBrainpoolP384r1Signature().rSig().uncompressedP384().y() + p_signature.ecdsaBrainpoolP384r1Signature().sSig(); + } else { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_brainpoolp384r1 (%s): Invalid curve point", p_certificate_id.c_str()); + return -1; + } + security_ecc k(ec_elliptic_curves::brainpool_p_384_r1, public_key_x, public_key_y); + if (k.sign_verif(hash_to_be_verified, signature) == 0) { + return 0; + } + + return -1; +} + +int security_services_its::sign_ecdsa_sm2p256(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::sign_ecdsa_sm2p256: ", p_hash); + loggers::get_instance().error("security_services_its::sign_ecdsa_sm2p256: To be done"); // FIXME FSCOM + + // std::string certificate_id = p_params[params_its::certificate]; + // loggers::get_instance().log("security_services_its::sign_ecdsa_sm2p256: encoded certificate_id = '%s'", certificate_id.c_str()); + // OCTETSTRING pkey; + // if (_security_db->get_private_key(certificate_id, pkey) != 0) { + // loggers::get_instance().warning("security_services_its::sign_ecdsa_sm2p256: Failed to get private key"); + // return -1; + // } + // // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + // OCTETSTRING hash_cert; + // if (_security_db->get_hash(certificate_id, hash_cert) != 0) { + // loggers::get_instance().warning("security_services_its::sign_ecdsa_sm2p256: Failed to get whole hash certificate"); + // return -1; + // } + // loggers::get_instance().log_msg("security_services_its::sign_ecdsa_sm2p256: hash_issuer: ", hash_cert); + // OCTETSTRING os = p_hash + hash_cert; // Hash (Data input) || Hash (Signer identifier input) + // loggers::get_instance().log_msg("security_services_its::sign_ecdsa_sm2p256: hash: ", os); + // OCTETSTRING hashed_data; + // hash_sha256(os, hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + // security_ecc k(ec_elliptic_curves::sm2_p_256, pkey); + // OCTETSTRING r_sig; + // OCTETSTRING s_sig; + // if (k.sign(hashed_data, r_sig, s_sig) != 0) { + // loggers::get_instance().warning("security_services_its::sign_ecdsa_sm2p256: Failed to sign payload"); + // return -1; + // } + // Ieee1609Dot2BaseTypes::EccP256CurvePoint ep; + // ep.x__only() = r_sig; + // p_signature.ecdsaSm2P256Signature() = Ieee1609Dot2BaseTypes::EcdsaP256Signature(ep, s_sig); + // loggers::get_instance().log_msg("security_services_its::sign_ecdsa_sm2p256: signature=", p_signature); + + return 0; +} + +int security_services_its::verify_sign_ecdsa_sm2p256(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, + const std::string &p_certificate_id, params_its &p_params) { + loggers::get_instance().log_msg(">>> security_services_its::verify_sign_ecdsa_sm2p256:", p_hash); + loggers::get_instance().log(">>> security_services_its::verify_sign_ecdsa_sm2p256: %s", p_certificate_id.c_str()); + + OCTETSTRING public_key_x; + OCTETSTRING public_key_y; + if (_security_db->get_public_keys(p_certificate_id, public_key_x, public_key_y) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_sm2p256 (%s): Failed to get public keys", p_certificate_id.c_str()); + return -1; + } + + // Generate the hash to be verified: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + OCTETSTRING issuer; // Hash (Signer identifier input) + if (_security_db->get_hash(p_certificate_id, issuer) != 0) { + loggers::get_instance().warning("security_services_its::verify_sign_ecdsa_sm2p256 (%s): Failed to get hash of the issuer certificate", + p_certificate_id.c_str()); + return -1; + } + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_sm2p256: hash_issuer: ", issuer); + OCTETSTRING hash_data = p_hash + issuer; // Hash (Data input) || Hash (Signer identifier input) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_sm2p256: hash: ", hash_data); + OCTETSTRING hash_to_be_verified; + hash_sha256(hash_data, hash_to_be_verified); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + loggers::get_instance().log_msg("security_services_its::verify_sign_ecdsa_sm2p256: hash_to_be_verified: ", hash_to_be_verified); + + // Build the signature + OCTETSTRING signature = p_signature.sm2Signature().rSig() + p_signature.sm2Signature().sSig(); + security_ecc k(ec_elliptic_curves::sm2_p_256, public_key_x, public_key_y); + if (k.sign_verif(hash_to_be_verified, signature) == 0) { + return 0; + } + + return -1; +} + +int security_services_its::extract_verification_keys(const Ieee1609Dot2::CertificateBase &p_cert, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y, + OCTETSTRING &p_public_comp_key, INTEGER &p_public_comp_key_mode, ec_elliptic_curves* p_signing_algorithm) { + loggers::get_instance().log_msg(">>> security_services_its::extract_verification_keys: ", p_cert); + + if (p_cert.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_verificationKey)) { // Explicit certificate + if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP256)) { + *p_signing_algorithm = ec_elliptic_curves::nist_p_256; + if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().compressed__y__0(); + security_ecc ecc(ec_elliptic_curves::nist_p_256, p_public_comp_key, ecc_compressed_mode::compressed_y_0); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(0); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().ischosen( + Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().compressed__y__1(); + security_ecc ecc(ec_elliptic_curves::nist_p_256, p_public_comp_key, ecc_compressed_mode::compressed_y_1); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(1); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().ischosen( + Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + security_ecc ecc(ec_elliptic_curves::nist_p_256, p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().x(), + p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().y()); + p_public_comp_key = ecc.public_key_compressed(); + p_public_comp_key_mode = INTEGER((int)ecc.public_key_compressed_mode()); + p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().x(); + p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().uncompressedP256().y(); + } else { + loggers::get_instance().error("security_services_its::extract_verification_keys: Unsupported ecdsaNistP256 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP256().get_selection()); + return -1; + } + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP256r1)) { + *p_signing_algorithm = ec_elliptic_curves::brainpool_p_256_r1; + if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().ischosen( + Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().compressed__y__0(); + security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p_public_comp_key, ecc_compressed_mode::compressed_y_0); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(0); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().ischosen( + Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().compressed__y__1(); + security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p_public_comp_key, ecc_compressed_mode::compressed_y_1); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(1); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().ischosen( + Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().uncompressedP256().x(); + p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().uncompressedP256().y(); + } else { + loggers::get_instance().error("security_services_its::extract_verification_keys: Unsupported ecdsaBrainpoolP256r1 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP256r1().get_selection()); + return -1; + } + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP384r1)) { + *p_signing_algorithm = ec_elliptic_curves::brainpool_p_384_r1; + if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().ischosen( + Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().compressed__y__0(); + security_ecc ecc(ec_elliptic_curves::brainpool_p_384_r1, p_public_comp_key, ecc_compressed_mode::compressed_y_0); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(0); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().ischosen( + Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().compressed__y__1(); + security_ecc ecc(ec_elliptic_curves::brainpool_p_384_r1, p_public_comp_key, ecc_compressed_mode::compressed_y_1); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(1); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().ischosen( + Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { + p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().uncompressedP384().x(); + p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().uncompressedP384().y(); + } else { + loggers::get_instance().error("security_services_its::extract_verification_keys: Unsupported ecdsaBrainpoolP384r1 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaBrainpoolP384r1().get_selection()); + return -1; + } + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP384)) { + *p_signing_algorithm = ec_elliptic_curves::nist_p_384; + if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().ischosen( + Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().compressed__y__0(); + security_ecc ecc(ec_elliptic_curves::nist_p_384, p_public_comp_key, ecc_compressed_mode::compressed_y_0); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(0); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().ischosen( + Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().compressed__y__1(); + security_ecc ecc(ec_elliptic_curves::nist_p_384, p_public_comp_key, ecc_compressed_mode::compressed_y_1); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(1); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().ischosen( + Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { + p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().uncompressedP384().x(); + p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().uncompressedP384().y(); + } else { + loggers::get_instance().error("security_services_its::extract_verification_keys: Unsupported ecdsaNistP384 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecdsaNistP384().get_selection()); + return -1; + } + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecsigSm2)) { + *p_signing_algorithm = ec_elliptic_curves::sm2_p_256; + if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecsigSm2().ischosen( + Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecsigSm2().compressed__y__0(); + security_ecc ecc(ec_elliptic_curves::sm2_p_256, p_public_comp_key, ecc_compressed_mode::compressed_y_0); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(0); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecsigSm2().ischosen( + Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + p_public_comp_key = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecsigSm2().compressed__y__1(); + security_ecc ecc(ec_elliptic_curves::sm2_p_256, p_public_comp_key, ecc_compressed_mode::compressed_y_1); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + p_public_comp_key_mode = INTEGER(1); + } else if (p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecsigSm2().ischosen( + Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + p_public_key_x = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecsigSm2().uncompressedP256().x(); + p_public_key_y = p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecsigSm2().uncompressedP256().y(); + } else { + loggers::get_instance().error("security_services_its::extract_verification_keys: Unsupported ecsigSm2 VerificationKey point type %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().ecsigSm2().get_selection()); + return -1; + } + } else { + loggers::get_instance().error("security_services_its::extract_verification_keys: Unsupported VerificationKey curve %d", p_cert.toBeSigned().verifyKeyIndicator().verificationKey().get_selection()); + return -1; + } + } else if (p_cert.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_reconstructionValue)) { // Implicit certificate + // Sanity checks + if (p_cert.signature__().ispresent()) { + loggers::get_instance().error("security_services_its::extract_verification_keys: Inconsistent implicit certificate, discard message"); + return -1; + } + // Rebuild signing keys + // 1. Load certificate issuer + std::string certificate_issuer_id; + if (_security_db.get()->get_certificate_id(p_cert.issuer().sha256AndDigest(), certificate_issuer_id) == -1) { + // Request for the issuer and discard this message + _unknown_certificate = OCTETSTRING(3, static_cast(p_cert.issuer().sha256AndDigest()) + p_cert.issuer().sha256AndDigest().lengthof() - 3); + loggers::get_instance().error("security_services_its::extract_verification_keys: Implicit certificate issuer is unknown"); + return -1; + } + Ieee1609Dot2::CertificateBase certificate_issuer; + if (_security_db.get()->get_certificate(certificate_issuer_id, certificate_issuer) == -1) { + // Request for the issuer and discard this message + _unknown_certificate = OCTETSTRING(3, static_cast(p_cert.issuer().sha256AndDigest()) + p_cert.issuer().sha256AndDigest().lengthof() - 3); + loggers::get_instance().warning("security_services_its::extract_verification_keys: Cannot load implicit certificate issuer"); + return -1; + } + // 2. The signing algorithm is provided by the issuer certificate + if (!certificate_issuer.toBeSigned().verifyKeyIndicator().ischosen(Ieee1609Dot2::VerificationKeyIndicator::ALT_verificationKey)) { + loggers::get_instance().warning("security_services_its::extract_verification_keys: Inconsistent certificate issuer: Wrong VerificationKeyIndicator, discard message"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::extract_verification_keys: Implicit certificate issuer: ", certificate_issuer); + // 3. Retrieve the issuer signing key + const Ieee1609Dot2BaseTypes::PublicVerificationKey &b = certificate_issuer.toBeSigned().verifyKeyIndicator().verificationKey(); + OCTETSTRING issuer_sign_key_x; + OCTETSTRING issuer_sign_key_y; + OCTETSTRING issuer_sign_key_comp_key; // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) + if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaNistP256)) { + const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecdsaNistP256(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::nist_p_256, p, issuer_sign_key_comp_key, issuer_sign_key_x, issuer_sign_key_y); + *p_signing_algorithm = ec_elliptic_curves::nist_p_256; + } else if (b.ischosen(Ieee1609Dot2BaseTypes::PublicVerificationKey::ALT_ecdsaBrainpoolP256r1)) { + const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = b.ecdsaBrainpoolP256r1(); + security_services_its::fill_public_key_vectors(ec_elliptic_curves::brainpool_p_256_r1, p, issuer_sign_key_comp_key, issuer_sign_key_x, issuer_sign_key_y); + *p_signing_algorithm = ec_elliptic_curves::brainpool_p_256_r1; + } else { + loggers::get_instance().warning("security_services_its::extract_verification_keys: Incosistent certificate issuer: Wrong PublicVerificationKey, discard message"); + return -1; + } + // 4. Retrieve the reconstruction key key + const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p = p_cert.toBeSigned().verifyKeyIndicator().reconstructionValue(); + OCTETSTRING rv_key_x; + OCTETSTRING rv_key_y; + OCTETSTRING rv_comp_key; // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03) + security_services_its::fill_public_key_vectors(*p_signing_algorithm, p, rv_comp_key, rv_key_x, rv_key_y); + // Compute the hash of the toBeSigned + OCTETSTRING tbs; + etsi_ts103097_tobesigned_certificate_codec codec; + codec.encode(p_cert.toBeSigned(), tbs); + if (!tbs.is_bound()) { + loggers::get_instance().warning("security_services_its::extract_verification_keys: Failed to encode toBeSigned, discard message"); + return -1; + } + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Implicit encoded toBeSigned: ", tbs); + OCTETSTRING hash_tbs; + sha256 sha; + sha.generate(tbs, hash_tbs); + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Implicit hash(toBeSignedCertificate): ", hash_tbs); + OCTETSTRING hash_sha_256; + _security_db.get()->get_hash_sha_256(certificate_issuer_id, hash_sha_256); + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Implicit issuer hash: ", hash_sha_256); + OCTETSTRING input = hash_tbs + hash_sha_256; + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: input: ", input); + sha.generate(input, hash_tbs); + loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: joint hash: ", hash_tbs); + // Reconstruction of the public key. + security_ecc r_key(*p_signing_algorithm, rv_key_x, rv_key_y); // Reconstruction key + if (r_key.reconstruct_public_keys(hash_tbs, static_cast(issuer_sign_key_x), static_cast(issuer_sign_key_y), p_public_key_x, p_public_key_y, p_public_comp_key, p_public_comp_key_mode) == -1) { + loggers::get_instance().warning("security_services_its::extract_verification_keys: Failed to encode toBeSigned, discard message"); + return -1; + } + loggers::get_instance().log("security_services_its::extract_verification_keys: *p_signing_algorithm: '%d'", *p_signing_algorithm); + loggers::get_instance().log_msg("security_services_its::extract_verification_keys: public_key_x: ", p_public_key_x); + loggers::get_instance().log_msg("security_services_its::extract_verification_keys: public_key_y: ", p_public_key_y); + loggers::get_instance().log_msg("security_services_its::extract_verification_keys: public_comp_key: ", p_public_comp_key); + loggers::get_instance().log_msg("security_services_its::extract_verification_keys: public_comp_key_mode: ", p_public_comp_key_mode); + } else { + loggers::get_instance().error("security_services_its::extract_verification_keys: Unsupported variant"); + } + return 0; +} + +int security_services_its::extract_encryption_keys(const Ieee1609Dot2::CertificateBase &p_cert, OCTETSTRING &p_public_enc_key_x, OCTETSTRING &p_public_enc_key_y, + OCTETSTRING &p_public_enc_comp_key, INTEGER &p_public_enc_comp_key_mode) { + loggers::get_instance().log("security_services_its::extract_encryption_keys"); + + if (p_cert.toBeSigned().encryptionKey().ispresent()) { + const Ieee1609Dot2BaseTypes::PublicEncryptionKey &p = static_cast(p_cert.toBeSigned().encryptionKey()); + if (p.publicKey().ischosen(Ieee1609Dot2BaseTypes::BasePublicEncryptionKey::ALT_eciesNistP256)) { + if (p.publicKey().eciesNistP256().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + p_public_enc_comp_key = p.publicKey().eciesNistP256().compressed__y__0(); + security_ecc ecc(ec_elliptic_curves::nist_p_256, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_0); + p_public_enc_key_x = ecc.public_key_x(); + p_public_enc_key_y = ecc.public_key_y(); + p_public_enc_comp_key_mode = INTEGER(0); + } else if (p.publicKey().eciesNistP256().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + const OCTETSTRING &p_public_enc_comp_key = p.publicKey().eciesNistP256().compressed__y__1(); + security_ecc ecc(ec_elliptic_curves::nist_p_256, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_1); + p_public_enc_key_x = ecc.public_key_x(); + p_public_enc_key_y = ecc.public_key_y(); + p_public_enc_comp_key_mode = INTEGER(1); + } else if (p.publicKey().eciesNistP256().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + p_public_enc_key_x = p.publicKey().eciesNistP256().uncompressedP256().x(); + p_public_enc_key_y = p.publicKey().eciesNistP256().uncompressedP256().y(); + } else { + loggers::get_instance().error("security_services_its::extract_encryption_keys: Unsupported EncryptionKey"); + return -1; + } + } else if (p.publicKey().ischosen(Ieee1609Dot2BaseTypes::BasePublicEncryptionKey::ALT_eciesBrainpoolP256r1)) { + if (p.publicKey().eciesBrainpoolP256r1().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + p_public_enc_comp_key = p.publicKey().eciesBrainpoolP256r1().compressed__y__0(); + security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_0); + p_public_enc_key_x = ecc.public_key_x(); + p_public_enc_key_y = ecc.public_key_y(); + p_public_enc_comp_key_mode = INTEGER(0); + } else if (p.publicKey().eciesBrainpoolP256r1().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + p_public_enc_comp_key = p.publicKey().eciesBrainpoolP256r1().compressed__y__1(); + security_ecc ecc(ec_elliptic_curves::brainpool_p_256_r1, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_1); + p_public_enc_key_x = ecc.public_key_x(); + p_public_enc_key_y = ecc.public_key_y(); + p_public_enc_comp_key_mode = INTEGER(1); + } else if (p.publicKey().eciesBrainpoolP256r1().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + p_public_enc_key_x = p.publicKey().eciesBrainpoolP256r1().uncompressedP256().x(); + p_public_enc_key_y = p.publicKey().eciesBrainpoolP256r1().uncompressedP256().y(); + } else { + loggers::get_instance().error("security_services_its::extract_encryption_keys: Unsupported EncryptionKey"); + return -1; + } + // } else if (p.publicKey().ischosen(Ieee1609Dot2BaseTypes::BasePublicEncryptionKey::ALT_ecencSm2256)) { // FIXME FSCOM + // if (p.publicKey().ecencSm2().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + // p_public_enc_comp_key = p.publicKey().ecencSm2().compressed__y__0(); + // security_ecc ecc(ec_elliptic_curves::sm2_p_256, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_0); + // p_public_enc_key_x = ecc.public_key_x(); + // p_public_enc_key_y = ecc.public_key_y(); + // p_public_enc_comp_key_mode = INTEGER(0); + // } else if (p.publicKey().ecencSm2().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + // p_public_enc_comp_key = p.publicKey().ecencSm2().compressed__y__1(); + // security_ecc ecc(ec_elliptic_curves::sm2_p_256, p_public_enc_comp_key, ecc_compressed_mode::compressed_y_1); + // p_public_enc_key_x = ecc.public_key_x(); + // p_public_enc_key_y = ecc.public_key_y(); + // p_public_enc_comp_key_mode = INTEGER(1); + // } else if (p.publicKey().ecencSm2().ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + // p_public_enc_key_x = p.publicKey().ecencSm2().uncompressedP256().x(); + // p_public_enc_key_y = p.publicKey().ecencSm2().uncompressedP256().y(); + // } else { + // loggers::get_instance().error("security_services_its::extract_encryption_keys: Unsupported EncryptionKey"); + // return -1; + // } + } else { + loggers::get_instance().error("security_services_its::extract_encryption_keys: Unsupported EncryptionKey"); + return -1; + } + } else { + loggers::get_instance().warning("security_services_its::extract_encryption_keys: EncryptionKey omitted"); + p_public_enc_key_x = OCTETSTRING(0, nullptr); + p_public_enc_key_y = OCTETSTRING(0, nullptr); + p_public_enc_comp_key = OCTETSTRING(0, nullptr); + return 0; // Normal termination + } + + return 0; +} // End of method extract_encryption_keys + +int security_services_its::extract_and_store_certificate(const Ieee1609Dot2::CertificateBase &p_certificate, std::string &p_certificate_id) { + loggers::get_instance().log_msg(">>> security_services_its::extract_and_store_certificate: ", p_certificate); + + // Encode certificate + etsi_ts103097_certificate_codec codec; + OCTETSTRING enc_cert; + codec.encode(p_certificate, enc_cert); + if (enc_cert.lengthof() == 0) { + loggers::get_instance().warning("security_services_its::extract_and_store_certificate: Failed to encode certificate"); + return -1; + } + loggers::get_instance().log_msg("security_services_its::extract_and_store_certificate: Encoded certificate=", enc_cert); + OCTETSTRING hash_cert_sha_256; + hash_sha256(enc_cert, hash_cert_sha_256); + loggers::get_instance().log_msg("security_services_its::extract_and_store_certificate: hash_cert_sha_256= ", hash_cert_sha_256); + int result = -1; + if (p_certificate.issuer().ischosen(Ieee1609Dot2::IssuerIdentifier::ALT_sha256AndDigest)) { + // Calculate the hash according to the hashId + OCTETSTRING hash_cert(hash_cert_sha_256); + loggers::get_instance().log_msg("security_services_its::extract_and_store_certificate: hash_cert= ", hash_cert); + const OCTETSTRING hashed_id8 = substr(hash_cert, hash_cert.lengthof() - 8, 8); + // Retrieve the certificate identifier from digest + loggers::get_instance().log_msg("security_services_its::extract_and_store_certificate: Retrieve the certificate identifier from digest: ", hashed_id8); + result = _security_db.get()->get_certificate_id(hashed_id8, p_certificate_id); + if (result == -1) { // Not found in current DB + if (_security_cache.get()->get_certificate_id(hashed_id8, p_certificate_id) == -1) { // Not found in TS cache + loggers::get_instance().log_msg("security_services_its::extract_and_store_certificate: Store new certificate in cache: ", p_certificate); + // const std::vector v(static_cast(hashed_id8), static_cast(hashed_id8) + + // hashed_id8.lengthof()); p_certificate_id = converter::get_instance().bytes_to_hexa(v); + p_certificate_id = std::string(static_cast(hex2str(oct2hex(hashed_id8)))); + // Add it into the cache + OCTETSTRING public_key_x, public_key_y, public_comp_key; + INTEGER public_comp_key_mode; + ec_elliptic_curves signing_algorithm; + if (extract_verification_keys(p_certificate, public_key_x, public_key_y, public_comp_key, public_comp_key_mode, &signing_algorithm) == -1) { + loggers::get_instance().error("security_services_its::extract_and_store_certificate: Unsupported EncryptionKey"); + return -1; + } + // Add encryption keys + OCTETSTRING public_enc_key_x, public_enc_key_y, public_enc_comp_key; + INTEGER public_enc_comp_key_mode; + if (extract_encryption_keys(p_certificate, public_enc_key_x, public_enc_key_y, public_enc_comp_key, public_enc_comp_key_mode) == -1) { + loggers::get_instance().error("security_services_its::extract_and_store_certificate: Unsupported EncryptionKey"); + return -1; + } + // And store it into the cache + _security_cache.get()->store_certificate(signing_algorithm, CHARSTRING(p_certificate_id.c_str()), enc_cert, int2oct(0, 32), // No way to get the private key here + public_key_x, public_key_y, public_comp_key, public_comp_key_mode, hash_cert, hash_cert_sha_256, hashed_id8, + p_certificate.issuer().sha256AndDigest(), OCTETSTRING(0, nullptr), // Encryption private not used + public_enc_key_x, public_enc_key_y, public_enc_comp_key, public_enc_comp_key_mode); + } + } + } else if (p_certificate.issuer().ischosen(Ieee1609Dot2::IssuerIdentifier::ALT_sha384AndDigest)) { + // Calculate the hash according to the hashId + OCTETSTRING hash_cert; + hash_sha384(enc_cert, hash_cert); + loggers::get_instance().log_msg("security_services_its::extract_and_store_certificate: hash_cert= ", hash_cert); + const OCTETSTRING hashed_id8 = substr(hash_cert, hash_cert.lengthof() - 8, 8); + // Retrieve the certificate identifier from digest + loggers::get_instance().log("security_services_its::extract_and_store_certificate: Retrieve the certificate identifier from digest"); + result = _security_db.get()->get_certificate_id(hashed_id8, p_certificate_id); + if (result == -1) { + if (_security_cache.get()->get_certificate_id(hashed_id8, p_certificate_id) == -1) { + loggers::get_instance().log_msg("security_services_its::extract_and_store_certificate: Store new certificate in cache: ", p_certificate); + // const std::vector v(static_cast(hashed_id8), static_cast(hashed_id8) + + // hashed_id8.lengthof()); p_certificate_id = converter::get_instance().bytes_to_hexa(v); + p_certificate_id = std::string(static_cast(hex2str(oct2hex(hashed_id8)))); + // Add it into the cache + OCTETSTRING public_key_x, public_key_y, public_comp_key; + INTEGER public_comp_key_mode; + ec_elliptic_curves signing_algorithm; + if (extract_verification_keys(p_certificate, public_key_x, public_key_y, public_comp_key, public_comp_key_mode, &signing_algorithm) == -1) { + loggers::get_instance().error("security_services_its::extract_and_store_certificate: Unsupported EncryptionKey"); + return -1; + } + // Add encryption keys + OCTETSTRING public_enc_key_x, public_enc_key_y, public_enc_comp_key; + INTEGER public_enc_comp_key_mode; + if (extract_encryption_keys(p_certificate, public_enc_key_x, public_enc_key_y, public_enc_comp_key, public_enc_comp_key_mode) == -1) { + loggers::get_instance().error("security_services_its::extract_and_store_certificate: Unsupported EncryptionKey"); + return -1; + } + // And store it into the cache + _security_cache.get()->store_certificate(signing_algorithm, CHARSTRING(p_certificate_id.c_str()), enc_cert, int2oct(0, 48), // No way to get the private key here + public_key_x, public_key_y, public_comp_key, public_comp_key_mode, hash_cert, hash_cert_sha_256, hashed_id8, + p_certificate.issuer().sha384AndDigest(), OCTETSTRING(0, nullptr), // Encryption private not used + public_enc_key_x, public_enc_key_y, public_enc_comp_key, public_enc_comp_key_mode); + } + } + } else { + loggers::get_instance().error("security_services_its::extract_and_store_certificate: Unsupported issuer"); + return -1; + } + + return 0; +} // End of method extract_and_store_certificate + +int security_services_its::read_certificate(const CHARSTRING &p_certificate_id, OCTETSTRING &p_certificate) const { + return _security_db.get()->get_certificate(std::string(static_cast(p_certificate_id)), p_certificate); +} + +int security_services_its::read_certificate_digest(const CHARSTRING &p_certificate_id, OCTETSTRING &p_digest) const { + return _security_db.get()->get_hashed_id(std::string(static_cast(p_certificate_id)), p_digest); +} + +int security_services_its::read_certificate_hash(const CHARSTRING &p_certificate_id, OCTETSTRING &p_hash) const { + return _security_db.get()->get_hash(std::string(static_cast(p_certificate_id)), p_hash); +} + +int security_services_its::read_certificate_hash_sha_256(const CHARSTRING &p_certificate_id, OCTETSTRING &p_hash) const { + return _security_db.get()->get_hash_sha_256(std::string(static_cast(p_certificate_id)), p_hash); +} + +int security_services_its::read_certificate_from_digest(const OCTETSTRING &p_digest, CHARSTRING &p_certificate_id) const { + std::string certificate_id; + if (_security_db.get()->get_certificate_id(p_digest, certificate_id) != -1) { + p_certificate_id = CHARSTRING(certificate_id.c_str()); + return 0; + } + return -1; +} + +int security_services_its::read_certificate_from_hashed_id3(const OCTETSTRING &p_digest, CHARSTRING &p_certificate_id) const { + std::string certificate_id; + if (_security_db.get()->get_certificate_hashed_id3(p_digest, certificate_id) != -1) { + p_certificate_id = CHARSTRING(certificate_id.c_str()); + return 0; + } + return -1; +} + +int security_services_its::read_private_key(const CHARSTRING &p_certificate_id, OCTETSTRING &p_private_key) const { + return _security_db.get()->get_private_key(std::string(static_cast(p_certificate_id)), p_private_key); +} + +int security_services_its::read_public_keys(const CHARSTRING &p_certificate_id, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y) const { + return _security_db.get()->get_public_keys(std::string(static_cast(p_certificate_id)), p_public_key_x, p_public_key_y); +} + +int security_services_its::read_private_enc_key(const CHARSTRING &p_certificate_id, OCTETSTRING &p_private_enc_key) const { + return _security_db.get()->get_private_enc_key(std::string(static_cast(p_certificate_id)), p_private_enc_key); +} + +void security_services_its::fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p_ecc_point, + OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y) { + loggers::get_instance().log_msg(">>> security_services_its::fill_public_key_vectors: ", p_ecc_point); + + if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__0)) { + p_public_comp_key = int2oct(2, 1) + p_ecc_point.compressed__y__0(); + security_ecc ecc(p_elliptic_curve, p_ecc_point.compressed__y__0(), ecc_compressed_mode::compressed_y_0); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + } else if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_compressed__y__1)) { + p_public_comp_key = int2oct(3, 1) + p_ecc_point.compressed__y__1(); + security_ecc ecc(p_elliptic_curve, p_ecc_point.compressed__y__1(), ecc_compressed_mode::compressed_y_1); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + } else if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP256CurvePoint::ALT_uncompressedP256)) { + p_public_key_x = p_ecc_point.uncompressedP256().x(); + p_public_key_y = p_ecc_point.uncompressedP256().y(); + p_public_comp_key = int2oct(0, 33); + } else { + p_public_key_x = int2oct(0, 32); + p_public_key_y = int2oct(0, 32); + p_public_comp_key = int2oct(0, 33); + } +} + +void security_services_its::fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP384CurvePoint &p_ecc_point, + OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y) { + // loggers::get_instance().log_msg(">>> security_services_its::fill_public_key_vectors: ", p_ecc_point); + + if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__0)) { + p_public_comp_key = int2oct(2, 1) + p_ecc_point.compressed__y__0(); + security_ecc ecc(p_elliptic_curve, p_ecc_point.compressed__y__0(), ecc_compressed_mode::compressed_y_0); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + } else if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_compressed__y__1)) { + p_public_comp_key = int2oct(3, 1) + p_ecc_point.compressed__y__1(); + security_ecc ecc(p_elliptic_curve, p_ecc_point.compressed__y__1(), ecc_compressed_mode::compressed_y_1); + p_public_key_x = ecc.public_key_x(); + p_public_key_y = ecc.public_key_y(); + } else if (p_ecc_point.ischosen(Ieee1609Dot2BaseTypes::EccP384CurvePoint::ALT_uncompressedP384)) { + p_public_key_x = p_ecc_point.uncompressedP384().x(); + p_public_key_y = p_ecc_point.uncompressedP384().y(); + p_public_comp_key = int2oct(0, 49); + } else { + p_public_key_x = int2oct(0, 48); + p_public_key_y = int2oct(0, 48); + p_public_comp_key = int2oct(0, 49); + } +} diff --git a/ccsrc/Protocols/Security/security_services.hh b/ccsrc/Protocols/Security/security_services_its.hh similarity index 78% rename from ccsrc/Protocols/Security/security_services.hh rename to ccsrc/Protocols/Security/security_services_its.hh index ad4bc3abd17c1629ccdcadc7a1d9b5e67563a134..f458fe0f60d7cfbf7bfd6f0edd1d3eb1421d42b6 100644 --- a/ccsrc/Protocols/Security/security_services.hh +++ b/ccsrc/Protocols/Security/security_services_its.hh @@ -14,8 +14,11 @@ class OCTETSTRING; //! TITAN forward declaration class CHARSTRING; //! TITAN forward declaration namespace Ieee1609Dot2BaseTypes { - class HashAlgorithm; //! TITAN forward declaration - class Signature; //! TITAN forward declaration + class EccP256CurvePoint; //! TITAN forward declaration + class EccP384CurvePoint; //! TITAN forward declaration + class HashAlgorithm; //! TITAN forward declaration + class Signature; //! TITAN forward declaration + class SequenceOfPsidSsp; //! TITAN forward declaration } // namespace Ieee1609Dot2BaseTypes namespace Ieee1609Dot2 { @@ -25,21 +28,23 @@ namespace Ieee1609Dot2 { class SignedData; //! TITAN forward declaration class EncryptedData; //! TITAN forward declaration class SignerIdentifier; //! TITAN forward declaration + class VerificationKeyIndicator; + //! TITAN forward declaration } // namespace Ieee1609Dot2 /*! - * \class security_services + * \class security_services_its * \brief This class provides security services for all layers as specified in TSI TS 102 723-8 and ETSI TS 103 097 * \remark Singleton pattern */ -class security_services { +class security_services_its { static constexpr unsigned int ProtocolVersion = 3; /*! * \brief Unique static object reference of this class */ - static security_services *instance; + static security_services_its *instance; params_its _params; bool _setup_done; @@ -58,11 +63,11 @@ class security_services { /*! * \brief Default private ctor */ - security_services(); + security_services_its(); /*! * \brief Default private dtor */ - ~security_services() { + ~security_services_its() { _ec_keys_enc.reset(nullptr); _security_db.reset(nullptr); _security_cache.reset(nullptr); @@ -76,9 +81,9 @@ public: /*! \publicsection */ /*! * \brief Public accessor to the single object reference */ - inline static security_services &get_instance() { + inline static security_services_its &get_instance() { if (instance == NULL) - instance = new security_services(); + instance = new security_services_its(); return *instance; }; @@ -107,7 +112,7 @@ public: /*! \publicsection */ int setup(params_its &p_params); - int store_certificate(const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, + int store_certificate(const ec_elliptic_curves p_signing_algorithm, const CHARSTRING &p_cert_id, const OCTETSTRING &p_cert, const OCTETSTRING &p_private_key, const OCTETSTRING &p_public_key_x, const OCTETSTRING &p_public_key_y, const OCTETSTRING &p_public_comp_key, const INTEGER &p_public_comp_key_mode, const OCTETSTRING &p_hash, const OCTETSTRING &p_hash_sha_256, const OCTETSTRING &p_hashid8, const OCTETSTRING &p_issuer, const OCTETSTRING &p_private_enc_key, const OCTETSTRING &p_public_enc_key_x, const OCTETSTRING &p_public_enc_key_y, @@ -126,6 +131,7 @@ public: /*! \publicsection */ int read_certificate_from_digest(const OCTETSTRING &p_digest, CHARSTRING &p_certificate_id) const; int read_certificate_from_hashed_id3(const OCTETSTRING &p_digest, CHARSTRING &p_certificate_id) const; int read_private_key(const CHARSTRING &p_certificate_id, OCTETSTRING &p_private_key) const; + int read_public_keys(const CHARSTRING &p_certificate_id, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y) const; int read_private_enc_key(const CHARSTRING &p_certificate_id, OCTETSTRING &p_private_enc_key) const; /*! @@ -154,6 +160,19 @@ public: /*! \publicsection */ const int get_protocol_version() const { return ProtocolVersion; }; + /*! + * \fn int fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p_ecc_point, OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y); + * \brief Initialize public key vectors, based on 256 bits curve + */ + static void fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p_ecc_point, + OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y); + /*! + * \fn int fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP256CurvePoint &p_ecc_point, OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y); + * \brief Initialize public key vectors, based on 384 bits curve + */ + static void fill_public_key_vectors(const ec_elliptic_curves p_elliptic_curve, const Ieee1609Dot2BaseTypes::EccP384CurvePoint &p_ecc_point, + OCTETSTRING &p_public_comp_key, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y); + private: /*! * \fn int process_ieee_1609_dot2_content(const Ieee1609Dot2::Ieee1609Dot2Content& p_ieee_1609_dot2_content, const bool p_verify, OCTETSTRING& @@ -169,6 +188,7 @@ private: params_its &p_params); int process_ieee_1609_dot2_encrypted_data(const Ieee1609Dot2::EncryptedData &p_encrypted_data, const bool p_verify, OCTETSTRING &p_unsecured_payload, params_its &p_params); + int retrieve_ssps(const Ieee1609Dot2BaseTypes::SequenceOfPsidSsp& p_psid_ssps, params_its &p_params); int sign_tbs_data(const Ieee1609Dot2::ToBeSignedData &p_tbs_data, const Ieee1609Dot2BaseTypes::HashAlgorithm &p_hashAlgorithm, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params); @@ -178,6 +198,7 @@ private: int sign_ecdsa_nistp384(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params); int sign_ecdsa_brainpoolp256r1(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params); int sign_ecdsa_brainpoolp384r1(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params); + int sign_ecdsa_sm2p256(const OCTETSTRING &p_hash, Ieee1609Dot2BaseTypes::Signature &p_signature, params_its &p_params); int verify_sign_ecdsa_nistp256(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, const std::string &p_certificate_id, params_its &p_params); int verify_sign_ecdsa_nistp384(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, const std::string &p_certificate_id, @@ -186,10 +207,12 @@ private: params_its &p_params); int verify_sign_ecdsa_brainpoolp384r1(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, const std::string &p_certificate_id, params_its &p_params); + int verify_sign_ecdsa_sm2p256(const OCTETSTRING &p_hash, const Ieee1609Dot2BaseTypes::Signature &p_signature, const std::string &p_certificate_id, + params_its &p_params); int extract_verification_keys(const Ieee1609Dot2::CertificateBase &p_cert, OCTETSTRING &p_public_key_x, OCTETSTRING &p_public_key_y, - OCTETSTRING &p_public_comp_key, INTEGER &p_public_comp_key_mode); + OCTETSTRING &p_public_comp_key, INTEGER &p_public_comp_key_mode, ec_elliptic_curves* p_signing_algorithm); int extract_encryption_keys(const Ieee1609Dot2::CertificateBase &p_cert, OCTETSTRING &p_public_enc_key_x, OCTETSTRING &p_public_enc_key_y, OCTETSTRING &p_public_enc_comp_key, INTEGER &p_public_enc_comp_key_mode); int extract_and_store_certificate(const Ieee1609Dot2::CertificateBase &p_certificate, std::string &p_certificate_id); -}; // End of class security_services +}; // End of class security_services_its diff --git a/ccsrc/Protocols/Security/sha256.cc b/ccsrc/Protocols/Security/sha256.cc deleted file mode 100644 index dc8c7f5801f822a36a9ed5b1b11c66c62e1728c4..0000000000000000000000000000000000000000 --- a/ccsrc/Protocols/Security/sha256.cc +++ /dev/null @@ -1,39 +0,0 @@ -/*! - * \file sha256.cc - * \brief Source file for SHA-256 helper methods. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#include - -#include "sha256.hh" - -int sha256::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { - // Sanity check - if (p_buffer.lengthof() == 0) { - p_hash = get_sha256_empty_string(); - return 0; - } - - return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); -} - -int sha256::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { - // Sanity check - if ((p_buffer == nullptr) || (p_length == 0)) { - p_hash = get_sha256_empty_string(); - return 0; - } - - // Resize data buffer - p_hash = int2oct(0, SHA256_DIGEST_LENGTH); - // Compute the hash value - ::SHA256_Init(&_ctx); - ::SHA256_Update(&_ctx, p_buffer, p_length); - ::SHA256_Final((unsigned char*)static_cast(p_hash), &_ctx); - return 0; -}; diff --git a/ccsrc/Protocols/Security/sha256.hh b/ccsrc/Protocols/Security/sha256.hh deleted file mode 100644 index 0de9a8890a4aff71ccdb2a4992b37d1c7c7e160a..0000000000000000000000000000000000000000 --- a/ccsrc/Protocols/Security/sha256.hh +++ /dev/null @@ -1,66 +0,0 @@ -/*! - * \file sha256.hh - * \brief Header file for SHA-256 helper methods. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include -#include - -class OCTETSTRING; //! TITAN forward declaration - -/*! - * \class sha256 - * \brief This class provides description of SHA-256 helper methods - */ -class sha256 { - SHA256_CTX _ctx; //! SHA context -public: - /*! - * \brief Default constructor - * Create a new instance of the sha256 class - */ - explicit sha256() : _ctx{} {}; - /*! - * \brief Default destructor - */ - virtual ~sha256(){}; - - /*! - * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-256 hash - * \param[out] p_hash The SHA-256 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); - - /*! - * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-256 hash - * \param[in] The length of the data buffer - * \param[out] p_hash The SHA-256 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); - - /*! - * \fn const OCTETSTRING get_sha256_empty_string() const; - * \brief Return the SHA-256 of an empty string - * \return The SHA-256 of an empty string - */ - inline const OCTETSTRING get_sha256_empty_string() const { - static unsigned char sha256_empty_string[] = { - 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, - 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; //! SHA-256 of an empty string - return OCTETSTRING(32, sha256_empty_string); - }; - -}; // End of class sha256 diff --git a/ccsrc/Protocols/Security/sha384.cc b/ccsrc/Protocols/Security/sha384.cc deleted file mode 100644 index 285205101953307aec1e7623a34167b2b4d27cea..0000000000000000000000000000000000000000 --- a/ccsrc/Protocols/Security/sha384.cc +++ /dev/null @@ -1,49 +0,0 @@ -/*! - * \file sha384.cc - * \brief Sorce file for SHA-384 helper methods. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#include - -#include - -#include "sha384.hh" - -int sha384::generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash) { - // Sanity check - if (p_buffer.lengthof() == 0) { - p_hash = get_sha384_empty_string(); - return 0; - } - - return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); -} - -int sha384::generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash) { - // Sanity check - if ((p_buffer == nullptr) || (p_length == 0)) { - p_hash = get_sha384_empty_string(); - return 0; - } - - // Resize data buffer - p_hash = int2oct(0, SHA384_DIGEST_LENGTH); - // Compute the hash value - ::SHA384_Init(&_ctx); - ::SHA384_Update(&_ctx, p_buffer, p_length); - ::SHA384_Final((unsigned char *)static_cast(p_hash), &_ctx); - return 0; -} - -const OCTETSTRING sha384::get_sha384_empty_string() const { - static unsigned char - sha384_empty_string[] = {0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, - 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, - 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b}; //! SHA-384 of an empty string - return OCTETSTRING(48, sha384_empty_string); -} diff --git a/ccsrc/Protocols/Security/sha384.hh b/ccsrc/Protocols/Security/sha384.hh deleted file mode 100644 index 525763c73aeeea441e13595f355ac19b3ff1bf73..0000000000000000000000000000000000000000 --- a/ccsrc/Protocols/Security/sha384.hh +++ /dev/null @@ -1,60 +0,0 @@ -/*! - * \file sha384.hh - * \brief Header file for SHA-384 helper methods. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include -#include - -class OCTETSTRING; //! TITAN forward declaration - -/*! - * \class sha384 - * \brief This class provides description of SHA-384 helper methods - */ -class sha384 { - SHA512_CTX _ctx; //! SHA context -public: //! \publicsection - /*! - * \brief Default constructor - * Create a new instance of the sha384 class - */ - explicit sha384() : _ctx{} {}; - /*! - * \brief Default destructor - */ - virtual ~sha384(){}; - - /*! - * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-384 hash - * \param[out] p_hash The SHA-384 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); - - /*! - * \fn int generate(const OCTETSTRING p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-384 hash - * \param[in] The length of the data buffer - * \param[out] p_hash The SHA-384 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); - - /*! - * \fn const OCTETSTRING get_sha384_empty_string() const; - * \brief Return the SHA-384 of an empty string - * \return The SHA-384 of an empty string - */ - const OCTETSTRING get_sha384_empty_string() const; -}; // End of class sha384 diff --git a/ccsrc/Protocols/UpperTester/module.mk b/ccsrc/Protocols/UpperTester/module.mk index c8ea2949aaca0448bd13c0750fd13ca29289ab99..027b1ef4d6aa45d5e773f57c09c6285b7da2d716 100644 --- a/ccsrc/Protocols/UpperTester/module.mk +++ b/ccsrc/Protocols/UpperTester/module.mk @@ -23,6 +23,10 @@ ifeq (AtsPki, $(ATS)) sources += uppertester_pki_codec.cc uppertester_pki_layer.cc uppertester_cam_codec.cc endif +ifeq (AtsMBR, $(ATS)) +sources += uppertester_mbr_codec.cc uppertester_mbr_layer.cc uppertester_cam_codec.cc +endif + ifeq (AtsSecurity, $(ATS)) sources += uppertester_cam_codec.cc uppertester_cam_layer.cc \ uppertester_denm_codec.cc uppertester_denm_layer.cc \ @@ -37,6 +41,7 @@ sources += uppertester_cam_codec.cc uppertester_cam_layer.cc \ uppertester_mapem_spatem_codec.cc uppertester_mapem_spatem_layer.cc \ UpperTesterRtcmemCodec.cc UpperTesterRtcmemLayer.cc \ uppertester_pki_codec.cc uppertester_pki_layer.cc \ + uppertester_mbr_codec.cc uppertester_mbr_layer.cc \ endif diff --git a/ccsrc/Protocols/UpperTester/uppertester_denm_codec.cc b/ccsrc/Protocols/UpperTester/uppertester_denm_codec.cc index 3c3646feb906aa9c247abb1884a6afafb7a366b4..88691309ce22f1f69d0ce32f039b2b2e66a213f7 100644 --- a/ccsrc/Protocols/UpperTester/uppertester_denm_codec.cc +++ b/ccsrc/Protocols/UpperTester/uppertester_denm_codec.cc @@ -178,7 +178,7 @@ int uppertester_denm_codec::encode_(const Base_Type &type, const TTCN_Typedescri const OPTIONAL &o = dynamic_cast &>(type); const INTEGER & i = static_cast(*o.get_opt_value()); encoding_buffer.put_string(int2oct(i, 2)); - } else if (s.rfind(".originatingStationID") != string::npos) { + } else if (s.rfind(".originatingStationId") != string::npos) { const INTEGER &i = static_cast(type); loggers::get_instance().log_msg("uppertester_denm_codec::encode_: i=", i); encoding_buffer.put_string(int2oct(i, 4)); @@ -256,7 +256,7 @@ int uppertester_denm_codec::decode(const OCTETSTRING &data, LibItsDenm__TypesAnd ptr += 1; OCTETSTRING os(4, ptr); ptr += 4; - r.actionId().originatingStationID() = oct2int(os); + r.actionId().originatingStationId() = oct2int(os); os = OCTETSTRING(2, ptr); r.actionId().sequenceNumber() = oct2int(os); msg.utDenmTriggerResult() = r; @@ -267,7 +267,7 @@ int uppertester_denm_codec::decode(const OCTETSTRING &data, LibItsDenm__TypesAnd ptr += 1; OCTETSTRING os(4, ptr); ptr += 4; - r.actionId().originatingStationID() = oct2int(os); + r.actionId().originatingStationId() = oct2int(os); os = OCTETSTRING(2, ptr); r.actionId().sequenceNumber() = oct2int(os); msg.utDenmUpdateResult() = r; diff --git a/ccsrc/Protocols/UpperTester/uppertester_denm_layer.cc b/ccsrc/Protocols/UpperTester/uppertester_denm_layer.cc index c66e67c4236d063fc1a5021c5d89b94865915b17..128e5cb39151bbf9bc0eea6b774c15f6417da170 100644 --- a/ccsrc/Protocols/UpperTester/uppertester_denm_layer.cc +++ b/ccsrc/Protocols/UpperTester/uppertester_denm_layer.cc @@ -73,7 +73,7 @@ void uppertester_denm_layer::sendMsg(const LibItsDenm__TypesAndValues::UtDenmTri loggers::get_instance().log_msg(">>> uppertester_denm_layer::sendMsg", send_par); if (_params[params_its::loopback].compare("1") == 0) { - LibItsDenm__TypesAndValues::UtDenmTriggerResult trigger_result(true, ITS__Container::ActionID(std::stoi(_params[params_its::station_id]), 1)); + LibItsDenm__TypesAndValues::UtDenmTriggerResult trigger_result(true, ETSI__ITS__CDD::ActionId(std::stoi(_params[params_its::station_id]), 1)); LibItsDenm__TypesAndValues::UtDenmResults ut_denm_results; ut_denm_results.utDenmTriggerResult() = trigger_result; to_all_upper_ports(ut_denm_results, p_params); @@ -90,7 +90,7 @@ void uppertester_denm_layer::sendMsg(const LibItsDenm__TypesAndValues::UtDenmUpd loggers::get_instance().log_msg(">>> uppertester_denm_layer::sendMsg", send_par); if (_params[params_its::loopback].compare("1") == 0) { - LibItsDenm__TypesAndValues::UtDenmUpdateResult update_result(true, ITS__Container::ActionID(std::stoi(_params[params_its::station_id]), 1)); + LibItsDenm__TypesAndValues::UtDenmUpdateResult update_result(true, ETSI__ITS__CDD::ActionId(std::stoi(_params[params_its::station_id]), 1)); LibItsDenm__TypesAndValues::UtDenmResults ut_denm_results; ut_denm_results.utDenmUpdateResult() = update_result; to_all_upper_ports(ut_denm_results, p_params); diff --git a/ccsrc/Protocols/UpperTester/uppertester_mbr_codec.cc b/ccsrc/Protocols/UpperTester/uppertester_mbr_codec.cc new file mode 100644 index 0000000000000000000000000000000000000000..0ee08586c5bae963185e264a1b58c029212ec541 --- /dev/null +++ b/ccsrc/Protocols/UpperTester/uppertester_mbr_codec.cc @@ -0,0 +1,136 @@ +#include +//#include + +#include "loggers.hh" +#include "uppertester_mbr_codec.hh" + +#include "LibItsMbr_TestSystem.hh" +#include "LibItsMbr_TypesAndValues.hh" + +//#include "pki_codec.hh" + +template class OPTIONAL; +class TTCN_EncDec; + +unsigned char uppertester_mbr_codec::c_utMbrInitialize = 0x00; +unsigned char uppertester_mbr_codec::c_utMbrInitializeResult = 0x01; +unsigned char uppertester_mbr_codec::c_utMbrTrigger = 0xF0; +unsigned char uppertester_mbr_codec::c_utMbrTriggerResult = 0xF1; +unsigned char uppertester_mbr_codec::c_utMbrEventInd = 0xF2; + +int uppertester_mbr_codec::encode(const Record_Type &msg, OCTETSTRING &data) { + loggers::get_instance().log_msg(">>> uppertester_mbr_codec::encode (1): ", (const Record_Type &)msg); + + TTCN_EncDec::clear_error(); + TTCN_Buffer encoding_buffer; + if (std::string(msg.get_descriptor()->name).compare("@LibItsMbr_TypesAndValues.UtMbrInitialize") == 0) { + encoding_buffer.put_c(static_cast(uppertester_mbr_codec::c_utMbrInitialize)); + } else { // Error + data = OCTETSTRING(0, nullptr); + loggers::get_instance().warning("<<< uppertester_mbr_codec::encode: Failed to encode UT message"); + return -1; + } + encode_(msg, *msg.get_descriptor(), encoding_buffer); + data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()); + loggers::get_instance().log_msg("<<< uppertester_mbr_codec::encode: data=", data); + return 0; +} + +int uppertester_mbr_codec::encode(const LibItsMbr__TypesAndValues::UtMbrTrigger &msg, OCTETSTRING &data) { + loggers::get_instance().log_msg(">>> uppertester_mbr_codec::encode (2): ", (const Record_Type &)msg); + + TTCN_EncDec::clear_error(); + TTCN_Buffer encoding_buffer; + // const Record_Type *type; + encoding_buffer.put_c(static_cast(uppertester_mbr_codec::c_utMbrTrigger)); + encoding_buffer.put_c(static_cast(msg.targetId())); + encoding_buffer.put_c(static_cast(msg.cause())); + data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()); + loggers::get_instance().log_msg("<<< uppertester_mbr_codec::encode: data=", data); + return 0; +} + +int uppertester_mbr_codec::encode(const LibItsMbr__TypesAndValues::UtMbrEventInd &msg, OCTETSTRING &data) { + loggers::get_instance().log_msg(">>> uppertester_mbr_codec::encode (3): ", (const Record_Type &)msg); + + TTCN_EncDec::clear_error(); + TTCN_Buffer encoding_buffer; + // const Record_Type *type; + encoding_buffer.put_c(static_cast(uppertester_mbr_codec::c_utMbrEventInd)); + loggers::get_instance().error("uppertester_mbr_codec::encode: To be implemented"); +// encoding_buffer.put_c(static_cast(msg.state())); + data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()); + loggers::get_instance().log_msg("<<< uppertester_mbr_codec::encode: data=", data); + return 0; +} + +int uppertester_mbr_codec::encode_(const Base_Type &type, const TTCN_Typedescriptor_t &field_descriptor, TTCN_Buffer &encoding_buffer) { + loggers::get_instance().log(">>> uppertester_mbr_codec::encode_: processing %s/%s/%p", type.get_descriptor()->name, field_descriptor.name, + dynamic_cast(&type)); + loggers::get_instance().log_msg(">>> uppertester_mbr_codec::encode_: ", type); + + if (dynamic_cast(&type) != NULL) { + const Record_Type &r = (const Record_Type &)type; + loggers::get_instance().log("uppertester_mbr_codec::encode_: processing Record_Type %s", r.get_descriptor()->name); + for (int i = 0; i < r.get_count(); i++) { + loggers::get_instance().log("uppertester_mbr_codec::encode_: processing %s/%s/%s - %d (1 ==> use dynamic_cast) - %d", r.fld_name(i), + r.fld_descr(i)->name, r.get_at(i)->get_descriptor()->name, r.get_at(i)->is_optional(), r.get_at(i)->is_present()); + if (r.get_at(i)->is_present()) { + if (encode_(*r.get_at(i), *r.fld_descr(i), encoding_buffer) == -1) { + loggers::get_instance().warning("uppertester_mbr_codec::encode_: -1 result code returned"); + return -1; + } + } else if (std::string(r.fld_name(i)).compare("alacarte") == 0) { + // Add empty field length + loggers::get_instance().log("uppertester_mbr_codec::encode_: alacarte is missing, add 0x00"); + encoding_buffer.put_c(0x00); + } + } // End of 'for' statement + } else { + std::string s(field_descriptor.name); + loggers::get_instance().log("uppertester_mbr_codec::encode_: field to process %s", s.c_str()); + + loggers::get_instance().log("uppertester_mbr_codec::encode_ (else): processing type %s/%s", type.get_descriptor()->name, field_descriptor.name); + type.encode(field_descriptor, encoding_buffer, TTCN_EncDec::CT_RAW); + } + + loggers::get_instance().log_to_hexa("<<>> uppertester_mbr_codec::decode: decoding_buffer=", decoding_buffer); + // decode_(msg, *msg.get_descriptor(), decoding_buffer); + + loggers::get_instance().log_msg("<<< uppertester_mbr_codec::decode: ", (const Record_Type &)msg); + return 0; +} + +std::unique_ptr uppertester_mbr_codec::decode(const OCTETSTRING &data, params_its *params) { + + std::unique_ptr result; + + const unsigned char * ptr = static_cast(data); + if (*ptr == uppertester_mbr_codec::c_utMbrInitializeResult) { + LibItsMbr__TypesAndValues::UtMbrResults msg; + msg.utMbrInitializeResult() = BOOLEAN(*(ptr + 1) == 0x01); + result.reset((Base_Type *)msg.clone()); + } else if (*ptr == uppertester_mbr_codec::c_utMbrTriggerResult) { + LibItsMbr__TypesAndValues::UtMbrResults msg; + msg.utMbrTriggerResult() = BOOLEAN(*(ptr + 1) == 0x01); + result.reset((Base_Type *)msg.clone()); + } else if (*ptr == uppertester_mbr_codec::c_utMbrEventInd) { + LibItsMbr__TypesAndValues::UtMbrEventInd msg; + loggers::get_instance().error("uppertester_mbr_codec::decode: To be implemented"); +// msg.state() = INTEGER(static_cast(*(ptr + 1))); + result.reset((Base_Type *)msg.clone()); + } else { + result.reset(nullptr); + } + + return result; +} diff --git a/ccsrc/Protocols/UpperTester/uppertester_mbr_codec.hh b/ccsrc/Protocols/UpperTester/uppertester_mbr_codec.hh new file mode 100644 index 0000000000000000000000000000000000000000..4876df973b0d5126059a23a7e304b84ff59e3060 --- /dev/null +++ b/ccsrc/Protocols/UpperTester/uppertester_mbr_codec.hh @@ -0,0 +1,49 @@ +/*! + * \file uppertester_mbr_codec.hh + * \brief Header file for ITS UpperTester PKI codec definition. + * \author ETSI TTF T027 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include + +#include "codec.hh" +#include "params.hh" + +class Base_Type; +class Record_Type; +class TTCN_Typedescriptor_t; +class TTCN_Buffer; + +namespace LibItsMbr__TypesAndValues { + class UtMbrTrigger; + class UtMbrResults; + class UtMbrEventInd; +} // namespace LibItsMbr__TypesAndValues + +class uppertester_mbr_codec : public codec { +public: + static unsigned char c_utMbrInitialize; + static unsigned char c_utMbrInitializeResult; + static unsigned char c_utMbrTriggerResult; + static unsigned char c_utMbrEventInd; + static unsigned char c_utMbrTrigger; + +private: + int encode_(const Base_Type &type, const TTCN_Typedescriptor_t &field_descriptor, TTCN_Buffer &encoding_buffer); + +public: + uppertester_mbr_codec() : codec(){}; + virtual ~uppertester_mbr_codec(){}; + + virtual int encode(const Record_Type &, OCTETSTRING &data); + int encode(const LibItsMbr__TypesAndValues::UtMbrTrigger &, OCTETSTRING &data); + int encode(const LibItsMbr__TypesAndValues::UtMbrEventInd &, OCTETSTRING &data); + virtual int decode(const OCTETSTRING &data, Record_Type &, params_its *params = NULL); + std::unique_ptr decode(const OCTETSTRING &data, params_its *params = NULL); +}; // End of class uppertester_mbr_codec diff --git a/ccsrc/Protocols/UpperTester/uppertester_mbr_layer.cc b/ccsrc/Protocols/UpperTester/uppertester_mbr_layer.cc new file mode 100644 index 0000000000000000000000000000000000000000..1a9004133092796acfca0d17859d61d2cf5a79c3 --- /dev/null +++ b/ccsrc/Protocols/UpperTester/uppertester_mbr_layer.cc @@ -0,0 +1,83 @@ +#include "uppertester_mbr_layer_factory.hh" + +#include "LibItsMbr_TestSystem.hh" +#include "LibItsMbr_TypesAndValues.hh" + +#include "loggers.hh" + +uppertester_mbr_layer::uppertester_mbr_layer(const std::string &p_type, const std::string ¶m) + : t_layer(p_type), _params(), _codec() { + loggers::get_instance().log(">>> uppertester_mbr_layer::uppertester_mbr_layer: %s, %s", to_string().c_str(), param.c_str()); + // Setup parameters + params::convert(_params, param); + params::const_iterator it = _params.find(params::loopback); + if (it == _params.cend()) { + _params.insert(std::pair(params::loopback, "0")); + } +} + +void uppertester_mbr_layer::sendMsg(const LibItsMbr__TypesAndValues::UtMbrInitialize &send_par, params &p_params) { + loggers::get_instance().log_msg(">>> uppertester_mbr_layer::sendMsg", send_par); + + if (_params[params::loopback].compare("1") == 0) { + LibItsMbr__TypesAndValues::UtMbrResults ut_mbr_results; + ut_mbr_results.utMbrInitializeResult() = BOOLEAN(true); + to_all_upper_ports(ut_mbr_results, p_params); + } else { + // Encode UpperTester PDU + OCTETSTRING data; + _codec.encode((const Record_Type &)send_par, data); + // Update parameters + send_data(data, p_params); + } +} + +void uppertester_mbr_layer::sendMsg(const LibItsMbr__TypesAndValues::UtMbrTrigger &send_par, params &p_params) { + loggers::get_instance().log_msg(">>> uppertester_mbr_layer::sendMsg", send_par); + + if (_params[params::loopback].compare("1") == 0) { + LibItsMbr__TypesAndValues::UtMbrResults ut_mbr_results; + ut_mbr_results.utMbrTriggerResult() = BOOLEAN(true); + to_all_upper_ports(ut_mbr_results, p_params); + } else { + // Encode UpperTester PDU + OCTETSTRING data; + _codec.encode(send_par, data); + // Update parameters + send_data(data, p_params); + } +} + +void uppertester_mbr_layer::sendMsg(const LibItsMbr__TypesAndValues::UtMbrEventInd &send_par, params &p_params) { + loggers::get_instance().log_msg(">>> uppertester_mbr_layer::sendMsg", send_par); + + if (_params[params::loopback].compare("1") == 0) { + LibItsMbr__TypesAndValues::UtMbrResults ut_mbr_results; + ut_mbr_results.utMbrTriggerResult() = BOOLEAN(true); + to_all_upper_ports(ut_mbr_results, p_params); + } else { + // Encode UpperTester PDU + OCTETSTRING data; + _codec.encode(send_par, data); + // Update parameters + send_data(data, p_params); + } +} + +void uppertester_mbr_layer::send_data(OCTETSTRING &data, params &p_params) { + loggers::get_instance().log_msg(">>> uppertester_mbr_layer::send_data: ", data); + // params.log(); + send_to_all_layers(data, p_params); +} + +void uppertester_mbr_layer::receive_data(OCTETSTRING &data, params &p_params) { + loggers::get_instance().log_msg(">>> uppertester_mbr_layer::receive_data: ", data); + + std::unique_ptr r = _codec.decode(data); + if (r.get() != nullptr) { + // Pass it to the ports if any + to_all_upper_ports(*r, p_params); + } +} + +uppertester_mbr_layer_factory uppertester_mbr_layer_factory::_f; diff --git a/ccsrc/Protocols/UpperTester/uppertester_mbr_layer.hh b/ccsrc/Protocols/UpperTester/uppertester_mbr_layer.hh new file mode 100644 index 0000000000000000000000000000000000000000..ac2b6f283bb8da1493ddb714bd60b91ff874db7f --- /dev/null +++ b/ccsrc/Protocols/UpperTester/uppertester_mbr_layer.hh @@ -0,0 +1,42 @@ +/*! + * \file uppertester_mbr_layer.hh + * \brief Header file for ITS UpperTester PKI protocol layer definition. + * \author ETSI TTF T027 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include + +#include "t_layer.hh" +#include "uppertester_mbr_codec.hh" + +namespace LibItsMbr__TestSystem { + class UpperTesterMbrPort; +} + +namespace LibItsMbr__TypesAndValues { + class UtMbrInitialize; + class UtMbrTrigger; +} // namespace LibItsMbr__TypesAndValues + +class uppertester_mbr_layer : public t_layer { + params _params; + uppertester_mbr_codec _codec; + +public: + uppertester_mbr_layer() : t_layer(), _params(), _codec(){}; + uppertester_mbr_layer(const std::string &p_type, const std::string ¶m); + virtual ~uppertester_mbr_layer(){}; + + void sendMsg(const LibItsMbr__TypesAndValues::UtMbrInitialize &send_par, params& p_params); + void sendMsg(const LibItsMbr__TypesAndValues::UtMbrTrigger &send_par, params& p_params); + void sendMsg(const LibItsMbr__TypesAndValues::UtMbrEventInd &send_par, params& p_params); + + virtual void send_data(OCTETSTRING &data, params& p_params); + virtual void receive_data(OCTETSTRING &data, params& params); +}; // End of class uppertester_mbr_layer diff --git a/ccsrc/Protocols/UpperTester/uppertester_mbr_layer_factory.hh b/ccsrc/Protocols/UpperTester/uppertester_mbr_layer_factory.hh new file mode 100644 index 0000000000000000000000000000000000000000..637220b4d65987ab89bfb441df6e0767677a6a70 --- /dev/null +++ b/ccsrc/Protocols/UpperTester/uppertester_mbr_layer_factory.hh @@ -0,0 +1,26 @@ +/*! + * \file uppertester_mbr_layer_factory.hh + * \brief Header file for ITS PKI Upper Tester protocol layer factory. + * \author ETSI TTF T027 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "layer_stack_builder.hh" + +#include "uppertester_mbr_layer.hh" + +class uppertester_mbr_layer_factory : public layer_factory { + static uppertester_mbr_layer_factory _f; + +public: + uppertester_mbr_layer_factory() { + // Register factory + layer_stack_builder::register_layer_factory("UT_MBR", this); + }; + inline virtual layer *create_layer(const std::string &p_type, const std::string &p_param) { return new uppertester_mbr_layer(p_type, p_param); }; +}; // End of class uppertester_mbr_layer_factory diff --git a/ccsrc/framework/include/params_its.hh b/ccsrc/framework/include/params_its.hh index b96dd3fad89f5fb2e9417e732320dc006ed7aa64..58f18f1b427f26f1ef967e982fb0cc31e685fce6 100644 --- a/ccsrc/framework/include/params_its.hh +++ b/ccsrc/framework/include/params_its.hh @@ -44,7 +44,7 @@ public: //! \publicsection static const std::string& longitude; //! Test system Longitude parameter name static const std::string& expiry; //! Test system GeoNetworking Lifetime parameter name (in ms) - static const std::string& station_id; //! To indicate to the peer ITS_Container::stationID + static const std::string& station_id; //! To indicate to the peer ETSI-ITS-CDD::StationIs static const std::string& device_mode; //! To indicate to the lower layer to act as a standalone device static const std::string& secured_mode; //! To indicate to the lower layer to apply signature on message exchanges as defined in IEEE 1609.2& ETSI TS 102 965 @@ -56,8 +56,8 @@ public: //! \publicsection static const std::string& certificate; //! The certificate identifier the Test System shall use. E.g. CERT_TS_A static const std::string& peer_certificate; //! The peer certificate identifier the Test System shall use for encryption. E.g. CERT_TS_A static const std::string& hash; //! The digest algorithm the Test System shall use, authorised values are SHA-256 or SHA-384. Default: SHA-256 - static const std::string& signature; //! The signature algorithm the Test System shall use, authorised values are NISTP-256, BP-256 and BP-384. Default: NISTP-256 - static const std::string& cypher; //! The encryption algorithm the Test System shall use, authorised values are NISTP-256 and BP-256. Default: NISTP-256 + static const std::string& signature; //! The signature algorithm the Test System shall use, authorised values are NISTP-256, BP-256, BP-384 and SM2P-256. Default: NISTP-256 + static const std::string& cypher; //! The encryption algorithm the Test System shall use, authorised values are NISTP-256, BP-256 and SM2P-256. Default: NISTP-256 static const std::string& distanceA; //! Test system GeoNetworking DistanceA parameter name static const std::string& distanceB; //! Test system GeoNetworking DistanceB parameter name static const std::string& angle; //! Test system GeoNetworking Angle parameter name @@ -77,6 +77,8 @@ public: //! \publicsection static const std::string& mqtt_protocol; //! Uu interafce MQTT protocol name static const std::string& mqtt_client_id; //! Uu interafce MQTT client identity + static const std::string& leap_delay_us; //! Leap seconds to convert to TAI. Default: 4us + /*! * \brief Default constructor * Create a new instance of the params_its class diff --git a/ccsrc/framework/src/params_its.cc b/ccsrc/framework/src/params_its.cc index 4b066fbadd548c39c36e8eb292b0c89002dd160d..fede2695fb833f75a28c8b4d7129b9d173e661ce 100644 --- a/ccsrc/framework/src/params_its.cc +++ b/ccsrc/framework/src/params_its.cc @@ -53,17 +53,19 @@ const std::string& params_its::distanceA = std::string("distanceA") const std::string& params_its::distanceB = std::string("distanceB"); const std::string& params_its::angle = std::string("angle"); -const std::string& params_its::payload_type = std::string("payload_type"); +const std::string& params_its::payload_type = std::string("payload_type"); -const std::string& params_its::next_header = std::string("next_header"); -const std::string& params_its::header_type = std::string("header_type"); -const std::string& params_its::header_sub_type = std::string("header_sub_type"); +const std::string& params_its::next_header = std::string("next_header"); +const std::string& params_its::header_type = std::string("header_type"); +const std::string& params_its::header_sub_type = std::string("header_sub_type"); -const std::string& params_its::interface_id = std::string("interface_id"); +const std::string& params_its::interface_id = std::string("interface_id"); -const std::string& params_its::uu_protocol = std::string("uu_protocol"); -const std::string& params_its::uu_transport = std::string("uu_transport"); -const std::string& params_its::pc5_layer = std::string("pc5_layer"); -const std::string& params_its::mqtt_topics = std::string("mqtt_topics"); -const std::string& params_its::mqtt_protocol = std::string("mqtt_protocol"); -const std::string& params_its::mqtt_client_id = std::string("mqtt_client_id"); +const std::string& params_its::uu_protocol = std::string("uu_protocol"); +const std::string& params_its::uu_transport = std::string("uu_transport"); +const std::string& params_its::pc5_layer = std::string("pc5_layer"); +const std::string& params_its::mqtt_topics = std::string("mqtt_topics"); +const std::string& params_its::mqtt_protocol = std::string("mqtt_protocol"); +const std::string& params_its::mqtt_client_id = std::string("mqtt_client_id"); + +const std::string& params_its::leap_delay_us = std::string("leap_delay_us"); diff --git a/config.mk b/config.mk index c6a59a390988055712452762ac7f31bf25f19bd3..8ec21eb16f298dbb29489d221c32ec4411c3c3eb 100644 --- a/config.mk +++ b/config.mk @@ -1,9 +1,10 @@ -TTCN3_DIR := $(HOME)/frameworks/titan/titan.core/Install -ASN1C_PATH := $(HOME)/frameworks/asn1c.denis -#WPCAP_DLL_PATH := /cygdrive/c/windows/system32/npcap/wpcap.dll -#NPCAP_INCLUDE := /cygdrive/c/PROGRA~1/Npcap/sdk/include -#T3Q_PATH=./tools/t3q-v2.0.0b30 -#T3Q_CONFIG=t3q.cfg -#T3D_PATH=./tools/t3d-v2.0.0b30 -#T3D_CONFIG=t3d.cfg -#ITS_CONTAINER=../../../AtsDENM/lib/asn1/cdd/ITS_Container.asn +TTCN3_COMPILER_OPTIONS := -d -e -f -g -l -L -R -U none -x -X +TTCN3_DIR := $(HOME)/frameworks/titan/titan.core/Install +ASN1C_PATH := $(HOME)/frameworks/asn1c.denis +#WPCAP_DLL_PATH := /cygdrive/c/windows/system32/npcap/wpcap.dll +#NPCAP_INCLUDE := /cygdrive/c/PROGRA~1/Npcap/sdk/include +#T3Q_PATH=./tools/t3q-v2.0.0b30 +#T3Q_CONFIG=t3q.cfg +#T3D_PATH=./tools/t3d-v2.0.0b30 +#T3D_CONFIG=t3d.cfg +#ITS_CONTAINER=../../../AtsDENM/lib/asn1/cdd/ITS_Container.asn diff --git a/data/certificates/Makefile b/data/certificates/Makefile index 2681cd19000dba617de372ca9877b8cebf19ee4c..74d1aa3f88f40cd5dabc16b16a8fa44694b003dd 100644 --- a/data/certificates/Makefile +++ b/data/certificates/Makefile @@ -54,11 +54,19 @@ certs_iut_at = $(filter $(outdir)/CERT_IUT_%_AT.oer, $(certificates_oer)) vkeys_iut_at = $(patsubst %.oer, %.vkey, $(certs_iut_at)) ekeys_iut_at = $(patsubst %.oer, %.ekey, $(certs_iut_at)) +certs_iut_at_imp = $(filter $(outdir)/CERT_IUT_%_AT_IMP.oer, $(certificates_oer)) +vkeys_iut_at_imp = $(patsubst %.oer, %.vkey, $(certs_iut_at_imp)) +ekeys_iut_at_imp = $(patsubst %.oer, %.ekey, $(certs_iut_at_imp)) + +certs_iut_ma = $(filter $(outdir)/CERT_IUT_%_MA.oer, $(certificates_oer)) +vkeys_iut_ma = $(patsubst %.oer, %.vkey, $(certs_iut_ma)) +ekeys_iut_ma = $(patsubst %.oer, %.ekey, $(certs_iut_ma)) + certs_iut := $(filter $(outdir)/CERT_IUT_%_RCA.oer, $(certificates_oer)) certs_iut += $(filter $(outdir)/CERT_IUT_%_AA.oer, $(certificates_oer)) -certs_iut += $(certs_iut_at) +certs_iut += $(certs_iut_at) $(certs_iut_at_imp) $(certs_iut_ma) -iut_files = $(patsubst $(outdir)/%, $(iutdir)/%, $(certs_iut) $(vkeys_iut_at) $(ekeys_iut_at)) +iut_files = $(patsubst $(outdir)/%, $(iutdir)/%, $(certs_iut) $(vkeys_iut_at) $(ekeys_iut_at) $(vkeys_iut_ma) $(ekeys_iut_ma) $(vkeys_iut_at_imp) $(ekeys_iut_at_imp)) install: $(iutdir) $(iut_files) $(iutdir)/index.lst @@ -68,14 +76,14 @@ $(iut_files): $(iutdir)/%: $(outdir)/% $(iutdir)/index.lst: $(certs_iut) $(asn1certidx) -o $@ $^ -$(vkeys_iut_at) $(ekeys_iut_at): +$(vkeys_iut_at) $(ekeys_iut_at) $(vkeys_iut_at_imp) $(ekeys_iut_at_imp): -IUT_TC23 = CERT_IUT_C1_AT.oer CERT_IUT_C1_AT.vkey CERT_IUT_C1_AT.ekey CERT_IUT_CC_AA.oer CERT_IUT_C_RCA.oer CERT_TS_A_AT.oer CERT_IUT_A_AA.oer -IUT_TC24 = CERT_IUT_C2_AT.oer CERT_IUT_C2_AT.vkey CERT_IUT_C2_AT.ekey CERT_IUT_C2_AA.oer CERT_IUT_C_RCA.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer CERT_IUT_A_AA.oer -IUT_TC25 = CERT_IUT_A1_AT.oer CERT_IUT_A1_AT.vkey CERT_IUT_A1_AT.ekey CERT_IUT_A_AA.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer -IUT_TC26 = CERT_IUT_A2_AT.oer CERT_IUT_A2_AT.vkey CERT_IUT_A2_AT.ekey CERT_IUT_A_AA.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer -IUT_TC27 = CERT_IUT_A3_AT.oer CERT_IUT_A3_AT.vkey CERT_IUT_A3_AT.ekey CERT_IUT_A_AA.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer -IUT_TC28 = CERT_IUT_A_AT_A8.oer CERT_IUT_A_AT_A8.vkey CERT_IUT_A_AT_A8.ekey CERT_IUT_A_AA_A8.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer CERT_IUT_A_AA.oer +IUT_TC23 = CERT_IUT_C1_AT.oer CERT_IUT_C1_AT.vkey CERT_IUT_C1_AT.ekey CERT_IUT_CC_AA.oer CERT_IUT_C_RCA.oer CERT_TS_A_AT.oer CERT_TS_A_AT_IMP.oer CERT_IUT_A_AA.oer +IUT_TC24 = CERT_IUT_C2_AT.oer CERT_IUT_C2_AT.vkey CERT_IUT_C2_AT.ekey CERT_IUT_C2_AA.oer CERT_IUT_C_RCA.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer CERT_TS_A_AT_IMP.oer CERT_IUT_A_AA.oer +IUT_TC25 = CERT_IUT_A1_AT.oer CERT_IUT_A1_AT.vkey CERT_IUT_A1_AT.ekey CERT_IUT_A_AA.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer CERT_TS_A_AT_IMP.oer +IUT_TC26 = CERT_IUT_A2_AT.oer CERT_IUT_A2_AT.vkey CERT_IUT_A2_AT.ekey CERT_IUT_A_AA.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer CERT_TS_A_AT_IMP.oer +IUT_TC27 = CERT_IUT_A3_AT.oer CERT_IUT_A3_AT.vkey CERT_IUT_A3_AT.ekey CERT_IUT_A_AA.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer CERT_TS_A_AT_IMP.oer +IUT_TC28 = CERT_IUT_A_AT_A8.oer CERT_IUT_A_AT_A8.vkey CERT_IUT_A_AT_A8.ekey CERT_IUT_A_AA_A8.oer CERT_IUT_A_RCA.oer CERT_TS_A_AT.oer CERT_TS_A_AT_IMP.oer CERT_IUT_A_AA.oer IUT_TCS = TC23 TC24 TC25 TC26 TC27 TC28 diff --git a/data/certificates/profiles/CERT_IUT_A_AT.xml b/data/certificates/profiles/CERT_IUT_A_AT.xml index 1c9a4036dfcc87b296da6533bca24bd5e1a12820..2f6613c1f3df352f89733f56c11b68afffb5a28d 100644 --- a/data/certificates/profiles/CERT_IUT_A_AT.xml +++ b/data/certificates/profiles/CERT_IUT_A_AT.xml @@ -12,7 +12,7 @@ - > + diff --git a/data/certificates/profiles/CERT_IUT_A_AT_IMP.xml b/data/certificates/profiles/CERT_IUT_A_AT_IMP.xml new file mode 100644 index 0000000000000000000000000000000000000000..85f865b055510c60c2f0bc9028ded5421d54dc1e --- /dev/null +++ b/data/certificates/profiles/CERT_IUT_A_AT_IMP.xml @@ -0,0 +1,35 @@ + + +3 + + + + + + + + + + + +> + + + + + + + + +01 FF FC  +01 FF FF FF  +   + + + + + + + + + diff --git a/data/certificates/profiles/CERT_TS_A_AT_IMP.xml b/data/certificates/profiles/CERT_TS_A_AT_IMP.xml new file mode 100644 index 0000000000000000000000000000000000000000..85f865b055510c60c2f0bc9028ded5421d54dc1e --- /dev/null +++ b/data/certificates/profiles/CERT_TS_A_AT_IMP.xml @@ -0,0 +1,35 @@ + + +3 + + + + + + + + + + + +> + + + + + + + + +01 FF FC  +01 FF FF FF  +   + + + + + + + + + diff --git a/data/certificates/profiles/CERT_TS_A_AT_IMP_BO.xml b/data/certificates/profiles/CERT_TS_A_AT_IMP_BO.xml new file mode 100644 index 0000000000000000000000000000000000000000..e620143609c14081da42ab8beb00a76d922e2efe --- /dev/null +++ b/data/certificates/profiles/CERT_TS_A_AT_IMP_BO.xml @@ -0,0 +1,36 @@ + + +3 + + + + + + + + + + + +> + + + + + + + + +01 FF FC  +01 FF FF FF  +   + + + + + + + + + + diff --git a/data/certificates/profiles/CERT_TS_F3_AT_IMP.xml b/data/certificates/profiles/CERT_TS_F3_AT_IMP.xml new file mode 100644 index 0000000000000000000000000000000000000000..037d0191f519fa1b220f64c472dc8ef3957417f7 --- /dev/null +++ b/data/certificates/profiles/CERT_TS_F3_AT_IMP.xml @@ -0,0 +1,35 @@ + + 3 + + + + + + + + + + + + > + + + + + + + + + 01 FF FC + 01 FF FF FF + + + + + + + + + + + diff --git a/data/certificates/profiles/CERT_TS_F_AT_IMP.xml b/data/certificates/profiles/CERT_TS_F_AT_IMP.xml new file mode 100644 index 0000000000000000000000000000000000000000..f9b4b8cc6e59ea5a1a6a97e2ab1a421ba2e60557 --- /dev/null +++ b/data/certificates/profiles/CERT_TS_F_AT_IMP.xml @@ -0,0 +1,36 @@ + + + 3 + + + + + + + + + + + + > + + + + + + + + + 01 FF FC + 01 FF FF FF + + + + + + + + + + + diff --git a/etc/AtsDENM/AtsDENM.cfg b/etc/AtsDENM/AtsDENM.cfg index db45356f852d49782048ba5cbeab09bfee2bb1a7..6cfabd69e927276a259c64fbb03634f46d01eed1 100644 --- a/etc/AtsDENM/AtsDENM.cfg +++ b/etc/AtsDENM/AtsDENM.cfg @@ -97,9 +97,9 @@ ItsDenm_TestCases.TC_DEN_MSGF_BV_01 #ItsDenm_TestCases.TC_DEN_MSGF_BV_02 # Check that DEN Basic Service generates a new DENM on reception of a valid AppDENM_Trigger request #ItsDenm_TestCases.TC_DEN_EVGN_BV_01 -# Check that a new ActionID value is assigned for each newly generated DENM +# Check that a new ActionId value is assigned for each newly generated DENM #ItsDenm_TestCases.TC_DEN_EVGN_BV_02 -# Check that a newly created ActionID contains the StationID of the originating ITS-S that detected the event +# Check that a newly created ActionId contains the StationID of the originating ITS-S that detected the event #ItsDenm_TestCases.TC_DEN_EVGN_BV_03 # Check that Cause and subcause values included in DENM as provided by application #ItsDenm_TestCases.TC_DEN_EVGN_BV_04 @@ -161,19 +161,19 @@ ItsDenm_TestCases.TC_DEN_MSGF_BV_01 #ItsDenm_TestCases.TC_DEN_SSP_BV_01_01 # Check that IUT does not send a DENM if it is not permitted by signing certificate #ItsDenm_TestCases.TC_DEN_SSP_BV_01_02 -# Check that receiving ITS-S transmits DENM to application if it concerns an unknown ActionID and if it is not a termination DENM +# Check that receiving ITS-S transmits DENM to application if it concerns an unknown ActionId and if it is not a termination DENM #ItsDenm_TestCases.TC_DEN_MSRV_BV_01 -#Check that receiving ITS-S transmits DENM to application if it concerns a known ActionID and referenceTime is greater than highest value received for this ActionID +#Check that receiving ITS-S transmits DENM to application if it concerns a known ActionId and referenceTime is greater than highest value received for this ActionId #ItsDenm_TestCases.TC_DEN_MSRV_BV_02 -# Check that receiving ITS-S discards termination DENM if it concerns an unknown ActionID (own actionID) +# Check that receiving ITS-S discards termination DENM if it concerns an unknown ActionId (own actionID) #ItsDenm_TestCases.TC_DEN_MSRV_BO_03 -# Check that receiving ITS-S discards termination DENM if it concerns an unknown ActionID (other actionID) +# Check that receiving ITS-S discards termination DENM if it concerns an unknown ActionId (other actionID) #ItsDenm_TestCases.TC_DEN_MSRV_BO_04 -# Check that receiving ITS-S discards DENM if referenceTime is lower than highest value received for this ActionID +# Check that receiving ITS-S discards DENM if referenceTime is lower than highest value received for this ActionId #ItsDenm_TestCases.TC_DEN_MSRV_BO_05 -# Check that receiving ITS-S discards DENM if detectionTime is smaller than highest value received for this ActionID +# Check that receiving ITS-S discards DENM if detectionTime is smaller than highest value received for this ActionId #ItsDenm_TestCases.TC_DEN_MSRV_BO_06 -# Check that receiving ITS-S transmits DENM to application if it concerns a known ActionID and referenceTime is equal to highest received value and detectionTime is more recent +# Check that receiving ITS-S transmits DENM to application if it concerns a known ActionId and referenceTime is equal to highest received value and detectionTime is more recent #ItsDenm_TestCases.TC_DEN_MSRV_BV_07 # Check that receiving ITS-S discards DENM for new event if SSP value of the signing certificate is not consistent with the causeCode #ItsDenm_TestCases.TC_DEN_MSRV_BO_08_01 diff --git a/etc/AtsMBR/AtsMBR.cfg b/etc/AtsMBR/AtsMBR.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f7f02531dffc04951ffe804ff0f3c11c8c69e02c --- /dev/null +++ b/etc/AtsMBR/AtsMBR.cfg @@ -0,0 +1,157 @@ + +[MODULE_PARAMETERS] +# This section shall contain the values of all parameters that are defined in your TTCN-3 modules. + +# The GeoNetworking address of the IUT. +#LibItsGeoNetworking_Pics.PICS_GN_LOCAL_GN_ADDR := { +# typeOfAddress := e_initial, +# stationType := e_unknown, +# reserved := 0, +# mid := '000000000000'O +#} +LibItsGeoNetworking_Pics.PICS_GN_LOCAL_GN_ADDR := { + typeOfAddress := e_manual, + stationType := e_roadSideUnit, + reserved := 49, + mid := '001C6B0D0201'O +} +LibItsGeoNetworking_Pixits.PX_GN_UPPER_LAYER := e_btpB +LibItsBtp_Pixits.PX_DESTINATION_PORT := 2001 +LibItsBtp_Pixits.PX_DESTINATION_PORT_INFO := 2001 + +# The certificate identifier the TA shall use in case of secured IUT +#LibItsCommon_Pixits.PX_CERT_FOR_TS := "CERT_TS_A_AT" + +# Enable Security support +LibItsGeoNetworking_Pics.PICS_GN_SECURITY := true +# Root path to access certificate stored in files, identified by certficate ID +LibItsSecurity_Pixits.PX_CERTIFICATE_POOL_PATH := "../data/certificates" +# Configuration sub-directory to access certificate stored in files +LibItsSecurity_Pixits.PX_IUT_SEC_CONFIG_NAME := "certificates" +# The certficate the IUT should use (cf. UtInitialize) +#LibItsSecurity_Pixits.PX_IUT_DEFAULT_CERTIFICATE := "CERT_IUT_A_AT" +# The certficate the TS should use to generate an ITS message +#LibItsSecurity_Pixits.PX_AT_CERTIFICATE := "CERT_TS_B_AT" # Possible values: CERT_TS_C_AT, CERT_TS_D_AT, or CERT_TS_E_AT + +#LibItsSecurity_Pics.PICS_SEC_SHA256 := false +#LibItsSecurity_Pics.PICS_SEC_SHA384 := true + +LibItsMbr_Pics.PICS_IUT_MA_CERTIFICATE_ID := "CERT_IUT_A_MA" + +[LOGGING] +# In this section you can specify the name of the log file and the classes of events +# you want to log into the file or display on console (standard error). + +LogFile := "../logs/AtsMBR/%e.%h-%r.%s" +FileMask := LOG_ALL | USER | DEBUG | MATCHING +ConsoleMask := LOG_ALL | USER | DEBUG | MATCHING +#FileMask := ERROR | WARNING | USER | PORTEVENT | MATCHING | EXECUTOR_RUNTIME | VERDICTOP | TIMEROP +#ConsoleMask := ERROR | WARNING | USER | PORTEVENT | MATCHING | EXECUTOR_RUNTIME | VERDICTOP | TIMEROP +LogSourceInfo := Stack +LogEntityName:= Yes +LogEventTypes:= Yes +#TimeStampFormat := DateTime + +[TESTPORT_PARAMETERS] +# In this section you can specify parameters that are passed to Test Ports. +# CAM Layer +# next_header : btpA|btpB (overwrite BTP.type) +# header_type : tsb|gbc +# header_sub_type : sh (single hop) +# DENM Layer +# next_header : btpA|btpB (overwrite BTP.type) +# header_type : tsb|gbc +# BTP Layer +# type : btpA|btpB +# destination port: dst_port +# source port : src_port +# device_mode : Set to 1 if the layer shall encapsulate upper layer PDU +# device_mode : Set to 1 if the layer shall encapsulate upper layer PDU +# GN Layer +# ll_address : GeoNetworking address of the Test System +# latitude : latitude of the Test System +# longitude : longitude of the Test System +# beaconing : Set to 1 if GnLayer shall start beaconing +# Beaconning timer expiry: expiry (ms) +# device_mode : Set to 1 if the layer shall encapsulate upper layer PDU +# secured_mode : Set to 1 if message exchanges shall be signed +# encrypted_mode : Set to 1 if message exchanges shall be encrypted +# NOTE: For signed & encrypted message exchanges, both secured_mode and encrypted_mode shall be set to 1 +# sec_db_path : Path to the certificates and keys storage location +# hash : Hash algorithm to be used when secured mode is set +# Authorized values are SHA-256 or SHA-384 +# Default: SHA-256 +# cypher : Cyphering algorithm to be used when secured mode is set +# Authorized values are NISTP-256, BP-256 and BP-384 +# Default: NISTP-256 +# Ethernet layer +# mac_src :Source MAC address +# mac_bc :Broadcast address +# eth_type : Ethernet type +# Commsignia layer +# mac_src : Device MAC address, used to discard packets +# To indicate no filering, use the value 000000000000 +# mac_bc : Broadcast address +# eth_type : Ethernet type, used to discard packets +# target_host : Device address +# target_port : Device port +# source_port : Test System port +# interface_id: Interface id, used to discard packets +# tx_power : TX power (dB) +# UDP layer (IP/UDP based on Pcap) +# dst_ip : destination IPv4 address (aa.bb.cc.dd) +# dst_port: destination port +# src_ip : source IPv4 address (aa.bb.cc.dd) +# src_port: source port +# Pcap layer +# mac_src : Source MAC address, used to exclude from capture the acket sent by the Test System +# filter : Pcap filter (compliant with tcpdump syntax) +# Online mode: +# nic: Local NIC +# If set, online mode is used +# Offline mode (nic is present but not set): +# file : File to read +# frame_offset: Frame offset, used to skip packets with frame number < frame_offset +# time_offset : Time offset, used to skip packets with time offset < time_offset +# save_mode : 1 to save sent packet, 0 otherwise + +# Single GeoNetworking component port +# https://standards.iso.org/iso/ts/17419/TS17419%20Assigned%20Numbers/TS17419_ITS-AID_AssignedNumbers.pdf +# its_aid=36: CAM +# its_aid=37: DENM +# its_aid=137: SPAT +# its_aid=138: MAP +# its_aid=139: IVIM +# its_aid=140: SREM/SSEM +# its_aid=141: GeoMet +# its_aid=128: RTCMEM + +# Cygwin +#system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EA,latitude=43551050,longitude=10298730,distanceA=1500,distanceB=1500,angle=0,device_mode=0,secured_mode=0,sec_db_path=../data/certificates/certificates)/ETH(mac_src=e2b7b30429eb)/PCAP(mac_src=e2b7b30429eb,nic=CEBB111F-D749-4B40-8B4D-DBB060E90987,filter=and ether proto 0x8947)" +# Linux +system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EA,latitude=43551050,longitude=10298730,distanceA=1500,distanceB=1500,angle=0,device_mode=0,secured_mode=0,sec_db_path=../data/certificates/certificates)/ETH(mac_src=8c554ac1eee0)/PCAP(mac_src=8c554ac1eee0,nic=wlp0s20f3,filter=and ether proto 0x8947)" +#system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=43551050,longitude=10298730,distanceA=1500,distanceB=1500,angle=0,device_mode=0,secured_mode=0,its_aid=36)/ETH(mac_src=8c554ac1eee0)/PCAP(mac_src=8c554ac1eee0,nic=wlp0s20f3,filter=and ether proto 0x8947)" +# Linux over UDP +#system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=43551050,longitude=10298730,distanceA=1500,distanceB=1500,angle=0,device_mode=0,secured_mode=0,its_aid=36)/ETH(mac_src=8c554ac1eee0)/UDP(dst_ip=192.168.1.43,src_port=4041,dst_port=9091)" + +system.httpPort.params := "HTTP(codecs=http_its:http_etsi_ieee1609dot2_codec)/TCP(debug=1,server_mode=1,server=192.168.1.43)" + +system.utMbrPort.params := "UT_MBR/UDP(dst_ip=192.168.1.43,dst_port=12345,src_port=12346)" + +[EXECUTE] + +# Check that the IUT generates an encrypted MBR message +#ItsMbr_TestCases.TC_MRS_ITSS_SEC_BV_001 + +# Check that the IUT provides the certificate of the reported ITS-S when the invalid secured geonetworking packet does not contain the AT certificate +ItsMbr_TestCases.TC_MRS_ITSS_MESSAGES_001 + +# Check that the IUT generates an invalid speed value observation on a CAM in the MR message when requested (Class 1) - obs-Speed-ValueTooLarge-VehicleType +#ItsMbr_TestCases.TC_MRS_ITSS_MESSAGES_CLASS1_CAM_001 + +[MAIN_CONTROLLER] +# The options herein control the behavior of MC. +KillTimer := 10.0 +LocalAddress := 127.0.0.1 +TCPPort := 12000 +NumHCs := 1 diff --git a/etc/AtsPki/AtsPki_Atos.cfg_ b/etc/AtsPki/AtsPki_Atos.cfg_ index 671ae27821b0b44ab546be8c0f08ef3638f7264e..b53626e0e9f8fc4801a1e1be4edda37e15687bdf 100644 --- a/etc/AtsPki/AtsPki_Atos.cfg_ +++ b/etc/AtsPki/AtsPki_Atos.cfg_ @@ -70,11 +70,11 @@ LibItsPki_Pics.PICS_EA_ENDPOINT := "http://yanngarcia.ddns.net/ea" #LibItsPki_Pixits.PX_INCLUDE_ENCRYPTION_KEYS := false # No encryption key in Authorization request -#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 or e_brainpool_p384_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256, e_nist_p384, e_sm2_p256, e_brainpool_p256_r1 or e_brainpool_p384_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1, e_sm2_p256 +#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1, e_sm2_p256 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1, e_sm2_p256 +#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1, e_sm2_p256 LibItsSecurity_Pics.PICS_SEC_CIRCULAR_REGION := false LibItsSecurity_Pics.PICS_SEC_RECTANGULAR_REGION := true diff --git a/etc/AtsPki/AtsPki_Autocrypt.cfg_ b/etc/AtsPki/AtsPki_Autocrypt.cfg_ index 630de23474105fdddccbf0bf1ed6200fa0f36ddb..67bbceff60e460aa4aba81a404f19eb1b6500aa8 100644 --- a/etc/AtsPki/AtsPki_Autocrypt.cfg_ +++ b/etc/AtsPki/AtsPki_Autocrypt.cfg_ @@ -57,12 +57,12 @@ LibItsPki_Pics.PICS_HTTP_POST_URI_DC := "/ctl" #LibItsPki_Pixits.PX_INCLUDE_ENCRYPTION_KEYS := false # No encryption key in Authorization request -#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p384_r1 +#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256, e_nist_p384, e_sm2_p256 or e_brainpool_p384_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 LibItsSecurity_Pics.PICS_SEC_CIRCULAR_REGION := false LibItsSecurity_Pics.PICS_SEC_RECTANGULAR_REGION := true diff --git a/etc/AtsPki/AtsPki_Ctag.cfg_ b/etc/AtsPki/AtsPki_Ctag.cfg_ index b6bcc920628972e6d8c93cb5cbeb2c6d6a3fbce5..8105a3f22e8ad8e63641af29883672417a9db86f 100644 --- a/etc/AtsPki/AtsPki_Ctag.cfg_ +++ b/etc/AtsPki/AtsPki_Ctag.cfg_ @@ -58,12 +58,12 @@ LibItsPki_Pics.PICS_ITS_S_SIGN_NISTP256_PUBLIC_KEY := '038038f5490cd5a58ff5465d3 #LibItsPki_Pixits.PX_INCLUDE_ENCRYPTION_KEYS := false # No encryption key in Authorization request -#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p384_r1 +#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256, e_nist_p384, e_sm2_p256 or e_brainpool_p384_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 LibItsSecurity_Pics.PICS_SEC_CIRCULAR_REGION := false LibItsSecurity_Pics.PICS_SEC_RECTANGULAR_REGION := true diff --git a/etc/AtsPki/AtsPki_Etas.cfg_ b/etc/AtsPki/AtsPki_Etas.cfg_ index 5bfc8b77e178b9320e42241689f0cc6f0869bef3..5f4b93a65c61c12ecd8831497ab465dcd5bb283c 100644 --- a/etc/AtsPki/AtsPki_Etas.cfg_ +++ b/etc/AtsPki/AtsPki_Etas.cfg_ @@ -66,12 +66,12 @@ LibItsPki_Pics.PICS_EA_ENDPOINT := "http://yanngarcia.ddns.net/ea" #LibItsPki_Pixits.PX_INCLUDE_ENCRYPTION_KEYS := false # No encryption key in Authorization request -#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p384_r1 +#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256, e_nist_p384, e_sm2_p256 or e_brainpool_p384_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 LibItsSecurity_Pics.PICS_SEC_CIRCULAR_REGION := false LibItsSecurity_Pics.PICS_SEC_RECTANGULAR_REGION := false diff --git a/etc/AtsPki/AtsPki_Microsec.cfg_ b/etc/AtsPki/AtsPki_Microsec.cfg_ index d4bcf7ee701c937bed2999166f3078c07fa26f5e..bfda4f871be5e3ae3d6f08f8b8557d46316b7904 100644 --- a/etc/AtsPki/AtsPki_Microsec.cfg_ +++ b/etc/AtsPki/AtsPki_Microsec.cfg_ @@ -52,12 +52,12 @@ LibItsPki_Pics.PICS_ITS_S_SIGN_NISTP256_PUBLIC_KEY := '038038f5490cd5a58ff5465d3 #LibItsPki_Pixits.PX_INCLUDE_ENCRYPTION_KEYS := false # No encryption key in Authorization request -#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p384_r1 +#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256, e_nist_p384, e_sm2_p256 or e_brainpool_p384_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256 or e_brainpool_p256_r1 LibItsSecurity_Pics.PICS_SEC_CIRCULAR_REGION := false LibItsSecurity_Pics.PICS_SEC_RECTANGULAR_REGION := true diff --git a/etc/AtsPki/AtsPki_Simu.cfg_ b/etc/AtsPki/AtsPki_Simu.cfg_ index 7fe30988721264c8f7c3b3c921b7f8d3210ac569..6a984ce5c47db23b40a967cf8918b57fe18292d7 100644 --- a/etc/AtsPki/AtsPki_Simu.cfg_ +++ b/etc/AtsPki/AtsPki_Simu.cfg_ @@ -61,11 +61,11 @@ LibItsPki_Pics.PICS_SECPKI_REENROLMENT := true #LibItsPki_Pixits.PX_INCLUDE_ENCRYPTION_KEYS := false # No encryption key in Authorization request #LibItsPki_Pixits.PICS_PKI_AUTH_POP := false # Do not use Signed for PoP in Authorization requet -#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 or e_brainpool_p384_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 -#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256, e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_VE_ALG := e_brainpool_p256_r1 # e_nist_p256, e_nist_p384, e_sm2_p256, e_brainpool_p256_r1 or e_brainpool_p384_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256, e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_ATV := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256, e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_EC_SIGN := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256, e_brainpool_p256_r1 +#LibItsPki_Pixits.PX_EC_ALG_FOR_AT := e_brainpool_p256_r1 # e_nist_p256, e_sm2_p256, e_brainpool_p256_r1 LibItsSecurity_Pics.PICS_SEC_CIRCULAR_REGION := false LibItsSecurity_Pics.PICS_SEC_RECTANGULAR_REGION := true diff --git a/etc/AtsSecurity/AtsSecurity.cfg b/etc/AtsSecurity/AtsSecurity.cfg index a3eb0a4c70fbc776dbb1e21b23f3f269a06731cd..62e31924d6d021ec45a4d4ef7df3d4a8df984bec 100644 --- a/etc/AtsSecurity/AtsSecurity.cfg +++ b/etc/AtsSecurity/AtsSecurity.cfg @@ -19,8 +19,9 @@ LibItsGeoNetworking_Pixits.PX_GN_UPPER_LAYER := e_btpB LibItsBtp_Pixits.PX_DESTINATION_PORT := 2001 LibItsBtp_Pixits.PX_DESTINATION_PORT_INFO := 2001 -# The certificate identifier the TA shall use in case of secured IUT -#LibItsCommon_Pixits.PX_CERT_FOR_TS := "CERT_IUT_A_AT" +#LibItsSecurity_Pics.PICS_SEC_NIST_P256 := false +#LibItsSecurity_Pics.PICS_SEC_BRAINPOOL_P256R1 := false; +#LibItsSecurity_Pics.PICS_SEC_BRAINPOOL_P384R1 := false; # Enable Security support LibItsGeoNetworking_Pics.PICS_GN_SECURITY := true @@ -35,16 +36,17 @@ LibItsSecurity_Pixits.PX_AT_CERTIFICATE := "CERT_TS_B_AT" # Possible values: CER #LibItsSecurity_Pics.PICS_SEC_SHA256 := false #LibItsSecurity_Pics.PICS_SEC_SHA384 := true + [LOGGING] # In this section you can specify the name of the log file and the classes of events # you want to log into the file or display on console (standard error). LogFile := "../logs/AtsSecurity/%e.%h-%r.%s" -FileMask := LOG_ALL | USER | DEBUG | MATCHING -ConsoleMask := LOG_ALL | USER | DEBUG | MATCHING -#FileMask := ERROR | WARNING | USER | PORTEVENT | MATCHING | EXECUTOR_RUNTIME | VERDICTOP | TIMEROP -#ConsoleMask := ERROR | WARNING | USER | PORTEVENT | MATCHING | EXECUTOR_RUNTIME | VERDICTOP | TIMEROP +#FileMask := LOG_ALL | USER | DEBUG | MATCHING +#ConsoleMask := LOG_ALL | USER | DEBUG | MATCHING +FileMask := ERROR | WARNING | USER | PORTEVENT | MATCHING | EXECUTOR_RUNTIME | VERDICTOP | TIMEROP +ConsoleMask := ERROR | WARNING | USER | PORTEVENT | MATCHING | EXECUTOR_RUNTIME | VERDICTOP | TIMEROP LogSourceInfo := Stack LogEntityName:= Yes LogEventTypes:= Yes @@ -132,7 +134,7 @@ system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EA,latitude=43551050 # Linux over UDP #system.geoNetworkingPort.params := "GN(ll_address=4C5E0C14D2EB,latitude=43551050,longitude=10298730,distanceA=1500,distanceB=1500,angle=0,device_mode=0,secured_mode=0,its_aid=36)/ETH(mac_src=8c554ac1eee0)/UDP(dst_ip=192.168.1.43,src_port=4041,dst_port=9091)" -system.utPort.params := "UT_GN/UDP(dst_ip=192.168.1.43,dst_port=12345,src_port=12346)" # Use with TC_SEC_ITSS_RCV_MSG_ test cases +system.utPort.params := "UT_GN/UDP(dst_ip=192.168.1.43,dst_port=12345,src_port=12346)" # Use with TC_SEC_ITSS_RCV_MSG_ and TC_SEC_ITSS_RCV_IMPLICIT_CERT_ test cases #system.utPort.params := "UT_CAM/UDP(dst_ip=192.168.1.43,dst_port=12345,src_port=12346)" #system.utPort.params := "UT_CAM/DEBUG" #system.camUtPort.params := "UT_CAM/DEBUG" @@ -145,9 +147,22 @@ system.camUtPort.params := "UT_CAM/UDP(dst_ip=192.168.1.43,dst_port=12345,src_po #Check that ITS-S sends a Ieee1609Dot2Data containing protocol version set to 3 #ItsSecurity_TestCases.TC_SEC_ITSS_SND_MSG_01_BV +# --------------------- IMPILICT CERT --------------------- +# Check that IUT supports usage of implicit certificate for signing message +ItsSecurity_TestCases.TC_SEC_ITSS_SND_IMPLICIT_CERT_01_BV + +# Check that IUT accepts a valid secured CAM message signed with a known implicit certificate +#ItsSecurity_TestCases.TC_SEC_ITSS_RCV_IMPLICIT_CERT_01_BV + +# Check that IUT accepts a valid secured CAM message signed with an unknown implicit certificate +#ItsSecurity_TestCases.TC_SEC_ITSS_RCV_IMPLICIT_CERT_02_BV + +# Check that IUT discards a valid secured CAM message signed with implicit certificate containing signature +#ItsSecurity_TestCases.TC_SEC_ITSS_RCV_IMPLICIT_CERT_01_BO + # ------------------------- CAM --------------------------- # Check that IUT sends the secured CAM using SignedData container. -ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_01_BV +#ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_01_BV # Check that IUT sends the secured CAM containing the HeaderInfo field psid set to 'AID_CAM'. #ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_02_BV @@ -162,7 +177,16 @@ ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_01_BV # Check that IUT calculate the digest of certificate using proper hash algorithm; # Check that IUT canonicalize certificates before hash calculation. -#ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_05_BV +# PICS_SEC_NIST_P256 +#ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_05_A_BV +#ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_05_AN_BV +# PICS_SEC_BRAINPOOL_P256R1 +#ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_05_B_BV +#ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_05_BN_BV +# PICS_SEC_BRAINPOOL_P384R1 +#ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_05_C_BV +#ItsSecurity_TestCases.TC_SEC_ITSS_SND_CAM_05_CN_BV + # Check that IUT sends the secured CAM containing the signing certificate when over the time of one # second no other secured CAM contained the certificate was sent. diff --git a/libasn1.mk b/libasn1.mk new file mode 100644 index 0000000000000000000000000000000000000000..32b2300d7a6b8de44259e0f39d8ec8fbd5574212 --- /dev/null +++ b/libasn1.mk @@ -0,0 +1,122 @@ +########################################################## +# This Makefile is to build the ASN1 library to be used +# for external codec in Titan +# This Makefile is expected that asn1c compiler is +# installed in the PATHs +########################################################## + +# The name of the library +ASN_LIBRARY = libItsAsn.a + +ifeq (,$(sort $(ASN_FILES))) + $(error ASN_FILES should be specified ) +endif + +#Override ASN1C instalation path +ifneq (, $(ASN1C_PATH)) + ASN1C:=$(ASN1C_PATH)/asn1c/asn1c -S $(ASN1C_PATH)/skeletons +else + ASN1C:=asn1c +endif + +LIB_MAKEFILE=Makefile.am.libasncodec +include $(LIB_MAKEFILE) +OBJS = ${ASN_MODULE_SRCS:.c=.o} +CONVERTER=converter +ASN_CONVERTER_SOURCES := \ + converter-example.c\ + pdu_collection.c +CONVERTER_OBJS=${ASN_CONVERTER_SOURCES:.c=.o} +ifneq ($(strip $(ASN_PDU)),$(firstword $(ASN_PDU))) + HAS_PDU_COLLECTION := -DASN_PDU_COLLECTION +endif + +CFLAGS += $(ASN_MODULE_CFLAGS) -DPDU=$(firstword $(ASN_PDU)) $(HAS_PDU_COLLECTION) -fPIC -I. +CC = gcc -std=c99 +ASN1C_OPTIONS += -no-gen-example -fcompound-names -no-gen-XER -no-gen-JER -no-gen-APER -no-gen-print -no-gen-random-fill +ifeq (yes,$(DEBUG)) + CFLAGS += -g -O0 -DASN_EMIT_DEBUG=1 +endif +ASN_SRC_FILES := $(addprefix $(TOP_DIR)/, $(ASN_FILES)) + +all: $(ASN_LIBRARY) + +$(LIB_MAKEFILE): $(ASN_SRC_FILES) Makefile + $(ASN1C) $(ASN1C_OPTIONS) $(addprefix -pdu=,$(pdu)) $(ASN_SRC_FILES) +# -for n in $(PATCHES); do git apply "$(SCRIPT_DIR)/$$n"; done + +$(CONVERTER): $(ASN_LIBRARY) $(CONVERTER_OBJS) + $(CC) $(CFLAGS) -o $@ $(CONVERTER_OBJS) $(ASN_LIBRARY) $(LIBS) + +$(ASN_LIBRARY): ${ASN_MODULE_SRCS:.c=.o} + ar rcs $@ $^ +# $(CC) $(CFLAGS) -o $@ $^ -shared $(LDFLAGS) $(LIBS) + +.SUFFIXES: +.SUFFIXES: .c .o + +.c.o: + $(CC) $(CFLAGS) -o $@ -c $< + +clean: + rm -f $(CONVERTER) $(ASN_LIBRARY) + rm -f $(OBJS) $(CONVERTER_OBJS) + +regen: clear-asn1c $(LIB_MAKEFILE) +clear-asn1c: + rm -f $(LIB_MAKEFILE) + +########################################################## + +$(TOP_DIR)/./build/asn1/ISO_TS_14816/AVIAEINumberingAndDataStructures.asn: + mkdir -p "$(dir $@)" + curl 'https://standards.iso.org/iso/14816/ISO14816%20ASN.1%20repository/ISO14816_AVIAEINumberingAndDataStructures.asn' | \ + sed -e 's/IssuerIdentifier/AVIAEIIssuerIdentifier/g' > "$@" + +#$(TOP_DIR)/./build/asn1/ISO_TS_14906/EfcDsrcApplication.asn: +# mkdir -p "$(dir $@)" +# curl -o "$@" 'https://standards.iso.org/iso/14906/ed-3/en/ISO14906(2018)EfcDsrcApplicationv6.asn' + +#$(TOP_DIR)/./build/asn1/ISO_TS_14906/EfcDsrcGeneric.asn: +# mkdir -p "$(dir $@) +# curl -o "$@" 'https://standards.iso.org/iso/14906/ed-3/en/ISO14906(2018)EfcDsrcGenericv7.asn' + +$(TOP_DIR)/./build/asn1/ISO_TS_17419/CITSapplMgmtIDs.asn: + mkdir -p "$(dir $@)" + curl -o "$@" 'https://standards.iso.org/iso/ts/17419/TS%2017419%20ASN.1%20repository/TS17419_2014_CITSapplMgmtIDs.asn' + +$(TOP_DIR)/./build/asn1/ISO_TS_19091/ISO-TS-19091-addgrp-C-2018-patched.asn: + mkdir -p "$(dir $@)" + curl 'https://standards.iso.org/iso/ts/19091/ed-2/en/ISO-TS-19091-addgrp-C-2018.asn' | \ + sed -e 's/\bHeadingConfidence\b/HeadingConfidenceDSRC/g' \ + -e 's/\bSpeedConfidence\b/SpeedConfidenceDSRC/g' \ + -e 's/\bHeading\b/HeadingDSRC/g' > "$@" + +$(TOP_DIR)/./build/asn1/ISO_TS_17419/CITSdataDictionary1.asn: + mkdir -p "$(dir $@)" + curl -o "$@" 'https://standards.iso.org/iso/17419/ed-1/en/17419.1.asn' + +$(TOP_DIR)/./build/asn1/ISO_TS_17419/CITSdataDictionary2.asn: + mkdir -p "$(dir $@)" + curl -o "$@" 'https://standards.iso.org/iso/17419/ed-1/en/17419.2.asn' + +#$(TOP_DIR)/./build/asn1/ISO_TS_19091/AddGrpC.asn: +#$(TOP_DIR)/./build/asn1/ISO_TS_19091/AddGrpC_noCircular.asn: +#$(TOP_DIR)/./build/asn1/ISO_TS_19091/DSRC.asn: +#$(TOP_DIR)/./build/asn1/ISO_TS_19091/DSRC_REGION_noCircular.asn +#$(TOP_DIR)/./build/asn1/ISO_TS_19091/REGION.asn + +$(TOP_DIR)/./build/asn1/ISO_TS_19321/IVI.asn: + mkdir -p "$(dir $@)" + curl 'https://standards.iso.org/iso/ts/19321/ed-2/en/ISO19321IVIv2.asn' | \ + sed -e 's/\bCITSdataDictionary1\b/CITSapplMgmtIDs/g' \ + -e 's/,\s*\.\.\.\s*,\s*[0-9]\+/,.../g' \ + -e 's/ITS-Container/ETSI-ITS-CDD/g' \ + -e 's/ts (102894)/102894/g' \ + -e 's/version (2)/major-version-3 (3) minor-version-1 (1)/g' \ + > "$@" + +#$(TOP_DIR)/build/asn1/ISO_TS_24534-3/ElectronicRegistrationIdentificationVehicleDataModule.asn: +# mkdir -p "$(dir $@)" +# curl -o "$@" 'https://standards.iso.org/iso/24534/-3/ISO%2024534-3%20ASN.1%20repository/ISO24534-3_ElectronicRegistrationIdentificationVehicleDataModule_ForBallot.asn' + diff --git a/scripts/devenv.bash.debian b/scripts/devenv.bash.debian index c6a9aaa760e99b77b8176a4b8867af032d8bf6a8..3954023022c3ecaae5adb797b9f65d34014d2616 100755 --- a/scripts/devenv.bash.debian +++ b/scripts/devenv.bash.debian @@ -57,11 +57,13 @@ then export TTCN3_LICENSE_FILE=${TTCN3_DIR}/etc/license/license.dat export PATH_DEV_TTCN=${HOME}/dev/ttcn3 # ITS support - export PATH_DEV_ITS=${HOME}/dev/etsi_its + export PATH_DEV_ITS=${HOME}/dev/TS.ITS # Emergency Communication support - export PATH_DEV_EMCOM=${HOME}/dev/etsi_emcom + export PATH_DEV_EMCOM=${HOME}/dev/NG112 # Mobile-Edge Computing support - export PATH_DEV_MEC=${HOME}/dev/etsi_mec + export PATH_DEV_MEC=${HOME}/dev/gs032p3-ttcn-test-suite + # CDM/CISE support + export PATH_DEV_MEC=${HOME}/dev/cise # Validation folder export VALIDATION_DIR=${HOME} fi diff --git a/scripts/devenv.bash.ubuntu b/scripts/devenv.bash.ubuntu index c6a9aaa760e99b77b8176a4b8867af032d8bf6a8..254cc37f0994b24a461c14791d3ec14c4336a3a2 100755 --- a/scripts/devenv.bash.ubuntu +++ b/scripts/devenv.bash.ubuntu @@ -2,12 +2,14 @@ # Turn on debug mode #set -vx -#set -e + +set -e # Colors and Prompt #export PS1="\w\$ " #export PS1="\D{%Y-%m-%d %H:%M:%S} \w\n\$ " +export TERM=xterm export EDITOR=emacs set -o emacs @@ -26,24 +28,24 @@ export HOME_INC=${HOME}/include export PATH=${HOME_BIN}:${PATH} # Update LD_LIBRARY_PATH environment variable -if [ -z "${LD_LIBRARY_PATH}" ] +if [ "${LD_LIBRARY_PATH}" == "" ] then - export LD_LIBRARY_PATH=${HOME_LIB}:/usr/local/lib:${HOME}/dev/etsi_its/lib + export LD_LIBRARY_PATH=${HOME_LIB}:/usr/local/lib else - export LD_LIBRARY_PATH=${HOME_LIB}:/usr/local/lib:${HOME}/dev/etsi_its/lib:${LD_LIBRARY_PATH} + export LD_LIBRARY_PATH=${HOME_LIB}:/usr/local/lib:${LD_LIBRARY_PATH} fi # Add JAVA support -#export JAVA_VERSION=1.8.0_92 -#export JAVA_JDK=jdk${JAVA_VERSION} -#if [ -d "${HOME_FRAMEWORKS}/${JAVA_JDK}" ] -#then -# export JAVA_HOME=${HOME_FRAMEWORKS}/${JAVA_JDK}/bin -#else -# unset JAVA_VERSION -# unset JAVA_JDK -#fi +export JAVA_VERSION=1.8.0_92 +export JAVA_JDK=jdk${JAVA_VERSION} +if [ -d "${HOME_FRAMEWORKS}/${JAVA_JDK}" ] +then + export JAVA_HOME=${HOME_FRAMEWORKS}/${JAVA_JDK}/bin +else + unset JAVA_VERSION + unset JAVA_JDK +fi # Add TITAN support export TOP=${HOME_FRAMEWORKS}/titan/titan.core @@ -57,19 +59,15 @@ then export TTCN3_LICENSE_FILE=${TTCN3_DIR}/etc/license/license.dat export PATH_DEV_TTCN=${HOME}/dev/ttcn3 # ITS support - export PATH_DEV_ITS=${HOME}/dev/etsi_its + export PATH_DEV_ITS=${HOME}/dev/TS.ITS # Emergency Communication support - export PATH_DEV_EMCOM=${HOME}/dev/etsi_emcom + export PATH_DEV_EMCOM=${HOME}/dev/NG112 # Mobile-Edge Computing support - export PATH_DEV_MEC=${HOME}/dev/etsi_mec + export PATH_DEV_MEC=${HOME}/dev/gs032p3-ttcn-test-suite + # CDM/CISE support + export PATH_DEV_MEC=${HOME}/dev/cise # Validation folder export VALIDATION_DIR=${HOME} fi export BROWSER=netsurf - -export OPENSSL_DIR=/usr/local - -export LSAN_OPTIONS=verbosity=1:log_threads=1 - - diff --git a/scripts/run_all.bash b/scripts/run_all.bash index fd921d1d2e4f1fa52576d00074cbce890a9c8ad2..288d5b70388544441e9f748e30fda0332172ae9c 100755 --- a/scripts/run_all.bash +++ b/scripts/run_all.bash @@ -10,17 +10,26 @@ then exit 1 fi -if ! [[ $1 =~ "^[0-9]+$" ]] +VLGD="" +if [[ $1 =~ ^[0-9]+$ ]] then COUNTER=$1 else COUNTER=1 + if [ "$1" == "valgrind" ] + then + VLGD=valgrind + fi fi if [ $COUNTER == 0 ] then - COUNTER=1 - cd .. && make && cd - + COUNTER=1 + cd .. && make && cd - + if [ "$2" == "valgrind" ] + then + VLGD=valgrind + fi fi CURPWD=`pwd` @@ -39,7 +48,7 @@ rm ../logs/$ATS/*.log for i in $(seq 1 1 $COUNTER) do ./run_mtc.bash & - ./run_ptcs.bash + ./run_ptcs.bash $VLGD dup=$(ps -ef | grep "$0" | grep -v grep | wc -l) while [ ${dup} -eq 3 ] @@ -49,7 +58,10 @@ do done sleep 1 - mv ../logs/$ATS/merged.log ../logs/$ATS/merged.`date +'%Y%m%d%S'`.log + if [ -f ../logs/$ATS/merged_formated.log ] + then + mv ../logs/$ATS/merged_formated.log ../logs/$ATS/merged.`date +'%Y%m%d%S'`.log + fi done exit 0 diff --git a/scripts/run_mtc.bash b/scripts/run_mtc.bash index 0559a9eaa0bd77cbbbdbd85f61678d8367e14861..e2255124147fb86b02e580a4992ec7ea013ab1c0 100755 --- a/scripts/run_mtc.bash +++ b/scripts/run_mtc.bash @@ -42,7 +42,6 @@ if [ "${TITAN_LOG_DIR}" != "" ] then ttcn3_logmerge -o ${TITAN_LOG_DIR}/merged.log ${LOG_FILES} ttcn3_logformat -o ${TITAN_LOG_DIR}/merged_formated.log ${TITAN_LOG_DIR}/merged.log - mv ${TITAN_LOG_DIR}/merged_formated.log ${TITAN_LOG_DIR}/merged.log echo "log files were merged into ${TITAN_LOG_DIR}/merged.log" fi diff --git a/scripts/run_ptcs.bash b/scripts/run_ptcs.bash index 1c097d445d09ed82c6c8e934e7e57c03fe142474..be027105f6013f4720cb10c92dd7f2105f9f7f7f 100755 --- a/scripts/run_ptcs.bash +++ b/scripts/run_ptcs.bash @@ -4,6 +4,12 @@ clear +VLGD="" +if [ "$1" == "valgrind" ] +then + VLGD="valgrind --leak-check=full --show-leak-kinds=all -v" +fi + if [ -z $ATS ] then echo "ATS shall be defined" @@ -28,9 +34,9 @@ fi if [ "$ATS" == "AtsRSUsSimulator" ] then - sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH ../bin/$ATS 127.0.0.1 12001 + sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH $VLGD ../bin/$ATS 127.0.0.1 12001 else - sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH ../bin/$ATS 127.0.0.1 12000 + sudo LD_LIBRARY_PATH=$LD_LIBRARY_PATH $VLGD ../bin/$ATS 127.0.0.1 12000 fi cd ${CURPWD} diff --git a/titan-test-system-framework b/titan-test-system-framework index 3ed2fe8a69be8562c2f9d8f5b1afb8ba91d5776a..2645a5245082506a64acc58e7c2c7ac5c5bc4c3a 160000 --- a/titan-test-system-framework +++ b/titan-test-system-framework @@ -1 +1 @@ -Subproject commit 3ed2fe8a69be8562c2f9d8f5b1afb8ba91d5776a +Subproject commit 2645a5245082506a64acc58e7c2c7ac5c5bc4c3a diff --git a/ttcn/AtsBTP b/ttcn/AtsBTP index 0a29c3037d0554893bc23de26cb792f94376acfe..e1c90f29e9b2fcdbb79f064f90ba5f34710b8a2c 160000 --- a/ttcn/AtsBTP +++ b/ttcn/AtsBTP @@ -1 +1 @@ -Subproject commit 0a29c3037d0554893bc23de26cb792f94376acfe +Subproject commit e1c90f29e9b2fcdbb79f064f90ba5f34710b8a2c diff --git a/ttcn/AtsCAM b/ttcn/AtsCAM index 61c37436e45c22873ae3d512982db262d8274c89..76f1ea77ad27467cc39300c8599f1c0d37c0be76 160000 --- a/ttcn/AtsCAM +++ b/ttcn/AtsCAM @@ -1 +1 @@ -Subproject commit 61c37436e45c22873ae3d512982db262d8274c89 +Subproject commit 76f1ea77ad27467cc39300c8599f1c0d37c0be76 diff --git a/ttcn/AtsDENM b/ttcn/AtsDENM index f0f7b1b479e1bc01bc58cfcd86af9831c26ddefb..1800c762a7dbc5b6edbd8442b1e196035ff29bbc 160000 --- a/ttcn/AtsDENM +++ b/ttcn/AtsDENM @@ -1 +1 @@ -Subproject commit f0f7b1b479e1bc01bc58cfcd86af9831c26ddefb +Subproject commit 1800c762a7dbc5b6edbd8442b1e196035ff29bbc diff --git a/ttcn/AtsGeoNetworking b/ttcn/AtsGeoNetworking index a3d39a719245239aaf91c23c8da57464ab59dd53..d3e6b2662c996a8971256c926385d1ca1f9eb0a0 160000 --- a/ttcn/AtsGeoNetworking +++ b/ttcn/AtsGeoNetworking @@ -1 +1 @@ -Subproject commit a3d39a719245239aaf91c23c8da57464ab59dd53 +Subproject commit d3e6b2662c996a8971256c926385d1ca1f9eb0a0 diff --git a/ttcn/AtsIPv6OverGeoNetworking b/ttcn/AtsIPv6OverGeoNetworking index 49aec246ebefa8eb74b0a06566c47288c94e71d6..3e3e90ce7c54d4b3ab1e2551778d8d52aade506c 160000 --- a/ttcn/AtsIPv6OverGeoNetworking +++ b/ttcn/AtsIPv6OverGeoNetworking @@ -1 +1 @@ -Subproject commit 49aec246ebefa8eb74b0a06566c47288c94e71d6 +Subproject commit 3e3e90ce7c54d4b3ab1e2551778d8d52aade506c diff --git a/ttcn/AtsIS b/ttcn/AtsIS index f788e19d36b042b4471b0de38f9993b6d44f2250..4a3ccd7075a263116a3bed5a2450d63830dcf35a 160000 --- a/ttcn/AtsIS +++ b/ttcn/AtsIS @@ -1 +1 @@ -Subproject commit f788e19d36b042b4471b0de38f9993b6d44f2250 +Subproject commit 4a3ccd7075a263116a3bed5a2450d63830dcf35a diff --git a/ttcn/AtsMBR b/ttcn/AtsMBR new file mode 160000 index 0000000000000000000000000000000000000000..9bcf30d5b9747c99441c84c5ed01e351e49b7205 --- /dev/null +++ b/ttcn/AtsMBR @@ -0,0 +1 @@ +Subproject commit 9bcf30d5b9747c99441c84c5ed01e351e49b7205 diff --git a/ttcn/AtsPki b/ttcn/AtsPki index 0400d1acd33cb610211826772f4100706237d0cf..9b604d87ee204a3aee977d4cd845f229ca260ebc 160000 --- a/ttcn/AtsPki +++ b/ttcn/AtsPki @@ -1 +1 @@ -Subproject commit 0400d1acd33cb610211826772f4100706237d0cf +Subproject commit 9b604d87ee204a3aee977d4cd845f229ca260ebc diff --git a/ttcn/AtsSecurity b/ttcn/AtsSecurity index 121c65e29e4d636921dd6e2bf5b853aee90d7d2f..2666a89c1687ee67c8f4e21ee95daeedb112d001 160000 --- a/ttcn/AtsSecurity +++ b/ttcn/AtsSecurity @@ -1 +1 @@ -Subproject commit 121c65e29e4d636921dd6e2bf5b853aee90d7d2f +Subproject commit 2666a89c1687ee67c8f4e21ee95daeedb112d001 diff --git a/ttcn/LibCommon b/ttcn/LibCommon index fa2b5c7d9d2a170e4d876d82ed5e865d925837a7..21bad7c51917d19bebdff5b36983e22922421976 160000 --- a/ttcn/LibCommon +++ b/ttcn/LibCommon @@ -1 +1 @@ -Subproject commit fa2b5c7d9d2a170e4d876d82ed5e865d925837a7 +Subproject commit 21bad7c51917d19bebdff5b36983e22922421976 diff --git a/ttcn/LibIts b/ttcn/LibIts index f68487c477dd1f174cafd5a2f4e2bfc205ba8cfb..30d2ee5e2279e2c455427e97c57014101ff160ae 160000 --- a/ttcn/LibIts +++ b/ttcn/LibIts @@ -1 +1 @@ -Subproject commit f68487c477dd1f174cafd5a2f4e2bfc205ba8cfb +Subproject commit 30d2ee5e2279e2c455427e97c57014101ff160ae diff --git a/ttcn/modules/titan.TestPorts.Common_Components.Abstract_Socket/module b/ttcn/modules/titan.TestPorts.Common_Components.Abstract_Socket/module index affc1fa4e6497ff138b79a958caa79532fba6857..732c9934d2c87966b5ab9ba4e6886f353d5e4ace 160000 --- a/ttcn/modules/titan.TestPorts.Common_Components.Abstract_Socket/module +++ b/ttcn/modules/titan.TestPorts.Common_Components.Abstract_Socket/module @@ -1 +1 @@ -Subproject commit affc1fa4e6497ff138b79a958caa79532fba6857 +Subproject commit 732c9934d2c87966b5ab9ba4e6886f353d5e4ace diff --git a/ttcn/patch_lib_common_titan/module.mk b/ttcn/patch_lib_common_titan/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..3b3b66029142802a399c0aa3a7b66eb989ddbe3b --- /dev/null +++ b/ttcn/patch_lib_common_titan/module.mk @@ -0,0 +1,9 @@ +sources := \ + ttcn/LibCommon_AbstractData.ttcn \ + ttcn/LibCommon_BasicTypesAndValues.ttcn \ + ttcn/LibCommon_DataStrings.ttcn \ + ttcn/LibCommon_Sync.ttcn \ + ttcn/LibCommon_TextStrings.ttcn \ + ttcn/LibCommon_Time.ttcn \ + ttcn/LibCommon_VerdictControl.ttcn + diff --git a/ttcn/patch_lib_common_titan/ttcn/LibCommon_AbstractData.ttcn b/ttcn/patch_lib_common_titan/ttcn/LibCommon_AbstractData.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..8ae5f859cfc20f83233a6a500d67ebc45abb7d80 --- /dev/null +++ b/ttcn/patch_lib_common_titan/ttcn/LibCommon_AbstractData.ttcn @@ -0,0 +1,137 @@ +/** + * @author ETSI + * @version $URL$ + * $Id$ + * @desc A collection of functions for abstract data types which may be + * useful in the implementation of any TTCN-3 test suite. + * @remark End users should be aware that any changes made to the in + * definitions this module may be overwritten in future releases. + * End users are encouraged to contact the distributers of this + * module regarding their modifications or additions so that future + * updates will include your changes. + * @copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * + */ + module LibCommon_AbstractData { + + import from LibCommon_BasicTypesAndValues all; + + group stringStack { + + type record StringStack { + UInt stackSize, + StringItems stringItems + } + + type record of charstring StringItems; + + /** + * @desc Constant which can be used to initialize a + * string stack. A string stack can be intialized by + * assigning this value in the variable declariation. + * An alternative is to call the initlialization function. + * @see LibCommon_AbstractData.f_initStringStack + * @remark Note that an initlialized stack stack is not + * necessarily the same as an empty string stack. + * An empty tring stack as 0 zero elements but may + * have a non empty list of (empty) items. + */ + const StringStack c_initStringStack := { 0, {} } + + /** + * @desc The invocation of this function will initialize + * a string stack to an empty string stack. + * An alternative is to initlialize a stack using a + * constant value. + * @see LibCommon_AbstractData.c_initStringStack + * @param p_stack String stack to be initialized. + */ + function f_initStringStack ( inout StringStack p_stack ) { + p_stack := c_initStringStack + } + + /** + * @desc This function checks if a string stack is empty. + * @param p_stack String stack to be checked. + * @return true if empty, false if not empty + */ + function f_isStringStackEmpty ( inout StringStack p_stack ) + return boolean { + if ( p_stack.stackSize == 0 ) {return true} + else {return false} + } + + /** + * @desc This function checks if a given string is on the + * string stack. + * @param p_stack String stack where the string item + * is to be looked for. + * @param p_item String to be checked for. + * @return true if found, false if not found + */ + function f_isItemOnStringStack ( inout StringStack p_stack, + in charstring p_item ) + return boolean { + var integer i; + for (i := 0; i < p_stack.stackSize; i := i+1 ) { + if ( p_stack.stringItems[i] == p_item ) { + return true; + } + } + return false; + } + + /** + * @desc This function checks if a given string is on the + * string stack. + * @param p_stack String stack where the string item + * is to be looked for. + * @param p_item String item on top of the stack. + * @return false if stack is empty, true otherwise + */ + function f_peekStringStackTop ( inout StringStack p_stack, + out charstring p_item) + return boolean { + if (p_stack.stackSize == 0) { + p_item := "f_peekTopStringStack: String stack is empty!"; + return false; + } + p_item := valueof(p_stack.stringItems[p_stack.stackSize-1]); + return true; + } + + + /** + * @desc This function puts a string to the top of a + * string stack. + * @param p_stack String stack to which the string item + * is to be added. + * @param p_item String to be added. + */ + function f_pushStringStack ( inout StringStack p_stack, + in charstring p_item ) { + p_stack.stringItems[p_stack.stackSize] := p_item; + p_stack.stackSize := p_stack.stackSize + 1; + } + + /** + * @desc This function removes the string from the top of a + * string stack. If the stack is empty nothing is done + * @param p_stack String stack from which the top string item + * is to be removed. + */ + function f_popStringStack ( inout StringStack p_stack ) { + if ( p_stack.stackSize > 0 ) { + p_stack.stackSize := p_stack.stackSize-1; + // "delete" top stack item to be safe + // Note: due to record of index the "old top" is size-1! + p_stack.stringItems[p_stack.stackSize] := ""; + } + } + + } // end group stringStack + +} // end module LibCommon_AbstractData diff --git a/ttcn/patch_lib_common_titan/ttcn/LibCommon_BasicTypesAndValues.ttcn b/ttcn/patch_lib_common_titan/ttcn/LibCommon_BasicTypesAndValues.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..9b5477d98b422df6a9051cfd7b589269cf553be3 --- /dev/null +++ b/ttcn/patch_lib_common_titan/ttcn/LibCommon_BasicTypesAndValues.ttcn @@ -0,0 +1,247 @@ +/** + * @author ETSI + * @version $URL$ + * $Id$ + * @desc A collection of basic type and value definitions which may be + * useful in the implementation of any TTCN-3 test suite.

+ * @remark End users should be aware that any changes made to the in + * definitions this module may be overwritten in future releases. + * End users are encouraged to contact the distributers of this + * module regarding their modifications or additions so that future + * updates will include your changes. + * @copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * + */ + module LibCommon_BasicTypesAndValues { + + /** + * @remark Number in subtype name always indicates encoding length + * in _bits_ + */ + group unsignedIntegerDefintions { + + const integer c_uInt1Max := 1; + const integer c_uInt2Max := 3; + const integer c_uInt3Max := 7; + const integer c_uInt4Max := 15; + const integer c_uInt5Max := 31; + const integer c_uInt6Max := 63; + const integer c_uInt7Max := 127; + const integer c_uInt8Max := 255; + const integer c_uInt9Max := 511; + const integer c_uInt10Max := 1023; + const integer c_uInt11Max := 2047; + const integer c_uInt12Max := 4095; + const integer c_uInt13Max := 8191; + const integer c_uInt14Max := 16383; + const integer c_uInt15Max := 32767; + const integer c_uInt16Max := 65535; + const integer c_uInt17Max := 131071; + const integer c_uInt18Max := 262143; + const integer c_uInt19Max := 524287; + const integer c_uInt20Max := 1048575; + const integer c_uInt21Max := 2097151; + const integer c_uInt22Max := 4194303; + const integer c_uInt23Max := 8388607; + const integer c_uInt24Max := 16777215; + const integer c_uInt25Max := 33554431; + const integer c_uInt26Max := 67108863; + const integer c_uInt27Max := 134217727; + const integer c_uInt28Max := 268435456; + const integer c_uInt29Max := 536870911; + const integer c_uInt30Max := 1073741823; + const integer c_uInt31Max := 2147483647; + const integer c_uInt32Max := 4294967295; + const integer c_uInt36Max := 68719476735; + const integer c_uInt48Max := 281474976710655; + const integer c_uInt52Max := 4503599627370495; + const integer c_uInt64Max := 18446744073709551615; + + type integer UInt (0 .. infinity); + type integer UInt1 (0 .. c_uInt1Max) with {variant "unsigned 1 bit"}; + type integer UInt2 (0 .. c_uInt2Max) with {variant "unsigned 2 bit"}; + type integer UInt3 (0 .. c_uInt3Max) with {variant "unsigned 3 bit"}; + type integer UInt4 (0 .. c_uInt4Max) with {variant "unsigned 4 bit"}; + type integer UInt5 (0 .. c_uInt5Max) with {variant "unsigned 5 bit"}; + type integer UInt6 (0 .. c_uInt6Max) with {variant "unsigned 6 bit"}; + type integer UInt7 (0 .. c_uInt7Max) with {variant "unsigned 7 bit"}; + type integer UInt8 (0 .. c_uInt8Max) with {variant "unsigned 8 bit"}; + type integer UInt9 (0 .. c_uInt9Max) with {variant "unsigned 9 bit"}; + type integer UInt10 (0 .. c_uInt10Max) with {variant "unsigned 10 bit"}; + type integer UInt11 (0 .. c_uInt11Max) with {variant "unsigned 11 bit"}; + type integer UInt12 (0 .. c_uInt12Max) with {variant "unsigned 12 bit"}; + type integer UInt13 (0 .. c_uInt13Max) with {variant "unsigned 13 bit"}; + type integer UInt14 (0 .. c_uInt14Max) with {variant "unsigned 14 bit"}; + type integer UInt15 (0 .. c_uInt15Max) with {variant "unsigned 15 bit"}; + type integer UInt16 (0 .. c_uInt16Max) with {variant "unsigned 16 bit"}; + type integer UInt17 (0 .. c_uInt17Max) with {variant "unsigned 17 bit"}; + type integer UInt18 (0 .. c_uInt18Max) with {variant "unsigned 18 bit"}; + type integer UInt19 (0 .. c_uInt19Max) with {variant "unsigned 19 bit"}; + type integer UInt20 (0 .. c_uInt20Max) with {variant "unsigned 20 bit"}; + type integer UInt21 (0 .. c_uInt21Max) with {variant "unsigned 21 bit"}; + type integer UInt22 (0 .. c_uInt22Max) with {variant "unsigned 22 bit"}; + type integer UInt23 (0 .. c_uInt23Max) with {variant "unsigned 23 bit"}; + type integer UInt24 (0 .. c_uInt24Max) with {variant "unsigned 24 bit"}; + type integer UInt25 (0 .. c_uInt25Max) with {variant "unsigned 25 bit"}; + type integer UInt26 (0 .. c_uInt26Max) with {variant "unsigned 26 bit"}; + type integer UInt27 (0 .. c_uInt27Max) with {variant "unsigned 27 bit"}; + type integer UInt28 (0 .. c_uInt28Max) with {variant "unsigned 28 bit"}; + type integer UInt29 (0 .. c_uInt29Max) with {variant "unsigned 29 bit"}; + type integer UInt30 (0 .. c_uInt30Max) with {variant "unsigned 30 bit"}; + type integer UInt31 (0 .. c_uInt31Max) with {variant "unsigned 31 bit"}; + type integer UInt32 (0 .. c_uInt32Max) with {variant "unsigned 32 bit"}; + type integer UInt36 (0 .. c_uInt36Max) with {variant "unsigned 36 bit"}; + type integer UInt48 (0 .. c_uInt48Max) with {variant "unsigned 48 bit"}; + type integer UInt52 (0 .. c_uInt52Max) with {variant "unsigned 52 bit"}; + type integer UInt64 (0 .. c_uInt64Max) with {variant "unsigned 64 bit"}; + + } // end group unsignedIntegerDefintions + + /** + * @remark Number in subtype name always indicates encoding length + * in _bits_ + */ + group signedIntegerDefintions { + + const integer c_int1Min := -1; + const integer c_int1Max := 0; + const integer c_int2Min := -2; + const integer c_int2Max := 1; + const integer c_int3Min := -4; + const integer c_int3Max := 3; + const integer c_int4Min := -8; + const integer c_int4Max := 7; + const integer c_int5Min := -16; + const integer c_int5Max := 15; + const integer c_int6Min := -32; + const integer c_int6Max := 31; + const integer c_int7Min := -64; + const integer c_int7Max := 63; + const integer c_int8Min := -128; + const integer c_int8Max := 127; + const integer c_int9Min := -256; + const integer c_int9Max := 255; + const integer c_int10Min := -512; + const integer c_int10Max := 511; + const integer c_int11Min := -1024; + const integer c_int11Max := 1023; + const integer c_int12Min := -2048; + const integer c_int12Max := 2047; + const integer c_int13Min := -4096; + const integer c_int13Max := 4095; + const integer c_int14Min := -8192; + const integer c_int14Max := 8191; + const integer c_int15Min := -16384; + const integer c_int15Max := 16383; + const integer c_int16Min := -32768; + const integer c_int16Max := 32767; + const integer c_int17Min := -65536; + const integer c_int17Max := 65535; + const integer c_int18Min := -131072; + const integer c_int18Max := 131071; + const integer c_int19Min := -262144; + const integer c_int19Max := 262143; + const integer c_int20Min := -524288; + const integer c_int20Max := 524287; + const integer c_int21Min := -1048576; + const integer c_int21Max := 1048575; + const integer c_int22Min := -2097152; + const integer c_int22Max := 2097151; + const integer c_int23Min := -4194304; + const integer c_int23Max := 4194303; + const integer c_int24Min := -8388608; + const integer c_int24Max := 8388607; + const integer c_int25Min := -16777216; + const integer c_int25Max := 16777215; + const integer c_int26Min := -33554432; + const integer c_int26Max := 33554431; + const integer c_int27Min := -67108864; + const integer c_int27Max := 67108863; + const integer c_int28Min := -134217728; + const integer c_int28Max := 134217727; + const integer c_int29Min := -268435456; + const integer c_int29Max := 268435456; + const integer c_int30Min := -536870912; + const integer c_int30Max := 536870911; + const integer c_int31Min := -1073741824; + const integer c_int31Max := 1073741823; + const integer c_int32Min := -2147483648; + const integer c_int32Max := 2147483647; + + type integer Int; + type integer Int1 (c_int1Min .. c_int1Max) with { variant "1 bit"}; + type integer Int2 (c_int2Min .. c_int2Max) with { variant "2 bit"}; + type integer Int3 (c_int3Min .. c_int3Max) with { variant "3 bit"}; + type integer Int4 (c_int4Min .. c_int4Max) with { variant "4 bit"}; + type integer Int5 (c_int5Min .. c_int5Max) with { variant "5 bit"}; + type integer Int6 (c_int6Min .. c_int6Max) with { variant "6 bit"}; + type integer Int7 (c_int7Min .. c_int7Max) with { variant "7 bit"}; + type integer Int8 (c_int8Min .. c_int8Max) with { variant "8 bit"}; + type integer Int9 (c_int9Min .. c_int9Max) with { variant "9 bit"}; + type integer Int10 (c_int10Min .. c_int10Max) with { variant "10 bit"}; + type integer Int11 (c_int11Min .. c_int11Max) with { variant "11 bit"}; + type integer Int12 (c_int12Min .. c_int12Max) with { variant "12 bit"}; + type integer Int13 (c_int13Min .. c_int13Max) with { variant "13 bit"}; + type integer Int14 (c_int14Min .. c_int14Max) with { variant "14 bit"}; + type integer Int15 (c_int15Min .. c_int15Max) with { variant "15 bit"}; + type integer Int16 (c_int16Min .. c_int16Max) with { variant "16 bit"}; + type integer Int17 (c_int17Min .. c_int17Max) with { variant "17 bit"}; + type integer Int18 (c_int18Min .. c_int18Max) with { variant "18 bit"}; + type integer Int19 (c_int19Min .. c_int19Max) with { variant "19 bit"}; + type integer Int20 (c_int20Min .. c_int20Max) with { variant "20 bit"}; + type integer Int21 (c_int21Min .. c_int21Max) with { variant "21 bit"}; + type integer Int22 (c_int22Min .. c_int22Max) with { variant "22 bit"}; + type integer Int23 (c_int23Min .. c_int23Max) with { variant "23 bit"}; + type integer Int24 (c_int24Min .. c_int24Max) with { variant "24 bit"}; + type integer Int25 (c_int25Min .. c_int25Max) with { variant "25 bit"}; + type integer Int26 (c_int26Min .. c_int26Max) with { variant "26 bit"}; + type integer Int27 (c_int27Min .. c_int27Max) with { variant "27 bit"}; + type integer Int28 (c_int28Min .. c_int28Max) with { variant "28 bit"}; + type integer Int29 (c_int29Min .. c_int29Max) with { variant "29 bit"}; + type integer Int30 (c_int30Min .. c_int30Max) with { variant "30 bit"}; + type integer Int31 (c_int31Min .. c_int31Max) with { variant "31 bit"}; + type integer Int32 (c_int32Min .. c_int32Max) with { variant "32 bit"}; + + } // end group signedIntegerDefintions + + group zeroedIntegers { + + const UInt1 c_uInt1Zero := 0; + const UInt2 c_uInt2Zero := 0; + const UInt3 c_uInt3Zero := 0; + const UInt4 c_uInt4Zero := 0; + const UInt5 c_uInt5Zero := 0; + const UInt6 c_uInt6Zero := 0; + const UInt7 c_uInt7Zero := 0; + const UInt8 c_uInt8Zero := 0; + const UInt10 c_uInt10Zero := 0; + const UInt12 c_uInt12Zero := 0; + const UInt14 c_uInt14Zero := 0; + const UInt16 c_uInt16Zero := 0; + const UInt24 c_uInt24Zero := 0; + const UInt32 c_uInt32Zero := 0; + const UInt48 c_uInt48Zero := 0; + + }//end group zeroedInt + + /** + * @remark Number in subtype name always indicates encoding length + * in _bits_ + */ + group booleanDefintions { + + type boolean Bool1 with { variant "1 bit" }; + type boolean Bool2 with { variant "2 bit" }; + type boolean Bool3 with { variant "3 bit" }; + type boolean Bool4 with { variant "4 bit" }; + type boolean Bool5 with { variant "5 bit" }; + type boolean Bool6 with { variant "6 bit" }; + type boolean Bool7 with { variant "7 bit" }; + type boolean Bool8 with { variant "8 bit" }; + + } // end group booleanDefintions + +} // end module LibCommon_BasicTypesAndValues diff --git a/ttcn/patch_lib_common_titan/ttcn/LibCommon_DataStrings.ttcn b/ttcn/patch_lib_common_titan/ttcn/LibCommon_DataStrings.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..9bfbe61a78b4cb161929cae010cf34f510d97e00 --- /dev/null +++ b/ttcn/patch_lib_common_titan/ttcn/LibCommon_DataStrings.ttcn @@ -0,0 +1,168 @@ +/** + * + * @author ETSI + * @version $URL$ + * $Id$ + * @desc A collection of data string type and value definitions which + * may be useful in the implementation of any TTCN-3 test + * suite. "Data string" refers to TTCN-3 hexstring, octetstring + * and bitstring types. + * @remark End users should be aware that any changes made to the in + * definitions this module may be overwritten in future releases. + * End users are encouraged to contact the distributers of this + * module regarding their modifications or additions so that future + * updates will include your changes. + * @copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * + */ + module LibCommon_DataStrings { + + /** + * @remark Number in name indicates string length in number of + * _bits_ + */ + group bitStringSubTypes { + + type bitstring Bit1 length(1) with {encode "length(1)"}; + type bitstring Bit2 length(2) with {encode "length(2)"}; + type bitstring Bit3 length(3) with {encode "length(3)"}; + type bitstring Bit4 length(4) with {encode "length(4)"}; + type bitstring Bit5 length(5) with {encode "length(5)"}; + type bitstring Bit6 length(6) with {encode "length(6)"}; + type bitstring Bit7 length(7) with {encode "length(7)"}; + type bitstring Bit8 length(8) with {encode "length(8)"}; + type bitstring Bit9 length(9) with {encode "length(9)"}; + type bitstring Bit10 length(10) with {encode "length(10)"}; + type bitstring Bit11 length(11) with {encode "length(11)"}; + type bitstring Bit12 length(12) with {encode "length(12)"}; + type bitstring Bit13 length(13) with {encode "length(13)"}; + type bitstring Bit14 length(14) with {encode "length(14)"}; + type bitstring Bit15 length(15) with {encode "length(15)"}; + type bitstring Bit16 length(16) with {encode "length(16)"}; + type bitstring Bit17 length(17) with {encode "length(17)"}; + type bitstring Bit18 length(18) with {encode "length(18)"}; + type bitstring Bit19 length(19) with {encode "length(19)"}; + type bitstring Bit20 length(20) with {encode "length(20)"}; + type bitstring Bit21 length(21) with {encode "length(21)"}; + type bitstring Bit22 length(22) with {encode "length(22)"}; + type bitstring Bit23 length(23) with {encode "length(23)"}; + type bitstring Bit24 length(24) with {encode "length(24)"}; + type bitstring Bit25 length(25) with {encode "length(25)"}; + type bitstring Bit26 length(26) with {encode "length(26)"}; + type bitstring Bit27 length(27) with {encode "length(27)"}; + type bitstring Bit28 length(28) with {encode "length(28)"}; + type bitstring Bit29 length(29) with {encode "length(29)"}; + type bitstring Bit30 length(30) with {encode "length(30)"}; + type bitstring Bit31 length(31) with {encode "length(31)"}; + type bitstring Bit32 length(32) with {encode "length(32)"}; + type bitstring Bit40 length(40) with {encode "length(40)"}; + + type bitstring Bit48 length(48) with {encode "length(48)"}; + type bitstring Bit64 length(64) with {encode "length(64)"}; + type bitstring Bit72 length(72) with {encode "length(72)"}; + type bitstring Bit128 length(128) with {encode "length(128)"}; + type bitstring Bit144 length(144) with {encode "length(144)"}; + type bitstring Bit256 length(256) with {encode "length(256)"}; + + } // end group bitStringSubTypes + + group zeroedBits { + + const Bit1 c_1ZeroBit := int2bit(0,1); + const Bit2 c_2ZeroBits := int2bit(0,2); + const Bit4 c_4ZeroBits := int2bit(0,4); + const Bit5 c_5ZeroBits := int2bit(0,5); + const Bit6 c_6ZeroBits := int2bit(0,6); + const Bit8 c_8ZeroBits := int2bit(0,8); + const Bit14 c_14ZeroBits := int2bit(0,14); + const Bit64 c_64ZeroBits := int2bit(0,64); + + }//end group zeroedBits + + /** + * @remark Number in name indicates string length in number of + * _octets_ + */ + group octetStringSubTypes { + + type octetstring Oct1 length(1) with {encode "length(1)"}; + type octetstring Oct2 length(2) with {encode "length(2)"}; + type octetstring Oct3 length(3) with {encode "length(3)"}; + type octetstring Oct4 length(4) with {encode "length(4)"}; + type octetstring Oct5 length(5) with {encode "length(5)"}; + type octetstring Oct6 length(6) with {encode "length(6)"}; + type octetstring Oct7 length(7) with {encode "length(7)"}; + type octetstring Oct8 length(8) with {encode "length(8)"}; + type octetstring Oct9 length(9) with {encode "length(9)"}; + type octetstring Oct10 length(10) with {encode "length(10)"}; + type octetstring Oct11 length(11) with {encode "length(11)"}; + type octetstring Oct12 length(12) with {encode "length(12)"}; + type octetstring Oct13 length(13) with {encode "length(13)"}; + type octetstring Oct14 length(14) with {encode "length(14)"}; + type octetstring Oct15 length(15) with {encode "length(15)"}; + type octetstring Oct16 length(16) with {encode "length(16)"}; + + type octetstring Oct20 length(20) with {encode "length(20)"}; + type octetstring Oct32 length(32) with {encode "length(32)"}; + type octetstring Oct48 length(48) with {encode "length(48)"}; + type octetstring Oct64 length(64) with {encode "length(64)"}; + type octetstring Oct80 length(80) with {encode "length(80)"}; + type octetstring Oct96 length(96) with {encode "length(96)"}; + type octetstring Oct128 length(128) with {encode "length(128)"}; + type octetstring Oct160 length(160) with {encode "length(160)"}; + type octetstring Oct320 length(320) with {encode "length(320)"}; + type octetstring Oct640 length(640) with {encode "length(640)"}; + type octetstring Oct1280 length(1280) with {encode "length(1280)"}; + type octetstring Oct1380 length(1380) with {encode "length(1380)"}; + + type octetstring Oct0to3 length(0..3) with {encode "length(0..3)"}; + type octetstring Oct0to8 length(0..16) with {encode "length(0..8)"}; + type octetstring Oct0to12 length(0..12) with {encode "length(0..12)"}; + type octetstring Oct0to16 length(0..16) with {encode "length(0..16)"}; + type octetstring Oct0to31 length(0..31) with {encode "length(0..31)"}; + type octetstring Oct0to20 length(0..20) with {encode "length(0..20)"}; + type octetstring Oct0to30 length(0..20) with {encode "length(0..30)"}; + type octetstring Oct0to127 length(0..127) with {encode "length(0..127)"}; + type octetstring Oct0to255 length(0..255) with {encode "length(0..255)"}; + + type octetstring Oct1to15 length(1..15) with {encode "length(1..15)"}; + type octetstring Oct1to31 length(1..31) with {encode "length(1..31)"}; + type octetstring Oct1to128 length(1..128) with {encode "length(1..128)"}; + type octetstring Oct1to254 length(1..254) with {encode "length(1..254)"}; + type octetstring Oct1to255 length(1..255) with {encode "length(1..255)"}; + + type octetstring Oct4to16 length(4..16) with {encode "length(4..16)"}; + type octetstring Oct6to15 length(6..15) with {encode "length(6..15)"}; + + } // end group octetStringSubTypes + + group zeroedBytes { + const Oct1 c_1ZeroByte := int2oct(0,1); + const Oct2 c_2ZeroBytes := int2oct(0,2); + const Oct4 c_4ZeroBytes := int2oct(0,4); + const Oct6 c_6ZeroBytes := int2oct(0,6); + const Oct8 c_8ZeroBytes := int2oct(0,8); + const Oct9 c_9ZeroBytes := int2oct(0,9); + const Oct12 c_12ZeroBytes := int2oct(0,12); + const Oct16 c_16ZeroBytes := int2oct(0,16); + const Oct20 c_20ZeroBytes := int2oct(0,20); + + const Oct80 c_80ZeroBytes := int2oct(0,80); + const Oct160 c_160ZeroBytes := int2oct(0,160); + const Oct320 c_320ZeroBytes := int2oct(0,320); + const Oct640 c_640ZeroBytes := int2oct(0,640); + const Oct1280 c_1280ZeroBytes := int2oct(0,1280); + const Oct1380 c_1380ZeroBytes := int2oct(0,1380); + const octetstring c_256ZeroBytes := int2oct(0,256); + const octetstring c_1KZeroBytes := int2oct(0,1024); + const octetstring c_4KZeroBytes := int2oct(0,4096); + const octetstring c_16KZeroBytes := int2oct(0,16384); + const octetstring c_64KZeroBytes := int2oct(0,65536); + const octetstring c_128KZeroBytes := int2oct(0,131072); + + }//end group zeroedBytes + +} // end module LibCommon_DataStrings diff --git a/ttcn/patch_lib_common_titan/ttcn/LibCommon_Sync.ttcn b/ttcn/patch_lib_common_titan/ttcn/LibCommon_Sync.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..39d965939571204acf5ac0d441830eb02676a43c --- /dev/null +++ b/ttcn/patch_lib_common_titan/ttcn/LibCommon_Sync.ttcn @@ -0,0 +1,1359 @@ +/** + * @author ETSI + * @version $URL$ + * $Id$ + * @desc This module implements _one_ generic synchronization mechanism + * for TTCN-3 test cases with one or more test components. + * Key concept is here that one test component acts as a + * synchronization server which listens and triggers one or more + * synchronization clients. It is recomended to use the MTC always as + * the synchronization server but in theory also a PTC can act as such + * a server.

+ * This synchronization is used by calling a function on + * the server test component to wait for a desired amount of clients + * to notify the server that they have reached a specific synchronization + * point. Each client test component must call another + * function to perform this notification.

+ * In the event that a client is not able to reach a synchronization + * point the server sends out a signal to all clients to abort the + * test case. This signal is a STOP message which can be caught by + * a test component default which in turn can then run a proper + * shut down behavior based on the current state of the test + * component.

+ * Note that this synchronization mechanism can also be used + * in a special mode called "self synchronization" when a test case + * only has one test component. Here, the test component in essence + * acts as a server and client at the same time. The main benefit of + * using self synchoronization is that the same shutdown mechanisms + * can also be reused fomr the multi component test cases.

+ * This module contains a lot of TTCN-3 definitions. It has been + * structured into tree main groups to help the user to identify + * quickly relevant TTCN-3 definitions. For rookie users of this + * module basicUserRelevantDefinitions should offer all the needed + * definitions. Advanced users can consider use of definitions in + * advancedUserRelevantDefinitions. Finally, internalDefinitions + * are definitions which are required for the module to work + * properly but do not need to be used in your code. Remember that + * the main motiviation of this sychronization module is to offer + * are _simple_ user interface. Practice has shown that when writing + * actual test component behavior _only a handful_ of functions + * usually wind up being used! Also check the synchronization examples + * module for example uses of this synchronization mechanism.

+ * The invocation of the sync functions is also closely tied + * to the verdict control functions which should also be reviewed + * prior to using this module.

+ * This module has been derived from EtsiCommon_Synchronization + * which was created in ETSIs STF256/276. It has been kept + * intentionally separate to avoid conflicts with future ETSI + * test suite releases. + * @see LibCommon_Sync.basicUserRelevantDefinitions + * @see LibCommon_Sync.advancedUserRelevantDefinitions + * @remark End users should be aware that any changes made to the in + * definitions this module may be overwritten in future releases. + * End users are encouraged to contact the distributers of this + * module regarding their modifications or additions so that future + * updates will include your changes. + * @copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * + */ +module LibCommon_Sync { + + //Common + import from LibCommon_BasicTypesAndValues all; + import from LibCommon_AbstractData all; + import from LibCommon_VerdictControl all; + + group basicUserRelevantDefinitions { + + group importantSyncTypeDefinitions { + + group compTypeRelated { + + /** + * @desc This type is used to be the base of any synchronization + * behavior which is to be executed on a sync server + * component. The test component which acts as a + * sync server in a test case must NOT directly use + * this component type in its runs on clause! + * Note that server synchronization functions may be + * invoked by a test component as long as its + * component type is type compatible to this component + * type definition! + */ + type component BaseSyncComp { + port SyncPort syncPort; + timer tc_sync := PX_TSYNC_TIME_LIMIT; + } + + /** + * @desc This type is used to define any synchronization + * behavior which is to be executed on a sync server + * component. The test component which acts as a + * sync server in a test case may - but does + * not have to - directly use this component type its + * runs on clause. + * Note that server synchronization functions may be + * invoked by a test component as long as its + * component type is type compatible to this component + * type definition! + */ + type component ServerSyncComp extends BaseSyncComp { + timer tc_shutDown := PX_TSHUT_DOWN_TIME_LIMIT; + } + + /** + * @desc This type is used to define any synchronization + * behavior which is to be executed on a sync client + * component. The test component(s) which act as a + * sync client in a test case may - but do not have + * to - directly use this component type their runs + * on clause. + * Note that server synchronization functions may be + * invoked by a test component as long as its + * component type is type compatible to this component + * type definition! + */ + type component ClientSyncComp extends BaseSyncComp { + var StringStack v_stateStack:= c_initStringStack; + var TestcaseStep vc_testcaseStep := e_preamble; + } + + /** + * @desc This type is used to define any synchronization + * behavior which is relevant to non-concurrent test + * cases. + * Note that self synchronization functions may be + * invoked by a test component as long as its + * component type is type compatible to this component + * type definition! + * Note also that this type is type compatible to the + * ClientSyncComp type so that shutdown altsteps from + * concurrent test cases can also be reused in single + * component test cases! + * @see LibCommon_Sync.ClientSyncComp + */ + type component SelfSyncComp extends ClientSyncComp { + port SyncPort syncSendPort; + } + + /** + * @desc This port type must be imported into test suites + * when defining test component types which are + * type compatible to a synchronization component + * type + * @see LibCommon_Sync.SelfSyncComp + * @see LibCommon_Sync.ServerSyncComp + * @see LibCommon_Sync.ClientSyncComp + */ + type port SyncPort message { + inout SyncCmd + } with { + extension "internal" + } + + + /** + * @desc Describes in which step of execution is the testcase + */ + type enumerated TestcaseStep { + e_preamble, + e_testBody, + e_postamble + } + + } // end compTypeRelated + + group standardSyncPointNames { + const charstring c_prDone := "preambleDone"; + const charstring c_poDone := "postambleDone"; + const charstring c_tbDone := "testBodyDone"; + const charstring c_initDone := "initDone"; + } + + } // end group importantSyncTypeDefinitions + + group syncCompTestConfiguration { + + /** + * @desc Calls self connect function if invoking + * component is the MTC or otherwise connects the client + * the server. This function allows to implement preambles + * in a way that they can be used by test components + * in both non-concurrent as well as concurrent test + * cases! + * @remark This function should _not_ be called if the MTC + * acts as a client (and not a server) in a concurrent + * test case. In this case f_connect4ClientSync + * should be used instead. + * @see LibCommon_Sync.f_connect4SelfSync + * @see LibCommon_Sync.f_connect4ClientSync + */ + function f_connect4SelfOrClientSync() + runs on SelfSyncComp { + if ( self == mtc ) { + f_connect4SelfSync(); + } else { + f_connect4ClientSync(); + } + } + + /** + * @desc Calls self connect function if the invoking + * component is the MTC or otherwise disconnects the client + * from the server. This function allows to implement + * postambles in a way that they can be used in both + * non-concurrent as well as concurrent test cases. + * @remark This function should _not_ be called if the MTC + * acts as a client (and not a server) in a concurrent + * test case. In this case f_disconnect4ClientSync + * should be used instead. + * @see LibCommon_Sync.f_disconnect4SelfSync + * @see LibCommon_Sync.f_disconnect4ClientSync + */ + function f_disconnect4SelfOrClientSync() + runs on SelfSyncComp { + if ( self == mtc ) { + f_disconnect4SelfSync(); + } else { + f_disconnect4ClientSync(); + } + } + + } // end group syncCompTestConfiguration + + group syncFunctions { + + /** + * @desc Implements synchronization of 2 clients from server side + * on one or more synchronization points. + * If problem occurs, then server sends STOP to all clients. + * Waits for PX_TSYNC_TIME_LIMIT to let clients + * finish executing their behavior until this + * synchronization point. After passing all synchronization + * points successfuly the server waits for all clients + * to stop. + * See f_serverSyncClientsTimed for overwriting this + * the timing constraint! + * This function sets the server component verdict. + * @remark The use of this function requires prior connection of + * the server sync ports! + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.f_serverSyncClientsTimed + * @see LibCommon_Sync.f_serverWaitForAllClientsToStop + * @param p_syncPointIds list of synchronization point name/ids + */ + function f_serverSync2ClientsAndStop( in SyncPointList p_syncPointIds ) + runs on ServerSyncComp { + f_serverSyncNClientsAndStop(2, p_syncPointIds); + } + + /** + * @desc Implements synchronization of 3 clients from server side + * on one or more synchronization points. + * If problem occurs, then server sends STOP to all clients. + * Waits for PX_TSYNC_TIME_LIMIT to let clients + * finish executing their behavior until this + * synchronization point. After passing all synchronization + * points successfuly the server waits for all clients + * to stop. + * See f_serverSyncClientsTimed for overwriting this + * the timing constraint! + * This function sets the server component verdict. + * @remark The use of this function requires prior connection of + * the server sync ports! + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.f_serverSyncClientsTimed + * @see LibCommon_Sync.f_serverWaitForAllClientsToStop + * @param p_syncPointIds list of synchronization point name/ids + */ + function f_serverSync3ClientsAndStop( in SyncPointList p_syncPointIds ) + runs on ServerSyncComp { + f_serverSyncNClientsAndStop(3, p_syncPointIds); + } + + /** + * @desc Implements synchronization of 4 clients from server side + * on one or more synchronization points. + * If problem occurs, then server sends STOP to all clients. + * Waits for PX_TSYNC_TIME_LIMIT to let clients + * finish executing their behavior until this + * synchronization point. After passing all synchronization + * points successfuly the server waits for all clients + * to stop. + * See f_serverSyncClientsTimed for overwriting this + * the timing constraint! + * This function sets the server component verdict. + * @remark The use of this function requires prior connection of + * the server sync ports! + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.f_serverSyncClientsTimed + * @see LibCommon_Sync.f_serverWaitForAllClientsToStop + * @param p_syncPointIds list of synchronization point name/ids + */ + function f_serverSync4ClientsAndStop( in SyncPointList p_syncPointIds ) + runs on ServerSyncComp { + f_serverSyncNClientsAndStop(4, p_syncPointIds); + } + + /** + * @desc Implements synchronization of N clients from server side + * on one or more synchronization points. + * If problem occurs, then server sends STOP to all clients. + * Waits for PX_TSYNC_TIME_LIMIT to let clients + * finish executing their behavior until this + * synchronization point. After passing all synchronization + * points successfuly the server waits for all clients + * to stop. + * See f_serverSyncClientsTimed for overwriting this + * the timing constraint! + * This function sets the server component verdict. + * @remark The use of this function requires prior connection of + * the server sync ports! + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.f_serverSyncClientsTimed + * @see LibCommon_Sync.f_serverWaitForAllClientsToStop + * @param p_numClients number of synchronization clients + * @param p_syncPointIds list of synchronization point name/ids + */ + function f_serverSyncNClientsAndStop ( + in UInt p_numClients, + in SyncPointList p_syncPointIds ) + runs on ServerSyncComp { + var integer i, v_noOfSyncIds := sizeof(p_syncPointIds); + for ( i := 0; i < v_noOfSyncIds; i := i+1 ) { + f_serverSyncClientsTimed ( + p_numClients, + valueof(p_syncPointIds[i]), + PX_TSYNC_TIME_LIMIT ); + } + f_serverWaitForAllClientsToStop(); + } + + /** + * @desc Implements synchronization of 2 clients and 1 UT from server side + * on one or more synchronization points. + * If problem occurs, then server sends STOP to all clients. + * Waits for PX_TSYNC_TIME_LIMIT to let clients + * finish executing their behavior until this + * synchronization point. After passing all synchronization + * points successfuly the server waits for all clients + * to stop. + * See f_serverSyncClientsTimed for overwriting this + * the timing constraint! + * This function sets the server component verdict. + * @remark The use of this function requires prior connection of + * the server sync ports! + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.f_serverSyncClientsTimed + * @see LibCommon_Sync.f_serverWaitForAllClientsToStop + * @param p_syncPointIds list of synchronization point name/ids + */ + function f_serverSync2ClientsUtAndStop( in SyncPointList p_syncPointIds ) + runs on ServerSyncComp { + var integer i, v_noOfSyncIds := sizeof(p_syncPointIds); + for ( i := 0; i < v_noOfSyncIds; i := i+1 ) { + f_serverSyncClientsTimed(3,valueof(p_syncPointIds[i]), PX_TSYNC_TIME_LIMIT); + } + f_serverWaitForAllClientsToStop(); + } + + /** + * @desc Calls either self synchronization function if + * invoking component is the MTC, otherwise + * calls client synchronization. After that it + * sets the verdict based on the specified return code. + * This function allows to implement TTCN-3 functions + * in a way that they can be used in both non-concurrent + * as well as concurrent test cases. + * @remark This function should _not_ be called if the MTC + * acts as a client (and not a server) in a concurrent + * test case. In this case f_clientSyncAndVerdict + * should be used instead. + * @param p_syncPoint Synchronization point name/id + * @param p_ret Current behavior execution status + * @see LibCommon_Sync.f_clientSyncAndVerdict + * @see LibCommon_VerdictControl.f_setVerdict + */ + function f_selfOrClientSyncAndVerdict( in charstring p_syncPoint, + in FncRetCode p_ret) + runs on SelfSyncComp { + if ( self == mtc ) { + // then assume we are running non-conurrent test case + f_selfSyncAndVerdict(p_syncPoint, p_ret); + } else { + f_clientSyncAndVerdict(p_syncPoint, p_ret); + } + } + + /** + * @desc Calls either self synchronization function if + * invoking component is the MTC, otherwise + * calls client synchronization. After that it + * sets a preamble specific verdict based on the + * specified return code. + * This function allows to implement TTCN-3 functions + * in a way that they can be used in both non-concurrent + * as well as concurrent test cases. + * @remark This function should _not_ be called if the MTC + * acts as a client (and not a server) in a concurrent + * test case. In this case f_clientSyncAndVerdictPreamble + * should be used instead. + * @param p_syncPoint Synchronization point name/id + * @param p_ret Current behavior execution status + * @see LibCommon_Sync.f_clientSyncAndVerdict + * @see LibCommon_VerdictControl.f_setVerdictPreamble + */ + function f_selfOrClientSyncAndVerdictPreamble( in charstring p_syncPoint, + in FncRetCode p_ret) + runs on SelfSyncComp { + if ( self == mtc ) { + // then assume we are running non-conurrent test case + f_selfSyncAndVerdictPreamble(p_syncPoint, p_ret); + } else { + f_clientSyncAndVerdictPreamble(p_syncPoint, p_ret); + } + } + + /** + * @desc Calls either self synchronization function if + * invoking component is the MTC, otherwise + * calls client synchronization. After that it + * sets a preamble specific verdict based on the + * specified return code. + * This function allows to implement TTCN-3 functions + * in a way that they can be used in both non-concurrent + * as well as concurrent test cases. + * @remark This function should _not_ be called if the MTC + * acts as a client (and not a server) in a concurrent + * test case. In this case f_clientSyncAndVerdictTestBody + * should be used instead. + * @param p_syncPoint Synchronization point name/id + * @param p_ret Current behavior execution status + * @see LibCommon_Sync.f_clientSyncAndVerdict + * @see LibCommon_VerdictControl.f_setVerdictPreamble + */ + function f_selfOrClientSyncAndVerdictTestBody( in charstring p_syncPoint, + in FncRetCode p_ret) + runs on SelfSyncComp { + if ( self == mtc ) { + // then assume we are running non-conurrent test case + f_selfSyncAndVerdictTestBody(p_syncPoint, p_ret); + } else { + f_clientSyncAndVerdictTestBody(p_syncPoint, p_ret); + } + } + + /** + * @desc Function kept for backward compatibility + * @see f_selfOrClientSyncAndVerdictPreamble + * + */ + function f_selfOrClientSyncAndVerdictPR( in charstring p_syncPoint, + in FncRetCode p_ret) + runs on SelfSyncComp { + f_selfOrClientSyncAndVerdictPreamble(p_syncPoint, p_ret); + } + + } // end group syncFunctions + + group syncCompStateHandling { + + /** + * + * @desc This function updates the state (stack) of a + * sync client or self sync component. This stack is + * key in the shutdown handling of test components. + * It adds the new state name to the top of the + * sync component stack of states. + * The state will only be added in case of a current + * execution status of e_success. + * @param p_newSyncCompState Name of state which was attempted to be reached. + * @param p_ret Current behavior execution status + * @remark If the state of component changes this function must be + * _at least_ called from your test suite prior to f_selfSync + * or f_clientSync which is the only definite place for the + * shutdown default invocation! + * @see LibCommon_Sync.a_dummyShutDown + * @see LibCommon_Sync.f_selfSync + * @see LibCommon_Sync.f_clientSync + */ + function f_addSyncCompState(in charstring p_newSyncCompState, + in FncRetCode p_ret) + runs on ClientSyncComp { + if ( p_ret == e_success ) { + if ( f_isItemOnStringStack(v_stateStack,p_newSyncCompState) ) { + log("**** f_addSyncCompState: WARNING: Attempt to add state which is already on sync state stack! No additition done.****"); + } else { + f_pushStringStack(v_stateStack,p_newSyncCompState); + } + } + } // end function f_addSyncCompState + + /** + * + * @desc This function returns the top state on the sync + * state stack of a sync client or self sync + * component and removes it from the stack + * This function cna be used, e.g., in a while + * statement within a postamble or shutdown + * implementation + * @param p_state State on top of the state stack. + * @return false if state stack is empty, true otherwise + * @see LibCommon_Sync.a_dummyShutDown + */ + function f_getTopSyncCompState( out charstring p_state ) + runs on ClientSyncComp + return boolean { + if ( not f_peekStringStackTop(v_stateStack,p_state) ) { + p_state := "IDLE"; + return false; + } + f_popStringStack(v_stateStack); + return true; + } // end function f_getTopSyncCompState + + /* + * @desc This function removes the last state on the state stack + * of a sync client or self sync component. + * This stack is key in the shutdown handling of test + * components. + * @see LibCommon_Sync.a_dummyShutDown + */ + function f_popSyncCompState() + runs on ClientSyncComp { + f_popStringStack(v_stateStack); + } // end function f_popSyncCompState + + /** + * + * @desc This function returns the top state on the sync state + * stack of a sync client or self sync component. It + * does not remove it from the stack + * This stack is key in the shutdown handling of test + * components. + * @param p_state State on top of the state stack. + * @return false if state stack is empty, true otherwise + * @see LibCommon_Sync.a_dummyShutDown + */ + function f_peekTopSyncCompState(out charstring p_state) + runs on ClientSyncComp + return boolean { + return f_peekStringStackTop(v_stateStack,p_state); + } // end function f_peekTopSyncCompState + + /** + * @desc This function checks if the sync state stack + * of a sync client or self sync component is empty. + * This stack is key in the shutdown handling of test + * components. + * @see LibCommon_Sync.a_dummyShutDown + */ + function f_isSyncCompStateStackEmpty() + runs on ClientSyncComp + return boolean { + return f_isStringStackEmpty(v_stateStack); + } // end function f_isSyncCompStateStackEmpty + + } // end group syncCompStateHandling + + group shutDownAltsteps { + + /** + * @desc This is an example of a shutdown altstep which can be + * used as a "template" for a interface specific shutdown + * altstep or possily as a first temporary solution in + * test case development.

+ * This altstep shall be activated as a default as the + * first statement in each test case function which drives + * an interface, i.e., in MTC behavior of single component + * and in each client behavior of multi component test + * cases.
+ * The required behavior from this altstep is to:

+ * 1) expect the STOP either via the test component + * syncPort

+ * 2) upon its arrival it should shut down the SUT + * gracefully based on the current component state

+ * The current component state should have been + * previously kept uptodate from a test suite via the + * f_addSyncCompState function. This default will then be + * (automatically) invoked either from within f_selfSync + * or f_clientSync.
+ * Note that shutdown defaults can be written as + * _interface specific_ - they do not need to be test case + * or test component specific! See another example of a + * shutdown altstep in the sync module. + * @see LibCommon_Sync.f_addSyncCompState + * @see LibCommon_Sync.f_selfSync + * @see LibCommon_Sync.f_clientSync + * @see LibCommon_SyncExamples.a_exampleShutDown + * @remark Your application specific shutdown altstep + * implementation(s) should _not_ be defined in this + * module but as part of your test suite or application specific + * modules. + */ + altstep a_dummyShutDown() + runs on SelfSyncComp { + [] syncPort.receive(m_syncServerStop){ + var charstring v_state := ""; + tc_sync.stop; + log("**** a_dummyShutDown: Test component received STOP signal from sync server - going to IDLE state ****"); + while ( f_getTopSyncCompState(v_state) ) { + if ( v_state == "x" ) { + // then do something + } else if ( v_state == "y" ) { + // then do something else + } + } // end while + f_disconnect4SelfOrClientSync(); + // unmap/disconnect more if needed + log("**** a_dummyShutDown: -> Test component stopping itself now! ****") ; + stop ; + } + } // end altstep a_dummyShutDown + + /** + * @desc Shutdown alstep in case the sync server is requesting shutdown. + * + * @remark User shall stop the component + */ + altstep a_shutdown() + runs on ClientSyncComp { + [] syncPort.receive(m_syncServerStop){ + tc_sync.stop ; + log("**** a_shutdown: Test component received STOP signal from MTC **** "); + } + } + + } // end group shutDownAltsteps + + } // end group basicUserRelevantDefinitions + + group advancedUserRelevantDefinitions { + + group serverRelated { + + /** + * @desc Implements synchronization of "n" clients from server + * side. If a problem occurs, then server sends STOP to + * all clients. Waits for PX_TSYNC_TIME_LIMIT to let + * clients finish executing their behavior until this + * synchronization point. See f_serverSyncClientsTimed for + * overwriting this later timing constraint! + * This function sets the server component verdict. + * @remark The use of this function requires prior connection of + * the server sync port! + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.f_serverSyncClientsTimed + * @param p_noOfClients number of clients to be synchronized + * @param p_syncId synchronization point name/id + */ + function f_serverSyncClients( in UInt p_noOfClients, in charstring p_syncId ) + runs on ServerSyncComp { + f_serverSyncClientsTimed(p_noOfClients,p_syncId, PX_TSYNC_TIME_LIMIT); + } + + /** + * @desc Implements synchronization of "n" clients from server + * side including intermediate synchronization. + * If a problem occurs, then server sends STOP to + * all clients. Waits for PX_TSYNC_TIME_LIMIT to let + * clients finish executing their behavior until this + * synchronization point. See f_serverSyncClientsTimed for + * overwriting this later timing constraint! + * This function sets the server component verdict. + * @remark The use of this function requires prior connection of + * the server sync port! + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.f_serverSyncClientsTimed + * @param p_noOfClients number of clients to be synchronized + * @param p_syncId synchronization point name/id + */ + function f_serverSyncClientsIntermediateSync( in UInt p_noOfClients, in charstring p_syncId, in UInt p_NoOfClientIntermediate, in template (present) charstring p_syncIdIntermediate ) + runs on ServerSyncComp { + f_serverSyncClientsTimedIntermediateSync(p_noOfClients,p_syncId, p_NoOfClientIntermediate, p_syncIdIntermediate, PX_TSYNC_TIME_LIMIT); + } + + /** + * @desc Handles synchronization of clients from server side. + * If problem occurs, then server sends STOP to all clients. + * This function sets the server verdict. + * @remark The use of this function requires prior connection of + * the server sync ports! + * @param p_NoOfClients number of clients to be synchronized + * @param p_syncId synchronization point name/id + * @param p_execTimeLimit time limit given to all clients to finish the execution + * of their behavior up to this synchronization point + * @see LibCommon_Sync.f_connect4SelfOrClientSync + */ + function f_serverSyncClientsTimed(in UInt p_NoOfClients, + in charstring p_syncId, + float p_execTimeLimit ) + runs on ServerSyncComp { + f_serverSyncClientsTimedIntermediateSync(p_NoOfClients, p_syncId, 0, ?, p_execTimeLimit ) + } // end function f_serverSyncClientsTimed + + /** @desc Handles synchronization of clients from server side including + * intermediate synchronization. + * If problem occurs, then server sends STOP to all clients. + * This function sets the server verdict. + * @remark The use of this function requires prior connection of + * the server sync ports! + * @param p_NoOfClients number of clients to be synchronized + * @param p_syncId synchronization point name/id + * @param p_execTimeLimit time limit given to all clients to finish the execution + * of their behavior up to this synchronization point + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @return execution status + */ + function f_serverSyncClientsTimedIntermediateSync( in UInt p_NoOfClients, + in charstring p_syncId, in UInt p_NoOfClientIntermediate, in template (present) charstring p_syncIdIntermediate, + float p_execTimeLimit ) + runs on ServerSyncComp { + + var integer v_noOfRecvdSyncMsgs := 0, v_noOfRecvdSyncMsgsIntermediate := 0; + var boolean v_stopClients := false; + var ClientSyncCompList v_clientRefs := {}, v_clientRefsIntermediate := {}; + var ClientSyncComp v_clientRef; + + if ( p_syncId == c_prDone ) { + log("**** f_serverSyncClientsTimed: Sync server now starting PREAMBLE synchronization ... ****") ; + } else if ( p_syncId == c_tbDone ) { + log("**** f_serverSyncClientsTimed: Sync server now starting TEST BODY synchronization ... ****") ; + } else if ( p_syncId == c_initDone ) { + log("**** f_serverSyncClientsTimed: Sync server now starting UPPER TESTER synchronization ... ****") ; + } else { + log("**** f_serverSyncClientsTimed: Sync server now starting handling of next synchronization point ... ****") ; + } + tc_sync.start(p_execTimeLimit) ; + alt{ + [v_noOfRecvdSyncMsgsIntermediate != p_NoOfClientIntermediate] syncPort.receive(m_syncClientReady(p_syncIdIntermediate)) -> sender v_clientRef { + if(not f_isPresentInArray(v_clientRef, v_clientRefsIntermediate)) { + v_clientRefsIntermediate[v_noOfRecvdSyncMsgsIntermediate] := v_clientRef; + v_noOfRecvdSyncMsgsIntermediate := v_noOfRecvdSyncMsgsIntermediate + 1; + if (v_noOfRecvdSyncMsgsIntermediate == p_NoOfClientIntermediate) { + f_serverSendToAllClients(v_clientRefsIntermediate, m_syncServerReady(p_syncIdIntermediate)); + } + } + repeat; + } + [] syncPort.receive(m_syncClientReady(p_syncId)) -> sender v_clientRef { + if(not f_isPresentInArray(v_clientRef, v_clientRefs)) { + v_clientRefs[v_noOfRecvdSyncMsgs] := v_clientRef; + v_noOfRecvdSyncMsgs := v_noOfRecvdSyncMsgs + 1; + } + if ( v_noOfRecvdSyncMsgs != p_NoOfClients ) { repeat; } + } + [] syncPort.receive(m_syncClientStop) -> sender v_clientRef { + log("**** f_serverSyncClientsTimed: Sync server received STOP signal from a client - server will wait for all clients to reach their next synchronization point and then stop them! ****") ; + v_stopClients := true; + if(not f_isPresentInArray(v_clientRef, v_clientRefs)) { + v_clientRefs[v_noOfRecvdSyncMsgs] := v_clientRef; + v_noOfRecvdSyncMsgs := v_noOfRecvdSyncMsgs + 1; + } + if ( v_noOfRecvdSyncMsgs != p_NoOfClients ) { repeat; } + + } + [] syncPort.receive(m_syncClientReady(?)) -> sender v_clientRef { + log("**** f_serverSyncClientsTimed: Sync server received client sync message with incorrect synchronization point id which is currently not handled - server will stop all clients! ****") ; + v_stopClients := true; + if(not f_isPresentInArray(v_clientRef, v_clientRefs)) { + v_clientRefs[v_noOfRecvdSyncMsgs] := v_clientRef; + } + } + [] syncPort.receive(SyncCmd :? ) { + log("**** f_serverSyncClientsTimed: Sync server received (invalid) sync message from other sync server - server will stop all clients! ****") ; + v_stopClients := true; } + [] any port.receive { + // leave it to be ok to receive anything else + // in case that the user has added any non-sync ports to + // his/her server component type definition! + repeat; + } + [] tc_sync.timeout{ + log("**** f_serverSyncClientsTimed: A client is not responding within specified time limit - sync server is sending stop to all clients! ****"); + v_stopClients := true; } + } //end alt + if (v_noOfRecvdSyncMsgsIntermediate != p_NoOfClientIntermediate) { + v_stopClients := true; + } + tc_sync.stop ; + if ( v_stopClients ) { + setverdict(inconc); + // then send out STOP sync msg + f_serverSendToAllClients(v_clientRefs, m_syncServerStop); + f_serverWaitForAllClientsToShutDown(); // function will never return! + } else { + setverdict(pass); + // then send out READY sync msg + f_serverSendToAllClients(v_clientRefs, m_syncServerReady(p_syncId)); + if ( p_syncId == c_prDone ) { + log("**** f_serverSyncClientsTimed: Sync server successfully passed PREAMBLE synchronization point. ****") ; + } else if ( p_syncId == c_tbDone ) { + log("**** f_serverSyncClientsTimed: Sync server successfully passed TEST BODY synchronization point. ****") ; + } else { + log("**** f_serverSyncClientsTimed: Sync server successfully passed synchronization point. ****") ; + } + } + } // end function f_serverSyncClientsTimedIntermediateSync + + /** + * @desc This function is intended only for use on the sync + * server component in concurrent TTCN-3 test cases. + * It waits for all components to finish execution within + * the PX_TSYNC_TIME_LIMIT. If a timeout occurs + * the server will stop all clients. + * This function sets the server component verdict. + */ + function f_serverWaitForAllClientsToStop() + runs on ServerSyncComp { + tc_sync.start; + alt { + [] all component.done { + tc_sync.stop; + log("**** f_serverWaitForAllClientsToStop: All sync clients have finished their execution. Sync server now terminating test case. ****") ; + } + [] tc_sync.timeout { + log("**** f_serverWaitForAllClientsToStop: Not all sync clients have finshed execution within the sync time limit. Sync server will stop test case! ****") ; + stop; + } + } // end alt + setverdict(pass); + } // end function f_serverWaitForAllClientsToStop + + } // end group serverRelated + + group clientRelated { + + /** + * @desc This function creates the connection needed to + * execute client synchronization functions + * @see LibCommon_Sync.f_clientSync + * @see LibCommon_Sync.f_clientSendStop + */ + function f_connect4ClientSync() + runs on ClientSyncComp { + connect(self:syncPort, mtc:syncPort); + }// end function f_connect4ClientSync + + /** + * @desc This function removes the connection needed + * to execute client synchronization functions + * @see LibCommon_Sync.f_clientSync + * @see LibCommon_Sync.f_clientSendStop + */ + function f_disconnect4ClientSync() + runs on ClientSyncComp { + disconnect(self:syncPort, mtc:syncPort); + }// end function f_disconnect4ClientSync + + /** + * @desc This function combines client verdict setting with its + * synchronization for use,e.g, after or within a + * test body implementation. + * Note that such premables can _not_ be reused in non- + * concurrent test cases. This can be achieved by using + * the f_selfOrClientSyncAndVerdict function instead. + * This function sets the client component verdict. + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + * @remark The use of this function requires prior connection + * of the client sync port! + * @see LibCommon_Sync.f_connect4ClientSync + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_VerdictControl.f_setVerdict + * @see LibCommon_Sync.f_selfOrClientSyncAndVerdict + */ + function f_clientSyncAndVerdict(in charstring p_syncId, + in FncRetCode p_ret) + runs on ClientSyncComp { + if(vc_testcaseStep == e_preamble) { + f_clientSyncAndVerdictPreamble(p_syncId, p_ret); + } else if(vc_testcaseStep == e_testBody) { + f_clientSyncAndVerdictTestBody(p_syncId, p_ret); + } + else { + f_clientSyncAndVerdictPostamble(p_syncId, p_ret); + } + } + + /** + * @desc This function combines client verdict setting with its + * synchronization for use after or within a preamble + * implementation. + * Note that such preambles can _not_ be reused in non- + * concurrent test cases. + * This function sets the client component verdict. + * @remark The use of this function requires prior connection + * of the client sync port! + * @see LibCommon_Sync.f_connect4ClientSync + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_VerdictControl.f_setVerdictPreamble + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + */ + function f_clientSyncAndVerdictPreamble(in charstring p_syncId , + FncRetCode p_ret) + runs on ClientSyncComp { + f_setVerdictPreamble(p_ret); + f_clientSync(p_syncId,p_ret); + vc_testcaseStep := e_testBody; + } + + /** + * @desc This function combines client verdict setting with its + * synchronization for use,e.g, after or within a + * test body implementation. + * Note that such premables can _not_ be reused in non- + * concurrent test cases. This can be achieved by using + * the f_selfOrClientSyncAndVerdict function instead. + * This function sets the client component verdict. + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + * @remark The use of this function requires prior connection + * of the client sync port! + * @see LibCommon_Sync.f_connect4ClientSync + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_VerdictControl.f_setVerdict + * @see LibCommon_Sync.f_selfOrClientSyncAndVerdict + */ + function f_clientSyncAndVerdictTestBody(in charstring p_syncId, + in FncRetCode p_ret) + runs on ClientSyncComp { + f_setVerdict(p_ret); + f_clientSync(p_syncId,p_ret); + vc_testcaseStep := e_postamble; + } + + /** + * @desc This function combines client verdict setting with its + * synchronization for use after or within a + * postamble implementation. + * Note that such prostambles can _not_ be reused in non- + * concurrent test cases. + * This function sets the client component verdict. + * @remark The use of this function requires prior connection + * of the client sync port! + * @see LibCommon_Sync.f_connect4ClientSync + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_VerdictControl.f_setVerdictPostamble + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + */ + function f_clientSyncAndVerdictPostamble(in charstring p_syncId , + in FncRetCode p_ret) + runs on ClientSyncComp { + f_setVerdictPostamble(p_ret); + f_clientSync(p_syncId,p_ret); + } + + /** + * @desc This function handles synchronization of a sync client + * with the server. In case of successful execution it sends + * a READY message to the server and waits the READY back. + * The time used for waiting is defined by PX_TSYNC_TIME_LIMIT. + * In case of a non successful execution status it + * sends a STOP message to the server. + * In both cases the receipt of a STOP message or no + * response from the server it will trigger the shutdown + * default (if activated). + * This function will set only the client verdict to INCONC + * (and stop its execution) if no STOP response is received + * from the server within the PX_TSYNC_TIME_LIMIT + * or if no shutdown default is activated. In all other + * cases the client verdict is NOT set. + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + * @remark The use of this function requires prior connection + * of the client sync port! + * @see LibCommon_Sync.f_connect4ClientSync + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.a_dummyShutDown + * @see LibCommon_Sync.f_clientSendStop + * @return Updated execution status + */ + function f_clientSync( in charstring p_syncId , + in FncRetCode p_ret ) + runs on ClientSyncComp + return FncRetCode{ + + if (p_ret == e_success){ + syncPort.send(m_syncClientReady(p_syncId)); + tc_sync.start; + alt{ + [] syncPort.receive(m_syncServerReady(p_syncId)){ + tc_sync.stop ; } + [] tc_sync.timeout{ + log("**** f_clientSync: Sync client did not receive message from sync server within the specified time limit - sync client will ask sync server to stop test case! ****") ; + f_clientSendStop(); } // function will not return! + } //end alt + } //end if + else { + log("**** f_clientSync: Execution status indicates that execution of test component behavior was not successful - sync client will ask sync server to stop test case! ****") ; + f_clientSendStop(); // function will not return! + } + if ( p_syncId == c_prDone ) { + log("**** f_clientSync: Sync client successfully passed PREAMBLE synchronization point. ****") ; + } else if ( p_syncId == c_tbDone ) { + log("**** f_clientSync: Sync client successfully passed TEST BODY synchronization point. ****") ; + } else { + log("**** f_clientSync: Sync client successfully passed synchronization point. ****") ; + } + return e_success ; + + } // end function f_clientSync + + /** + * @desc This function can be used to request the shutdown a + * multi component test case _prior_ to reaching a + * synchronization point. It sends a STOP message to + * the sync server and awaits then the STOP from the server + * which will trigger the shutdown default (if activated). + * This function will set the server verdict to INCONC (and + * stop the test case) if no shutdown default is activated. + * This function will set only the client verdict to INCONC + * (and stop its execution) if no STOP response is received + * from the server within the PX_TSYNC_TIME_LIMIT + * or if no shutdown default is activated. In all other + * cases the client verdict is NOT set. + * @remark The use of this function requires prior connection + * of the client sync port! + * @see LibCommon_Sync.f_connect4ClientSync + * @see LibCommon_Sync.f_connect4SelfOrClientSync + * @see LibCommon_Sync.PX_TSYNC_TIME_LIMIT + * @see LibCommon_Sync.a_dummyShutDown + */ + function f_clientSendStop() + runs on ClientSyncComp { + log("**** f_clientSendStop: Sync client requesting from server to stop test case (including itself). ****") ; + syncPort.send(m_syncClientStop) ; + tc_sync.start; + alt{ + [] tc_sync.timeout{ + log("**** f_clientSendStop: Stopping sync client without shutdown - either no shutdown default active or no stop received from server. ****") ; + setverdict(inconc); + stop ; + } + }//end alt + tc_sync.stop; + stop; // stop here if shutdown default does not stop + } + + } // end group clientRelated + + } // end group advancedUserRelevantDefinitions + + group otherSyncModuleDefinitions { + + group syncModuleparams { + /** + * + * @desc Default time limit for a sync client to reach a + * synchronization point + */ + modulepar float PX_TSYNC_TIME_LIMIT := 120.0; + + /* + * @desc Default time limit for a sync client to finish + * its execution of the shutdown default + */ + modulepar float PX_TSHUT_DOWN_TIME_LIMIT := 120.0; + } + + group otherSyncTypes { + + type record of charstring SyncPointList; + + type record of ClientSyncComp ClientSyncCompList; + + } // end group otherSyncTypes + + group otherSelfSyncRelatedDefinitions { + + /** + * @desc This function creates the connection needed to + * execute self sync functions + * @see LibCommon_Sync.f_selfSync + * @see LibCommon_Sync.f_selfSyncStop + */ + function f_connect4SelfSync() + runs on SelfSyncComp { + connect(self:syncSendPort, self:syncPort); + }// end function f_connect4SelfSync + + /** + * @desc This function removes the connection needed + * to execute self sync functions + * @see LibCommon_Sync.f_selfSync + * @see LibCommon_Sync.f_selfSyncStop + */ + function f_disconnect4SelfSync() + runs on SelfSyncComp { + disconnect(self:syncSendPort, self:syncPort); + }// end function f_disconnect4SelfSync + + /** + * @desc This function combines MTC verdict setting with self + * synchronization for use in the preamble / test body / postamble + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + * @see LibCommon_VerdictControl.f_setVerdict + * @see LibCommon_Sync.f_selfSync + * @see LibCommon_Sync.a_dummyShutDown + */ + function f_selfSyncAndVerdict( in charstring p_syncId, + in FncRetCode p_ret ) + runs on SelfSyncComp { + if(vc_testcaseStep == e_preamble) { + f_selfSyncAndVerdictPreamble(p_syncId, p_ret); + } else if(vc_testcaseStep == e_testBody) { + f_selfSyncAndVerdictTestBody(p_syncId, p_ret); + } + else { + f_selfSyncAndVerdictPostamble(p_syncId, p_ret); + } + } + + /** + * @desc This function combines MTC verdict setting with self + * synchronization for use after the preamble. + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + * @see LibCommon_VerdictControl.f_setVerdictPreamble + * @see LibCommon_Sync.f_selfSync + */ + function f_selfSyncAndVerdictPreamble( in charstring p_syncId, + in FncRetCode p_ret ) + runs on SelfSyncComp { + f_setVerdictPreOrPostamble(p_ret); + f_selfSync(p_syncId,p_ret); + vc_testcaseStep := e_testBody; + } + + /** + * @desc This function combines MTC verdict setting with self + * synchronization for use after the test body. + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + * @see LibCommon_VerdictControl.f_setVerdict + * @see LibCommon_Sync.f_selfSync + */ + function f_selfSyncAndVerdictTestBody( in charstring p_syncId, + in FncRetCode p_ret ) + runs on SelfSyncComp { + f_setVerdict(p_ret); + f_selfSync(p_syncId,p_ret); + vc_testcaseStep := e_postamble; + } + + /** + * @desc This function combines MTC verdict setting with self + * synchronization for use after the postamble. + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + * @see LibCommon_VerdictControl.f_setVerdictPostamble + * @see LibCommon_Sync.f_selfSync + */ + function f_selfSyncAndVerdictPostamble( in charstring p_syncId , + in FncRetCode p_ret ) + runs on SelfSyncComp { + f_setVerdictPreOrPostamble(p_ret); + f_selfSync(p_syncId,p_ret); + } + + /** + * @desc This function synchronizes a MTC with itself. In case + * of a non successful execution status it sends a STOP + * message to itself and invokes that way the + * shutdown default (if activated). + * This function will set the server verdict to INCONC (and + * stop the test case) if no shutdown default is activated. + * Otherwise no verdict is set. + * @remark Sync ports should be connected prior to the invocation + * of this function! + * @param p_syncId Synchronization point name/id + * @param p_ret Current behavior execution status + * @return Updated execution status + * @see LibCommon_Sync.f_connect4SelfSync + * @see LibCommon_Sync.a_dummyShutDown + */ + function f_selfSync( in charstring p_syncId , + in FncRetCode p_ret ) + runs on SelfSyncComp + return FncRetCode{ + if (p_ret != e_success){ + f_selfSyncStop() ; // function will not return! + } + if ( p_syncId == c_prDone ) { + log("**** f_selfSync: Successfully passed PREAMBLE synchronization point. ****") ; + } else if ( p_syncId == c_tbDone ) { + log("**** f_selfSync: Successfully passed TEST BODY synchronization point. ****") ; + } else { + log("**** f_selfSync: Successfully passed synchronization point. ****") ; + } + return e_success ; + }// end function f_selfSync + + /** + * @desc This function can be used to shut down a test case _prior_ + * to reaching a synchronization point. it sends a STOP + * message to itself and invokes that way the + * shutdown default (if activated). + * This function will set the server verdict to INCONC (and + * stop the test case) if no shutdown default is activated. + * Otherwise no verdict is set. + * @remark Sync ports should be connected prior to the invocation + * of this function! + * @see LibCommon_Sync.f_connect4SelfSync + */ + function f_selfSyncStop() + runs on SelfSyncComp { + + log("**** f_selfSyncStop: MTC requests to stop test case (itself). ****") ; + syncSendPort.send(m_syncServerStop) ; // this MUST be _server_ for the default to catch! + tc_sync.start(PX_TSYNC_TIME_LIMIT); + alt{ + [] tc_sync.timeout{ + log("**** f_selfSyncStop: Stopping MTC without shutdown - either no shutdown default active or missing syncPort connection ****") ; + setverdict(inconc); + stop ; + } + }//end alt + tc_sync.stop; + stop; // if shutdown default is not activated or if it does not stop + } // end function f_selfSyncStop + + } // end group otherSelfSyncRelatedDefinitions + + /** + * + * @desc The sychronization protocol is conceptually based on + * named synchronization. Each synchronization point + * has it own specific synchronization message. This + * makes each synchronization unique, and allows, e.g., to + * ensure that a server synchronizes only clients which have + * reached the same synchronization point. + */ + group syncProtocolDefinition { + + type union SyncCmd { + ClientReady clientReady, + ServerReady serverReady, + ClientStop clientStop, + ServerStop serverStop + } + + type record ClientReady { + charstring syncPointId + } + + type record ServerReady { + charstring syncPointId + } + + type record ClientStop {} + + type record ServerStop {} + + } // end group syncProtocolDefinition + + group syncMessages { + template SyncCmd m_syncClientReady( template (present) charstring p_syncId ) := { + clientReady := { p_syncId } + } + + template SyncCmd m_syncServerReady( template (present) charstring p_syncId ) := { + serverReady := { p_syncId } + } + + template SyncCmd m_syncClientStop := { + clientStop := {} + } + + template SyncCmd m_syncServerStop := { + serverStop := {} + } + + } // end group syncMessages + + group otherSyncFunctions { + + /** + * @desc Makes server send a sync message to all known clients + * @param p_clientRefs List of client references to which the message is to be send + * @param p_syncCmd The actual synchronization message to be sent out + */ + function f_serverSendToAllClients( in ClientSyncCompList p_clientRefs, + in template (value) SyncCmd p_syncCmd) + runs on ServerSyncComp { + var integer i:=0; + for (i:=0; i< sizeof(p_clientRefs); i:=i+1 ){ + syncPort.send(p_syncCmd) to valueof(p_clientRefs[i]); + } + } // end function f_serverSendToAllClients + + /** + * @desc This function is intended only for use on server in concurrent + * TTCN-3 test cases. It waits for all components to shut down + * within the PX_TSHUT_DOWN_TIME_LIMIT. If a timeout occurs + * it aborts the test case (no matter how far clients got with their + * shutdown). + * This function sets the server verdict. + */ + function f_serverWaitForAllClientsToShutDown() + runs on ServerSyncComp { + + tc_shutDown.start(PX_TSHUT_DOWN_TIME_LIMIT); + alt { + [] syncPort.receive { + // clients may still try to send some sync message + } + [] all component.done { + tc_shutDown.stop; + log("**** f_serverWaitForAllClientsToShutDown: All components have properly shut down. Sync server will now terminate the test case. ****") ; + } + [] tc_shutDown.timeout { + log("**** f_serverWaitForAllClientsToShutDown: Not all clients have properly shutdown within the shut down time limit. Sync server will now terminate test case! ****") ; + } + } // end alt + // cover case that shut down default is NOT activated + setverdict(inconc); + //mtc.stop; + syncPort.send(m_syncServerStop) to self; // this MUST be _server_ for the default to catch! + tc_sync.start(PX_TSYNC_TIME_LIMIT); + alt{ + [] tc_sync.timeout{ + log("**** f_selfSyncStop: Stopping MTC without shutdown - either no shutdown default active or missing syncPort connection ****") ; + setverdict(inconc); + stop ; + } + }//end alt + tc_sync.stop; + stop; // if shutdown default is not activated or if it does not stop + } // end function f_serverWaitForAllClientsToShutDown + + function f_isPresentInArray(in ClientSyncComp p_clientRef, in ClientSyncCompList p_clientRefs) + return boolean { + var integer i; + for(i:=0; i < sizeof(p_clientRefs); i:=i+1) { + if(p_clientRefs[i] == p_clientRef) { + return true; + } + } + return false; + } + } // end group otherSyncFunctions + + } // end group otherSyncDefinitions + +} // end module LibCommon_Sync diff --git a/ttcn/patch_lib_http/ttcn/LibHttp_BinaryMessageBodyTypes.ttcn b/ttcn/patch_lib_http/ttcn/LibHttp_BinaryMessageBodyTypes.ttcn index ff2492a4cde1e713e130620f7abf1f7c633fb460..3c4b3c10ceea729b50d5ec0e01c1eee42f43ecaf 100644 --- a/ttcn/patch_lib_http/ttcn/LibHttp_BinaryMessageBodyTypes.ttcn +++ b/ttcn/patch_lib_http/ttcn/LibHttp_BinaryMessageBodyTypes.ttcn @@ -18,10 +18,6 @@ module LibHttp_BinaryMessageBodyTypes { // LibIts import from Ieee1609Dot2BaseTypes language "ASN.1:1997" all; import from Ieee1609Dot2 language "ASN.1:1997" all; - import from EtsiTs102941BaseTypes language "ASN.1:1997" all; - import from EtsiTs102941TypesEnrolment language "ASN.1:1997" all; - import from EtsiTs102941MessagesCa language "ASN.1:1997" all; - import from EtsiTs103097Module language "ASN.1:1997" all; type union BinaryBody { // TODO Add here your custom variants @@ -29,7 +25,8 @@ module LibHttp_BinaryMessageBodyTypes { Certificate ieee1609dot2_certificate, octetstring raw } with { - variant "" + variant ""; + encode "RAW" } } // End of LibHttp_BinaryMessageBodyTypes diff --git a/ttcn/patch_lib_http/ttcn/LibHttp_BinaryTemplates.ttcn b/ttcn/patch_lib_http/ttcn/LibHttp_BinaryTemplates.ttcn index 5319d23913ec495977cc47981117ffe93d98ea07..c8de0ac8426cfe508de94173e4f3f0bd70977203 100644 --- a/ttcn/patch_lib_http/ttcn/LibHttp_BinaryTemplates.ttcn +++ b/ttcn/patch_lib_http/ttcn/LibHttp_BinaryTemplates.ttcn @@ -17,9 +17,6 @@ module LibHttp_BinaryTemplates { // LibIts import from Ieee1609Dot2BaseTypes language "ASN.1:1997" all; import from Ieee1609Dot2 language "ASN.1:1997" all; - import from EtsiTs102941BaseTypes language "ASN.1:1997" all; - import from EtsiTs102941TypesEnrolment language "ASN.1:1997" all; - import from EtsiTs102941MessagesCa language "ASN.1:1997" all; import from EtsiTs103097Module language "ASN.1:1997" all; template (value) BinaryBody m_binary_body_raw( @@ -46,7 +43,7 @@ module LibHttp_BinaryTemplates { ) := { ieee1609dot2_data := p_ieee1609dot2_data } // End of template mw_binary_body_ieee1609dot2_data - + template (value) BinaryBody m_binary_body_ieee1609dot2_certificate( in template (value) CertificateBase p_ieee1609dot2_certificate ) := { diff --git a/virtualization/docker-dev/Dockerfile b/virtualization/docker-dev/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..28dc2b3cba5e26a4553c9867cfdb86a2345f2323 --- /dev/null +++ b/virtualization/docker-dev/Dockerfile @@ -0,0 +1,25 @@ +FROM stfubuntu:20.04 + +LABEL ETSI ITS +LABEL description="TS.ITS Docker Image" + +ENV TERM=linux \ + HOME=/home/etsi \ + HOSTNAME=docker-titan-TS.ITS-r2 + +COPY home /home/etsi + +RUN cd /home/etsi \ + && chown -R etsi:etsi . \ + && ls ./etc/init.d/*.sh | while read S; do chmod 0750 "$S" || exit 1; done + +USER etsi + +RUN cd ${HOME} \ + && export PATH=$HOME/bin:$PATH \ + && ls ${HOME}/etc/init.d/*.sh | while read S; do /bin/bash -c "$S" || exit 1; done \ + && rm -fr ${HOME}/etc + +CMD ["/bin/bash"] + +# That's all Floks diff --git a/virtualization/docker/Dockerfile.stfubuntu b/virtualization/docker-dev/Dockerfile.stfubuntu similarity index 100% rename from virtualization/docker/Dockerfile.stfubuntu rename to virtualization/docker-dev/Dockerfile.stfubuntu diff --git a/virtualization/docker-dev/README.md b/virtualization/docker-dev/README.md new file mode 100644 index 0000000000000000000000000000000000000000..388edf6a7b87676fb496d8dd163340955754c374 --- /dev/null +++ b/virtualization/docker-dev/README.md @@ -0,0 +1,66 @@ +# HOWTO build docker images + +## General imformation + +Pre-requisites on your host machine: + +- Install [Docker](https://docs.docker.com/install/) + +#### From Windows host: + +- Install [Virtualbox](https://www.virtualbox.org/manual/ch01.html) +- Install any X Server. For example [VcXsrv](https://sourceforge.net/projects/vcxsrv/) + +#### From Mac host: + +- Install [Virtualbox](https://www.virtualbox.org/manual/ch01.html) +- Install [XQuartz](https://www.xquartz.org) + +#### From Linux host: + +- No other requirements + +## Build docker image + +For Windows host, rename ```build.cmd.a``` and ```run.cmd.a``` to ```build.cmd``` and ```run.cmd``` respectivelly. + +Special scrips ```build.sh``` (or ```build.cmd```) can be executed to automatically build all necessary images. + +There are several build stages: + +1. Build STF Ubuntu 18.04 image +2. Install Titan from Github +3. Install Eclipse and Titan Eclipse plugin into ~/frameworks/titan +4. Install asn1c into ~/frameworks/asn1c +5. Checkout TS.ITS sources from ETSI svn repository using default credentials +6. Build ASN.1 recoder library +7. Build certificate generation tool + +## Import and build ITS project + +### Run Docker image + +#### From Windows host: + +1. Authorize Docker container to interact with the XServer: +Go to the X Server installation directory and add the Docker container ip address to the file ```X0.hosts```: +``` +localhost +inet6:localhost +192.168.99.100 +``` + +Execute ```run.cmd``` or launch a command line window and run the command + +```docker run -it --net=host -e DISPLAY=192.168.99.1:0 etsiforge/etsi-its-ts-r2``` + +NOTE: Modify the IP address in the command for the address of 'VirtualBox Hot-Only Network'. + +#### From Linux host: + +Execute ```run.sh``` or launch a command line window and run the command + +```sh +docker run -it --net=host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix etsiforge/etsi-its-ts-r2 +``` + diff --git a/virtualization/docker/build.sh b/virtualization/docker-dev/build.sh similarity index 64% rename from virtualization/docker/build.sh rename to virtualization/docker-dev/build.sh index 122590f1baf66e468408dda1254b6ecde594c03c..178690fba33c871b96fb4bc7fe9000993b7abec7 100755 --- a/virtualization/docker/build.sh +++ b/virtualization/docker-dev/build.sh @@ -13,13 +13,13 @@ if [ "$1" == "--force-stfubuntu" ]; then fi # Check and build stfubuntu image if [ -z `docker images -q stfubuntu` ]; then - docker build --no-cache --tag stfubuntu:20.04 -f Dockerfile.stfubuntu --force-rm . || exit 1 + docker build --no-cache --tag stfubuntu:22.04 -f Dockerfile.stfubuntu --force-rm . || exit 1 fi -docker build --no-cache --tag etsiforge/etsi-its-ts --force-rm . || ( echo "Docker build failed: $?"; exit 1 ) +docker build --no-cache --tag etsiforge-r2 --force-rm . || ( echo "Docker build failed: $?"; exit 1 ) docker images -docker inspect etsiforge/etsi-its-ts:latest || ( echo "Docker inspect failed: $?"; exit 1 ) +docker inspect etsiforge/etsi-its-ts-r2:latest || ( echo "Docker inspect failed: $?"; exit 1 ) # That's all Floks exit 0 diff --git a/virtualization/docker/home/etc/init.d/10-titan.sh b/virtualization/docker-dev/home/etc/init.d/10-titan.sh similarity index 100% rename from virtualization/docker/home/etc/init.d/10-titan.sh rename to virtualization/docker-dev/home/etc/init.d/10-titan.sh diff --git a/virtualization/docker/home/etc/init.d/30-asn1c.sh b/virtualization/docker-dev/home/etc/init.d/30-asn1c.sh similarity index 78% rename from virtualization/docker/home/etc/init.d/30-asn1c.sh rename to virtualization/docker-dev/home/etc/init.d/30-asn1c.sh index fae38d4ada3ce1de5146a866a25550cb31de0948..43527e74766e2ad1b8924aa8b414cc07f73c9434 100755 --- a/virtualization/docker/home/etc/init.d/30-asn1c.sh +++ b/virtualization/docker-dev/home/etc/init.d/30-asn1c.sh @@ -7,6 +7,7 @@ echo -e "*****************************\n* Install asn1c\n*********************** cd ${HOME}/frameworks || exit 1 git clone https://github.com/fillabs/asn1c.git ./asn1c || exit 1 cd ./asn1c +sed --in-place 's/AC_CHECK_INCLUDES_DEFAULT/#AC_CHECK_INCLUDES_DEFAULT/g' ./configure.ac autoreconf -iv && ./configure --prefix=${HOME} && make install || exit 1 cd ${HOME} diff --git a/virtualization/docker-dev/home/etc/init.d/40-ttf024.sh b/virtualization/docker-dev/home/etc/init.d/40-ttf024.sh new file mode 100755 index 0000000000000000000000000000000000000000..49309099ff2e5aaa519c4d5b252eb4986e5fc3e7 --- /dev/null +++ b/virtualization/docker-dev/home/etc/init.d/40-ttf024.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +#set -e +set -vx + +echo -e "*****************************\n* Checkout TS.ITS sources\n*****************************\n" +cd ${HOME}/dev || exit 1 + +git clone --recurse-submodules --single-branch --branch ttf_t024 https://forge.etsi.org/rep/ITS/TS.ITS.git TS.ITS || exit 1 +cd ./TS.ITS || exit 1 +for i in `find ./ttcn -type d -name "Ats*"` +do + cd $i + git checkout devel2 + cd - +done +for i in `find ./ttcn/Ats* -type d -name "asn1"` +do + cd $i + git checkout testing2 +# if [ -f ETSI-ITS-CDD.asn ] +# then +# ln -sf ETSI-ITS-CDD.asn ETSI_ITS_CDD.asn || exit 1 +# elif [ -f IVIM-PDU-Descriptions.asn ] +# then +# ln -sf IVIM-PDU-Descriptions.asn IVIM_PDU_Descriptions.asn || exit 1 +# ln -sf MAPEM-PDU-Descriptions.asn MAPEM_PDU_Descriptions.asn || exit 1 +# ln -sf RTCMEM-PDU-Descriptions.asn RTCMEM_PDU_Descriptions.asn || exit 1 +# ln -sf SPATEM-PDU-Descriptions.asn SPATEM_PDU_Descriptions.asn || exit 1 +# ln -sf SREM-PDU-Descriptions.asn SREM_PDU_Descriptions.asn || exit 1 +# ln -sf SSEM-PDU-Descriptions.asn SSEM_PDU_Descriptions.asn || exit 1 +# ln -sf iso-patched/'ISO14906(2018)EfcDsrcApplicationv6-patched.asn' iso-patched/EfcDsrcApplication.asn || exit 1 +# ln -sf iso-patched/'ISO14906(2018)EfcDsrcGenericv7-patched.asn' iso-patched/EfcDsrcGeneric.asn || exit 1 +# ln -sf iso-patched/ISO24534-3_ElectronicRegistrationIdentificationVehicleDataModule-patched.asn iso-patched/ElectronicRegistrationIdentificationVehicleDataModule.asn || exit 1 +# ln -sf iso-patched/ISO14823-missing.asn iso-patched/GDD.asn || exit 1 +# fi + SUB_DIRS=`find . -type d` + if [ "SUB_DIRS" != "" ] + then + for j in $SUB_DIRS + do + cd $j + git checkout testing2 + cd - + done + fi + cd - +done +cd ${HOME}/dev/TS.ITS/titan-test-system-framework +git checkout devel +cd ./ttcn/LibHttp +ln -sf module_its.mk module.mk +cd ${HOME}/dev/TS.ITS/ttcn/LibIts +git checkout devel2 + +cd ${HOME}/dev/TS.ITS/ +cp ./ttcn/patch_lib_common/module.mk ./ttcn/LibCommon/ +cp ./ttcn/patch_lib_common/ttcn/* ./ttcn/LibCommon/ttcn + +echo -e "*****************************\n* Setup environment\n*****************************\n" +cd ${HOME}/dev/TS.ITS/scripts +chmod 775 *.bash devenv.bash.* +cd ${HOME} +ln -sf ${HOME}/dev/TS.ITS/scripts/devenv.bash.ubuntu ${HOME}/devenv.bash +ls -ltr ${HOME} + +cd ${HOME} + +exit 0 diff --git a/virtualization/docker/home/etc/init.d/45-certgen.sh b/virtualization/docker-dev/home/etc/init.d/45-certgen.sh similarity index 69% rename from virtualization/docker/home/etc/init.d/45-certgen.sh rename to virtualization/docker-dev/home/etc/init.d/45-certgen.sh index 9c8b61f1c684a78e65fa804525f48eb686cfad1c..273c18c80bc296ebb667d2f0e5f29c3e69863386 100755 --- a/virtualization/docker/home/etc/init.d/45-certgen.sh +++ b/virtualization/docker-dev/home/etc/init.d/45-certgen.sh @@ -6,10 +6,10 @@ set -vx echo -e "*****************************\n* Build ETSI ITS certificate generation tools \n*****************************\n" cd ${HOME}/dev || exit 1 -git clone --recurse-submodules https://forge.etsi.org/rep/ITS/itscertgen.git ./itscertgen +git clone --recurse-submodules --branch release2 https://forge.etsi.org/rep/ITS/itscertgen.git ./itscertgen cd ./itscertgen -cd cshared && make && cd - -cd certgen/ && make && cd - +sed --in-place 's/\-fillabs2//g' ./certgen/asncodec/Makefile +make && cd - || exit 1 echo -e "*****************************\n* Generate ETSI ITS certificates \n*****************************\n" cd ${HOME}/dev/TS.ITS/data/certificates diff --git a/virtualization/docker/home/etc/init.d/50-ats.sh b/virtualization/docker-dev/home/etc/init.d/50-ats.sh similarity index 91% rename from virtualization/docker/home/etc/init.d/50-ats.sh rename to virtualization/docker-dev/home/etc/init.d/50-ats.sh index 4a014f19b2d50e1ab60b5158720f393d627ee7bb..4bc661411c940adfaabac3327597c8d60ee3645d 100755 --- a/virtualization/docker/home/etc/init.d/50-ats.sh +++ b/virtualization/docker-dev/home/etc/init.d/50-ats.sh @@ -11,7 +11,7 @@ cd ${HOME}/dev/TS.ITS/scripts || exit 1 echo -e "*****************************\n* Build test suites\n*****************************\n" cd ${HOME}/dev/TS.ITS -ATS_LIST="AtsCAM AtsDENM AtsGeoNetworking AtsPki AtsSecurity AtsIS" +ATS_LIST="AtsCAM AtsDENM AtsGeoNetworking AtsIS AtsPki AtsSecurity AtsMBR" for i in ${ATS_LIST} do export ATS=$i diff --git a/virtualization/docker/home/etc/init.d/60-doxygen.sh b/virtualization/docker-dev/home/etc/init.d/60-doxygen.sh similarity index 100% rename from virtualization/docker/home/etc/init.d/60-doxygen.sh rename to virtualization/docker-dev/home/etc/init.d/60-doxygen.sh diff --git a/virtualization/docker/home/etc/titan_repos.txt b/virtualization/docker-dev/home/etc/titan_repos.txt similarity index 100% rename from virtualization/docker/home/etc/titan_repos.txt rename to virtualization/docker-dev/home/etc/titan_repos.txt diff --git a/virtualization/docker/run.sh b/virtualization/docker-dev/run.sh similarity index 82% rename from virtualization/docker/run.sh rename to virtualization/docker-dev/run.sh index b4cb2df13addeedec43f8027aee27e596aba8901..c223af1c408ccd3c842e632485751331ce9efc29 100755 --- a/virtualization/docker/run.sh +++ b/virtualization/docker-dev/run.sh @@ -5,7 +5,7 @@ #set -e set -vx -docker run --interactive --tty --rm --publish 2222:22 --env DISPLAY=$DISPLAY --volume /tmp/.X11-unix:/tmp/.X11-unix --cap-add=NET_RAW --cap-add=NET_ADMIN etsiforge/etsi-its-ts:latest +docker run --interactive --tty --rm --publish 2222:22 --env DISPLAY=$DISPLAY --volume /tmp/.X11-unix:/tmp/.X11-unix --cap-add=NET_RAW --cap-add=NET_ADMIN etsiforge/etsi-its-ts-r2:latest # That's all Floks exit 0 diff --git a/virtualization/docker/Dockerfile b/virtualization/docker/Dockerfile index 69a82822dbb228a7543f3c9f61a6db9c38aed876..04cc0bca1f9c4f9ae88b86174589bf25a4a328fe 100644 --- a/virtualization/docker/Dockerfile +++ b/virtualization/docker/Dockerfile @@ -1,25 +1,56 @@ -FROM stfubuntu:20.04 - -LABEL ETSI ITS -LABEL description="TS.ITS Docker Image" - -ENV TERM=linux \ - HOME=/home/etsi \ - HOSTNAME=docker-titan-TS.ITS - -COPY home /home/etsi - -RUN cd /home/etsi \ - && chown -R etsi:etsi . \ - && ls ./etc/init.d/*.sh | while read S; do chmod 0750 "$S" || exit 1; done - +FROM alpine:latest + +# Install dependencies +RUN apk update && \ + apk add --no-cache autoconf automake sudo make git g++ diffutils expect openssl-dev libxml2-dev libxml2-utils libxslt-dev libtool ncurses-dev jsoncpp-dev readline-dev flex bison perl libexecinfo-dev bash libedit libedit-dev lksctp-tools lksctp-tools-dev libpcap-dev + +# Create user and sudouser +RUN \ + addgroup -g 1000 etsi && \ + adduser -S -D -u 1000 -G etsi -h /home/etsi -s /bin/bash etsi && \ + echo "etsi:etsi" | chpasswd && \ + echo "etsi ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers || exit 1 USER etsi -RUN cd ${HOME} \ - && export PATH=$HOME/bin:$PATH \ - && ls ${HOME}/etc/init.d/*.sh | while read S; do /bin/bash -c "$S" || exit 1; done \ - && rm -fr ${HOME}/etc - -CMD ["/bin/bash"] - -# That's all Floks +# Setup Hosts file at the boot time +RUN \ + echo 'sudo sh -c "cp /etc/hosts /etc/append && (echo \"127.0.1.1 $HOSTNAME\"; cat /etc/append) > /etc/hosts"' >> /home/etsi/.bashrc \ + echo 'sh' >> /home/etsi/.bashrc || exit 1 + +# Install asn1.c and Titan +WORKDIR /home/etsi +RUN \ + mkdir -p frameworks dev tmp \ + && cd frameworks \ + && git clone --branch=vlm_test https://github.com/fillabs/asn1c.git ./asn1c \ + && cd ./asn1c \ + && autoreconf -iv && ./configure --prefix=${HOME} && make install \ + && cd - \ + && git clone https://github.com/eclipse/titan.core.git || exit 1 +WORKDIR /home/etsi/frameworks/titan.core/ + +# Setup ENV variables +ENV TTCN3_DIR=/home/etsi/frameworks/titan.core/Install +ENV PATH=$TTCN3_DIR/bin:$PATH \ + LD_LIBRARY_PATH=$TTCN3_DIR/lib:$LD_LIBRARY_PATH + +# Set flags +RUN \ + echo "ALPINE_LINUX=yes" > Makefile.personal && \ + echo "TTCN3_DIR=$TTCN3_DIR" >> Makefile.personal && \ + echo "JNI=no" >> Makefile.personal && \ + echo "GUI=no" >> Makefile.personal && \ + echo "DEBUG=no" >> Makefile.personal || exit 1 + +# Build Titan +RUN \ + sed --in-place 's/LINUX_LIBS := -lxml2/LINUX_LIBS := -lxml2 -lpthread/g' ./core/Makefile && \ + make install && make clean || exit 1 + +WORKDIR /home/etsi/dev + +EXPOSE 80/tcp 443/tcp 12340-12349/udp + +ENTRYPOINT ["/home/etsi/dev/cise/virtualization/docker/docker-entrypoint.sh"] + +CMD ["help"] \ No newline at end of file diff --git a/virtualization/docker/README.md b/virtualization/docker/README.md index 7e6b794621404295b3c857b36ae6a00315e3f2b5..16cd5e7a9b079b113f622cd44a2500f54003ea38 100644 --- a/virtualization/docker/README.md +++ b/virtualization/docker/README.md @@ -22,45 +22,65 @@ Pre-requisites on your host machine: ## Build docker image -For Windows host, rename ```build.cmd.a``` and ```run.cmd.a``` to ```build.cmd``` and ```run.cmd``` respectivelly. +In this configuration, TITAN compiler is located on a Docker image and the sources and the outputs are located on the host. -Special scrips ```build.sh``` (or ```build.cmd```) can be executed to automatically build all necessary images. +Pre-requisites on your host machine: +- Install Docker -There are several build stages: +Procedure on the host machine: +- Open a Terminal +- Clone the ETSI ITS Test System -1. Build STF Ubuntu 18.04 image -2. Install Titan from Github -3. Install Eclipse and Titan Eclipse plugin into ~/frameworks/titan -4. Install asn1c into ~/frameworks/asn1c -5. Checkout TS.ITS sources from ETSI svn repository using default credentials -6. Build ASN.1 recoder library -7. Build certificate generation tool +```sh +$ git clone --recurse-submodules --single-branch https://forge.etsi.org/gitlab/ITS/TS.ITS.git +cd ${HOME}/dev/TS.ITS/titan-test-system-framework +git checkout devel +cd ./ttcn/LibHttp +ln -sf module_its.mk module.mk +cd ${HOME}/dev/TS.ITS/ttcn/LibIts +git checkout devel +``` -## Import and build ITS project +- From the ETSI ITS Test System root directory, build the Docker image executing the following commands: -### Run Docker image +```sh +$ cd ./virtualization/docker +$ docker build --no-cache --tag alpine-its -f Dockerfile --force-rm . +$ docker images +``` -#### From Windows host: +To build the ITS Test Suite, execute the following command: -1. Authorize Docker container to interact with the XServer: -Go to the X Server installation directory and add the Docker container ip address to the file ```X0.hosts```: -``` -localhost -inet6:localhost -192.168.99.100 +```sh +$ ./docker-run.sh build ``` -Execute ```run.cmd``` or launch a command line window and run the command +Possble other options are 'clean' to remove all the build outputs or 'rebuild' to force a build of the Test Suite after a 'clean'. -```docker run -it --net=host -e DISPLAY=192.168.99.1:0 etsiforge/etsi-its-ts``` +To retrieve the list of the available test cases, execute the following command: -NOTE: Modify the IP address in the command for the address of 'VirtualBox Hot-Only Network'. +```sh +$ ./docker-run.sh list +``` -#### From Linux host: +Before to execute the ITS Test Suite, prepare, edit and update the configuration file (e.g. CAM Test Suite): + +```sh +$ ln -sf ../../etc/AtsCam/AtsCAM_xxx.cf_ ../../etc/AtsCam/AtsCAN.cfg +$ vi ../../etc/AtsCAM/AtsCAM.cfg # To update it +``` -Execute ```run.sh``` or launch a command line window and run the command +To execute the ITS Test Suite, execute the following command: ```sh -docker run -it --net=host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix etsiforge/etsi-its-ts +$ ./docker-run.sh run ``` +Notes: +- The ITS Test System is listening on port 442 +- Updating the file etc/AtsCAM.cfg is about: +. Selecting the test(s) to be executed +. Updating value of PICs and PIXITs +. Updating HTTP port setting + + diff --git a/virtualization/docker/docker-entrypoint.sh b/virtualization/docker/docker-entrypoint.sh new file mode 100755 index 0000000000000000000000000000000000000000..3fa9d562ec8119e42eab93cc7782c8b351fc70fb --- /dev/null +++ b/virtualization/docker/docker-entrypoint.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + echo "No command specified. Available commands:" + for i in $(echo $commands | sed "s/,/ /g") + do + echo " $i" + done +} + +commands="help,build CAM,clean CAM,list CAM,modulepar CAM,rebuild CAM,run CAM,version" + +if [ $# == 0 ]; then + usage + exit 1 +fi + +if [ $# == 2 ]; then + if [ "$2" != "" ]; then + export ATS=Ats$2 + cli="${GEN_DIR}/bin/$ATS" + echo "cli: $cli" + fi +fi + + +case "$1" in + build) + cd ${GEN_DIR} && make + ;; + clean) + cd ${GEN_DIR} && make clean + ;; + list) + ${cli} -l + ;; + modulepar) + ${cli} -p + ;; + rebuild) + cd ${GEN_DIR} && rm -fr ./bin ./build ; make + ;; + run) + cd ${GEN_DIR}/scripts && ./run_all.bash + ;; + version) + compiler -v + ;; + *) + usage + exit 1 + ;; +esac + +unset ATS +exit 0 \ No newline at end of file diff --git a/virtualization/docker/docker-run.sh b/virtualization/docker/docker-run.sh new file mode 100755 index 0000000000000000000000000000000000000000..50a34f148afd85002e5a075266fc0086f1b9fd25 --- /dev/null +++ b/virtualization/docker/docker-run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -exo pipefail + +cd "$(dirname ${BASH_SOURCE})" + +docker run --rm -it \ + -w $HOME/dev/TS.ITS \ + -e GEN_DIR=$HOME/dev/TS.ITS \ + -u "$(id -u):$(id -g)" \ + -v "${PWD}/../..:$HOME/dev/TS.ITS" \ + --entrypoint $HOME/dev/TS.ITS/virtualization/docker/docker-entrypoint.sh \ + alpine-its:latest "$@" +# -p 0.0.0.0:80:80 \ +# -p 0.0.0.0:443:443 \ diff --git a/virtualization/docker/home/etc/init.d/40-ttf011.sh b/virtualization/docker/home/etc/init.d/40-ttf011.sh deleted file mode 100755 index f8639c487cdbda442bc1ab2f8940a4061b6ade52..0000000000000000000000000000000000000000 --- a/virtualization/docker/home/etc/init.d/40-ttf011.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -#set -e -set -vx - -echo -e "*****************************\n* Checkout TS.ITS sources\n*****************************\n" -cd ${HOME}/dev || exit 1 - -git clone --recurse-submodules --single-branch https://forge.etsi.org/rep/ITS/TS.ITS.git TS.ITS -cd ./TS.ITS -for i in `find ./ttcn -type d -name "Ats*"` -do - cd $i - git checkout devel - cd - -done -for i in `find ./ttcn/Ats* -type d -name "asn1"` -do - cd $i - git checkout testing - SUB_DIRS=`find . -type d` - if [ "SUB_DIRS" != "" ] - then - for j in $SUB_DIRS - do - cd $j - git checkout testing - cd - - done - fi - cd - -done -cd ${HOME}/dev/TS.ITS/titan-test-system-framework -git checkout devel -cd ./ttcn/LibHttp -ln -sf module_its.mk module.mk -cd ${HOME}/dev/TS.ITS/ttcn/LibIts -git checkout devel - -echo -e "*****************************\n* Setup environment\n*****************************\n" -cd ${HOME}/dev/TS.ITS/scripts -chmod 775 *.bash devenv.bash.* -cd ${HOME} -ln -sf ${HOME}/dev/TS.ITS/scripts/devenv.bash.ubuntu ${HOME}/devenv.bash -ls -ltr ${HOME} - -cd ${HOME} - -exit 0 diff --git a/virtualization/vagrant/provisioner.bash b/virtualization/vagrant/provisioner.bash index 91c4747eb07781be8e82b3cd8dcab9c9b5bdb637..67dbf48714bc738e60574d87493e6fbaa1a79915 100755 --- a/virtualization/vagrant/provisioner.bash +++ b/virtualization/vagrant/provisioner.bash @@ -70,25 +70,41 @@ fi # Checkout TS.ITS sources cd /home/vagrant/dev -git clone --recurse-submodules --single-branch https://forge.etsi.org/rep/ITS/TS.ITS.git TS.ITS +git clone --recurse-submodules --single-branch --branch ttf_t024 https://forge.etsi.org/rep/ITS/TS.ITS.git TS.ITS cd ./TS.ITS for i in `find ./ttcn -type d -name "Ats*"` do cd $i - git checkout devel + git checkout devel2 cd - done for i in `find ./ttcn/Ats* -type d -name "asn1"` do cd $i - git checkout testing + git checkout testing2 + if [ -f ETSI-ITS-CDD.asn ] + then + ln -sf ETSI-ITS-CDD.asn ETSI_ITS_CDD.asn + elif [ -f IVIM-PDU-Descriptions.asn ] + then + ln -sf IVIM-PDU-Descriptions.asn IVIM_PDU_Descriptions.asn + ln -sf MAPEM-PDU-Descriptions.asn MAPEM_PDU_Descriptions.asn + ln -sf RTCMEM-PDU-Descriptions.asn RTCMEM_PDU_Descriptions.asn + ln -sf SPATEM-PDU-Descriptions.asn SPATEM_PDU_Descriptions.asn + ln -sf SREM-PDU-Descriptions.asn SREM_PDU_Descriptions.asn + ln -sf SSEM-PDU-Descriptions.asn SSEM_PDU_Descriptions.asn + ln -sf iso-patched/'ISO14906(2018)EfcDsrcApplicationv6-patched.asn' iso-patched/EfcDsrcApplication.asn + ln -sf iso-patched/'ISO14906(2018)EfcDsrcGenericv7-patched.asn' iso-patched/EfcDsrcGeneric.asn + ln -sf iso-patched/ISO24534-3_ElectronicRegistrationIdentificationVehicleDataModule-patched.asn iso-patched/ElectronicRegistrationIdentificationVehicleDataModule.asn + ln -sf iso-patched/ISO14823-missing.asn iso-patched/GDD.asn + fi SUB_DIRS=`find . -type d` if [ "SUB_DIRS" != "" ] then for j in $SUB_DIRS do cd $j - git checkout testing + git checkout testing2 cd - done fi @@ -174,10 +190,10 @@ cd ${HOME}/dev/TS.ITS/scripts # Build ETSI ITS certificate generation tools cd /home/vagrant/dev -git clone --recurse-submodules https://forge.etsi.org/rep/ITS/itscertgen.git ./itscertgen +git clone --recurse-submodules --branch release2 https://forge.etsi.org/rep/ITS/itscertgen.git ./itscertgen cd ./itscertgen -cd cshared && make && cd - -cd certgen/ && make && cd - +sed --in-place 's/\-fillabs2//g' ./certgen/asncodec/Makefile +make && cd - # Generate ETSI ITS certificates cd /home/vagrant/dev/TS.ITS/data/certificates CERTGEN=${HOME}/dev/itscertgen make