From 162dbc6897ef7f9579846942cf07e1ef5ee269f1 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Tue, 28 Sep 2021 11:39:44 -0700 Subject: [PATCH 001/184] AKMC-111: Enable standalone build & testing of CryptoLib outside of NOS3/cFS infrastructure --- .gitignore | 21 +++++ CMakeLists.txt | 36 ++++++-- fsw/CMakeLists.txt | 48 +++++++++++ fsw/crypto_tests/CMakeLists.txt | 20 +++++ fsw/crypto_tests/data/tc4.1.dat | Bin 0 -> 161 bytes fsw/crypto_util/CMakeLists.txt | 41 +++++++++ fsw/crypto_util/app/apply_security.c | 66 +++++++++++++++ fsw/crypto_util/app/crypto_sequence.c | 73 ++++++++++++++++ fsw/crypto_util/app/process_security.c | 63 ++++++++++++++ fsw/crypto_util/include/apply_security.h | 34 ++++++++ fsw/crypto_util/include/crypto_sequence.h | 34 ++++++++ fsw/crypto_util/include/process_security.h | 34 ++++++++ fsw/crypto_util/include/shared_util.h | 43 ++++++++++ fsw/crypto_util/src/shared_util.c | 93 +++++++++++++++++++++ fsw/public_inc/cfe_minimum.h | 50 +++++++++++ fsw/public_inc/common_types_minimum.h | 71 ++++++++++++++++ fsw/public_inc/crypto.h | 17 ++-- fsw/public_inc/crypto_config.h | 2 +- fsw/public_inc/crypto_print.h | 2 + fsw/public_inc/crypto_structs.h | 2 + fsw/public_inc/itc_gcm128.h | 4 + fsw/public_inc/osapi_minimum.h | 80 ++++++++++++++++++ fsw/src/crypto.c | 49 ++++++++++- fsw/src/crypto_print.c | 2 + 24 files changed, 861 insertions(+), 24 deletions(-) create mode 100644 .gitignore create mode 100644 fsw/CMakeLists.txt create mode 100644 fsw/crypto_tests/CMakeLists.txt create mode 100644 fsw/crypto_tests/data/tc4.1.dat create mode 100644 fsw/crypto_util/CMakeLists.txt create mode 100644 fsw/crypto_util/app/apply_security.c create mode 100644 fsw/crypto_util/app/crypto_sequence.c create mode 100644 fsw/crypto_util/app/process_security.c create mode 100644 fsw/crypto_util/include/apply_security.h create mode 100644 fsw/crypto_util/include/crypto_sequence.h create mode 100644 fsw/crypto_util/include/process_security.h create mode 100644 fsw/crypto_util/include/shared_util.h create mode 100644 fsw/crypto_util/src/shared_util.c create mode 100644 fsw/public_inc/cfe_minimum.h create mode 100644 fsw/public_inc/common_types_minimum.h create mode 100644 fsw/public_inc/osapi_minimum.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4fe5d94d --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +.idea +vgcore* +core +*.so +build +venv + +#CMake.gitignore +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +DartConfiguration.tcl diff --git a/CMakeLists.txt b/CMakeLists.txt index 28fcc4c7..2651840b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,20 +14,38 @@ # NASA IV&V # ivv-itc@lists.nasa.gov -cmake_minimum_required(VERSION 2.6.4) +#cmake_minimum_required(VERSION 2.6.4) +cmake_minimum_required(VERSION 3.14.0) project(CRYPTO C) +set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") + +OPTION(DEBUG "Debug" OFF) # Disabled by default +IF(DEBUG) + ADD_DEFINITIONS(-DDEBUG) + add_compile_options(-ggdb) +ENDIF(DEBUG) + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + include(CTest) + enable_testing() +endif() + include_directories(fsw/public_inc) # The shared OSAL and cFE include directories should always be used # Note that this intentionally does NOT include PSP-specific includes, just the generic -include_directories(${CFECORE_SOURCE_DIR}/src/inc) -include_directories(${CFEPSP_SOURCE_DIR}/fsw/inc) - -aux_source_directory(fsw/src LIB_SRC_FILES) +# Only include cFS/NOS3 directories if env var is defined +if(DEFINED ENV{CFECORE_SOURCE_DIR}) #if ${CFECORE_SOURCE_DIR} is set, expect cFS build infrastructure to be in place. + include_directories(${CFECORE_SOURCE_DIR}/src/inc) + include_directories(${CFEPSP_SOURCE_DIR}/fsw/inc) + ADD_DEFINITIONS(-DNOS3) +else() + #pass +endif() -# Create the app module -add_cfe_app(crypto ${LIB_SRC_FILES}) +if(NOT DEFINED ${PROJECT_BINARY_DIR}) + set(PROJECT_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build) +endif() -# Add libgcrypt -target_link_libraries(crypto libgcrypt) +add_subdirectory(fsw) diff --git a/fsw/CMakeLists.txt b/fsw/CMakeLists.txt new file mode 100644 index 00000000..3bc71820 --- /dev/null +++ b/fsw/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +# +# This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not +# limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +# for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +# any warranty that the software will be error free. +# +# In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +# arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +# contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +# documentation or services provided hereunder +# +# ITC Team +# NASA IV&V +# ivv-itc@lists.nasa.gov + +include_directories(public_inc) + +aux_source_directory(src LIB_SRC_FILES) + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + include(CTest) + enable_testing() +endif() + +# Create the app module +if(DEFINED ENV{CFECORE_SOURCE_DIR}) #if ${CFECORE_SOURCE_DIR} is set, expect cFS build infrastructure to be in place. + add_cfe_app(Crypto ${LIB_SRC_FILES}) +else() #standalone build + add_library(Crypto SHARED ${LIB_SRC_FILES}) +endif() + +# Add libgcrypt +target_link_libraries(Crypto gcrypt) + +#Include cmake install module - todo +#include(GNUInstallDirs) + +add_custom_command(TARGET Crypto POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_BINARY_DIR}/lib/libCrypto.so + COMMENT "Created ${PROJECT_BINARY_DIR}/lib/libCrypto.so" + ) + +add_subdirectory(crypto_util) + +if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MYPROJECT_BUILD_TESTING) AND BUILD_TESTING) + add_subdirectory(crypto_tests) +endif() diff --git a/fsw/crypto_tests/CMakeLists.txt b/fsw/crypto_tests/CMakeLists.txt new file mode 100644 index 00000000..d53b7cdc --- /dev/null +++ b/fsw/crypto_tests/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +# +# This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not +# limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +# for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +# any warranty that the software will be error free. +# +# In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +# arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +# contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +# documentation or services provided hereunder +# +# ITC Team +# NASA IV&V +# ivv-itc@lists.nasa.gov +set(PROJECT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +add_test(NAME Process_Security + COMMAND ${PROJECT_BINARY_DIR}/bin/process_security tc ${PROJECT_TEST_DIR}/data/tc4.1.dat + WORKING_DIRECTORY ${PROJECT_TEST_DIR}) \ No newline at end of file diff --git a/fsw/crypto_tests/data/tc4.1.dat b/fsw/crypto_tests/data/tc4.1.dat new file mode 100644 index 0000000000000000000000000000000000000000..6f4bf17bd230c0c781bfb1e73979d3eab324991f GIT binary patch literal 161 zcmV;S0ABwf0|1@?{{R6102qMKHvo(oe+vKs0E7SlG)R)W#ZOa}DSb>g7cVM2M)s&2 z6G`dfYRCzN*t^wQSQN%$bK`>7`kax*%%8C5DC6&LMgr7f;; literal 0 HcmV?d00001 diff --git a/fsw/crypto_util/CMakeLists.txt b/fsw/crypto_util/CMakeLists.txt new file mode 100644 index 00000000..6ff0d152 --- /dev/null +++ b/fsw/crypto_util/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +# +# This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not +# limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +# for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +# any warranty that the software will be error free. +# +# In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +# arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +# contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +# documentation or services provided hereunder +# +# ITC Team +# NASA IV&V +# ivv-itc@lists.nasa.gov + +include_directories(include) +include_directories(../crypto/public_inc) + +aux_source_directory(src UTIL_SRC_FILES) +aux_source_directory(app APP_SRC_FILES) + +file( GLOB SOURCE_FILES app/*.c ) +foreach(SOURCE_PATH ${SOURCE_FILES}) + + get_filename_component(EXECUTABLE_NAME ${SOURCE_PATH} NAME_WE) + + add_executable(${EXECUTABLE_NAME} ${SOURCE_PATH}) + + target_sources(${EXECUTABLE_NAME} PRIVATE src/shared_util.c) + target_link_libraries(${EXECUTABLE_NAME} LINK_PUBLIC Crypto) + + add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_BINARY_DIR}/bin/${EXECUTABLE_NAME} + COMMAND ${CMAKE_COMMAND} -E rm $ + COMMENT "Created ${PROJECT_BINARY_DIR}/bin/${EXECUTABLE_NAME}" + ) +endforeach(SOURCE_PATH ${SOURCE_FILES}) + +target_include_directories (Crypto PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + diff --git a/fsw/crypto_util/app/apply_security.c b/fsw/crypto_util/app/apply_security.c new file mode 100644 index 00000000..e41f5f7d --- /dev/null +++ b/fsw/crypto_util/app/apply_security.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +/* + * Simple apply security program that reads a file into memory and calls the Crypto_TC_ApplySecurity function on the data. + */ + +#include "apply_security.h" + +int main(int argc, char *argv[]) { + char *buffer; + char const *filename; + long buffer_size; + char *security_type; + + if (argc == 3) { + security_type = argv[1]; + filename = argv[2]; + } else { + fprintf(stderr,"Command line usage: \n"\ + "\t%s \n"\ + " : Apply TeleCommand (tc) | Telemetry (tm) | Advanced Orbiting Systems (aos) Security T\n"\ + " : binary file with telecommand transfer frame bits\n",argv[0]); + + return OS_ERROR; + } + buffer = c_read_file(filename,&buffer_size); + debug_printf("File buffer size:%lu\n",buffer_size); + int buffer_size_i = (int) buffer_size; + debug_printf("File buffer size int:%d\n",buffer_size_i); + debug_printf("File content: \n"); + debug_hexprintf(buffer,buffer_size_i); + + + //Setup & Initialize CryptoLib + Crypto_Init(); + + //Call ApplySecurity on buffer contents depending on type. + if (strcmp(security_type,"tc")==0){ + Crypto_TC_ApplySecurity(&buffer, &buffer_size_i); + } else if (strcmp(security_type,"tm")==0){ + Crypto_TM_ApplySecurity(buffer, &buffer_size_i); + } else if (strcmp(security_type,"aos")==0){ + Crypto_AOS_ApplySecurity(buffer, &buffer_size_i); + } + + debug_printf("Applied Security buffer size int:%d\n",buffer_size_i); + debug_printf("File content: \n"); + debug_hexprintf(buffer,buffer_size_i); + + free(buffer); +} \ No newline at end of file diff --git a/fsw/crypto_util/app/crypto_sequence.c b/fsw/crypto_util/app/crypto_sequence.c new file mode 100644 index 00000000..be43b008 --- /dev/null +++ b/fsw/crypto_util/app/crypto_sequence.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + + +/* + * Simple crypto security program that reads files into memory and calls the appropriate Crypto* function on the data. + */ + +#include "crypto_sequence.h" + +int main(int argc, char *argv[]) { + char *buffer; + char const *filename; + long buffer_size; + char *security_type; + + if (argc < 3 || argc % 2 == 0) { + fprintf(stderr,"Command line usage: \n"\ + "\t%s [ ]+\n"\ + "specify as many [ ] pairs as necessary to complete your crypto sequence test. Each file will be loaded and processed in sequence. \n"\ + " : Apply TeleCommand (tc_a) | Telemetry (tm_a) | Advanced Orbiting Systems (aos_a) Security T\n"\ + " : Process TeleCommand (tc_p) | Telemetry (tm_p) | Advanced Orbiting Systems (aos_p) Security T\n"\ + " : binary file with telecommand transfer frame bits\n",argv[0]); + + return OS_ERROR; + } + //Setup & Initialize CryptoLib + Crypto_Init(); + + int arg_index = 0; + while(arg_index != argc-1){ + security_type = argv[++arg_index]; + debug_printf("Security Type: %s\n",security_type); + filename = argv[++arg_index]; + debug_printf("Filename: %s\n",filename); + buffer = c_read_file(filename,&buffer_size); + debug_printf("File buffer size:%lu\n",buffer_size); + int buffer_size_i = (int) buffer_size; + debug_printf("File buffer size int:%d\n",buffer_size_i); + debug_printf("File content: \n"); + debug_hexprintf(buffer,buffer_size_i); + + //Call Apply/ProcessSecurity on buffer contents depending on type. + if (strcmp(security_type,"tc_a")==0){ + Crypto_TC_ApplySecurity(&buffer, &buffer_size_i); + } else if (strcmp(security_type,"tm_a")==0){ + Crypto_TM_ApplySecurity(buffer, &buffer_size_i); + } else if (strcmp(security_type,"aos_a")==0){ + Crypto_AOS_ApplySecurity(buffer, &buffer_size_i); + } else if (strcmp(security_type,"tc_p")==0){ + Crypto_TC_ProcessSecurity(buffer, &buffer_size_i); + } else if (strcmp(security_type,"tm_p")==0){ + Crypto_TM_ProcessSecurity(buffer, &buffer_size_i); + } else if (strcmp(security_type,"aos_p")==0){ + Crypto_AOS_ProcessSecurity(buffer, &buffer_size_i); + } + free(buffer); + } +} \ No newline at end of file diff --git a/fsw/crypto_util/app/process_security.c b/fsw/crypto_util/app/process_security.c new file mode 100644 index 00000000..15d1cad7 --- /dev/null +++ b/fsw/crypto_util/app/process_security.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + + +/* + * Simple Process security program that reads a file into memory and calls the Crypto_TC_ProcessSecurity function on the data. + */ + +#include "process_security.h" + +int main(int argc, char *argv[]) { + char *buffer; + char const *filename; + long buffer_size; + char *security_type; + + if (argc == 3) { + security_type = argv[1]; + filename = argv[2]; + } else { + fprintf(stderr,"Command line usage: \n"\ + "\t%s \n"\ + " : Process TeleCommand (tc) | Telemetry (tm) | Advanced Orbiting Systems (aos) Security T\n"\ + " : binary file with telecommand transfer frame bits\n",argv[0]); + + return OS_ERROR; + } + buffer = c_read_file(filename,&buffer_size); + debug_printf("File buffer size:%lu\n",buffer_size); + int buffer_size_i = (int) buffer_size; + debug_printf("File buffer size int:%d\n",buffer_size_i); + debug_printf("File content: \n"); + debug_hexprintf(buffer,buffer_size_i); + + + //Setup & Initialize CryptoLib + Crypto_Init(); + + //Call ProcessSecurity on buffer contents depending on type. + if (strcmp(security_type,"tc")==0){ + Crypto_TC_ProcessSecurity(buffer, &buffer_size_i); + } else if (strcmp(security_type,"tm")==0){ + Crypto_TM_ProcessSecurity(buffer, &buffer_size_i); + } else if (strcmp(security_type,"aos")==0){ + Crypto_AOS_ProcessSecurity(buffer, &buffer_size_i); + } + + free(buffer); +} \ No newline at end of file diff --git a/fsw/crypto_util/include/apply_security.h b/fsw/crypto_util/include/apply_security.h new file mode 100644 index 00000000..c34ebf99 --- /dev/null +++ b/fsw/crypto_util/include/apply_security.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +#ifndef AMMOS_CRYPTOLIB_APPLY_SECURITY_H +#define AMMOS_CRYPTOLIB_APPLY_SECURITY_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "crypto.h" +#include "shared_util.h" +#include + +#ifdef __cplusplus +} /* Close scope of 'extern "C"' declaration which encloses file. */ +#endif + +#endif //AMMOS_CRYPTOLIB_APPLY_SECURITY_H diff --git a/fsw/crypto_util/include/crypto_sequence.h b/fsw/crypto_util/include/crypto_sequence.h new file mode 100644 index 00000000..0de48f28 --- /dev/null +++ b/fsw/crypto_util/include/crypto_sequence.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +#ifndef AMMOS_CRYPTOLIB_CRYPTO_SEQUENCE_H +#define AMMOS_CRYPTOLIB_CRYPTO_SEQUENCE_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "crypto.h" +#include "shared_util.h" +#include + +#ifdef __cplusplus +} /* Close scope of 'extern "C"' declaration which encloses file. */ +#endif + +#endif //AMMOS_CRYPTOLIB_CRYPTO_SEQUENCE_H diff --git a/fsw/crypto_util/include/process_security.h b/fsw/crypto_util/include/process_security.h new file mode 100644 index 00000000..5e1ca946 --- /dev/null +++ b/fsw/crypto_util/include/process_security.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +#ifndef AMMOS_CRYPTOLIB_PROCESS_SECURITY_H +#define AMMOS_CRYPTOLIB_PROCESS_SECURITY_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "crypto.h" +#include "shared_util.h" +#include + +#ifdef __cplusplus +} /* Close scope of 'extern "C"' declaration which encloses file. */ +#endif + +#endif //AMMOS_CRYPTOLIB_PROCESS_SECURITY_H diff --git a/fsw/crypto_util/include/shared_util.h b/fsw/crypto_util/include/shared_util.h new file mode 100644 index 00000000..07973dee --- /dev/null +++ b/fsw/crypto_util/include/shared_util.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +#ifndef AMMOS_CRYPTOLIB_SHARED_UTIL_H +#define AMMOS_CRYPTOLIB_SHARED_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + + +#include "osapi_minimum.h" + +char * c_read_file(const char * f_name, long * f_size); + +void debug_printf(const char* format, ...); +void debug_hexprintf(const char* bin_data,int size_bin_data); + + +#ifdef __cplusplus +} /* Close scope of 'extern "C"' declaration which encloses file. */ +#endif + +#endif //AMMOS_CRYPTOLIB_SHARED_UTIL_H diff --git a/fsw/crypto_util/src/shared_util.c b/fsw/crypto_util/src/shared_util.c new file mode 100644 index 00000000..91def234 --- /dev/null +++ b/fsw/crypto_util/src/shared_util.c @@ -0,0 +1,93 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +#include "shared_util.h" + +//temp debug, remove later. +#include + + +/* +* Function: c_read_file +* -------------------- +* Reads a file from disk into a char * buffer. +* +* +* const char* f_name: file name & path to be read +* long* f_size: +* +* returns: a malloc'd char* containing the contents of the buffer. +* Note that this buffer is NOT null terminated and must be free()'d. +*/ +char * c_read_file(const char * f_name, long * f_size) { + char* buffer=0; + long length; + FILE* f = fopen(f_name,"rb"); + if (f){ + fseek (f, 0, SEEK_END); + length = ftell (f); + fseek (f, 0, SEEK_SET); + buffer = malloc (length); + if (buffer) { + fread (buffer, 1, length, f); + } + fclose (f); + } + if (buffer){ + *f_size = length; + debug_printf("Buffer Length:%lu\n",length); + return buffer; + } else{ + return NULL; + } + +} + +#ifdef DEBUG +void debug_printf(const char *format, ...) +{ + va_list args; + fprintf(stderr, "DEBUG - "); + va_start(args, format); + vfprintf(stderr,format, args); + va_end(args); +} +#else +void debug_printf(const char* format, ...) { + //Do nothing, DEBUG preprocessor disabled. +} +#endif + +#ifdef DEBUG +void debug_hexprintf(const char *bin_data, int size_bin_data) +{ + //https://stackoverflow.com/questions/6357031/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-in-c + //https://stackoverflow.com/questions/5040920/converting-from-signed-char-to-unsigned-char-and-back-again + unsigned char* u_bin_data = (unsigned char*)bin_data; + unsigned char output[(size_bin_data*2)+1]; + char *ptr = &output[0]; + int i; + for(i=0; i < size_bin_data; i++){ + ptr += sprintf(ptr,"%02X",u_bin_data[i]); + } + debug_printf("%s\n",output); +} +#else +void debug_hexprintf(const char* bin_data, int size_bin_data) { + //Do nothing, DEBUG preprocessor disabled. +} +#endif diff --git a/fsw/public_inc/cfe_minimum.h b/fsw/public_inc/cfe_minimum.h new file mode 100644 index 00000000..42ded8d4 --- /dev/null +++ b/fsw/public_inc/cfe_minimum.h @@ -0,0 +1,50 @@ +/* +** Minimal port of https://github.com/nasa-itc/cFE/blob/master/fsw/cfe-core/src/inc/cfe.h +** needed to build standalone crypto library. +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** File: cfe.h +** +** Purpose: cFE header file +** +** Author: David Kobe, the Hammers Company, Inc. +** +** Notes: This header file centralizes the includes for all cFE +** Applications. It includes all header files necessary +** to completely define the cFE interface. +** +*/ + +/*************************************************************************/ + +/* +** Ensure that header is included only once... +*/ +#ifndef _cfe_minimum_ +#define _cfe_minimum_ + +#include "common_types_minimum.h" +#include "osapi_minimum.h" + +#define CFE_PSP_MemCpy memcpy +#define CFE_PSP_MemSet memset +#define OS_printf printf + +#endif /* _cfe_ */ diff --git a/fsw/public_inc/common_types_minimum.h b/fsw/public_inc/common_types_minimum.h new file mode 100644 index 00000000..23bb908d --- /dev/null +++ b/fsw/public_inc/common_types_minimum.h @@ -0,0 +1,71 @@ +/* + * Minimal port of https://github.com/nasa-itc/osal/blob/master/src/os/inc/common_types.h + * needed to build standalone crypto library. + * + * Copyright (c) 2019 United States Government as represented by + * the Administrator of the National Aeronautics and Space Administration. + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Filename: common_types.h + * + * Purpose: + * Unit specification for common types. + * + * Design Notes: + * Assumes make file has defined processor family + * + * References: + * Flight Software Branch C Coding Standard Version 1.0a + * + * Notes: + */ + +#ifndef _common_types_minimum_ +#define _common_types_minimum_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include +#include +#include + +/* + * NOTE - NOT DEFINING STRUCT_LOW_BIT_FIRST or STRUCT_HIGH_BIT_FIRST + * We should not make assumptions about the bit order here + */ + + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + typedef uint8_t uint8; + typedef uint16_t uint16; + typedef uint32_t uint32; + typedef uint64_t uint64; + typedef intptr_t intptr; + typedef uintptr_t cpuaddr; + typedef size_t cpusize; + typedef ptrdiff_t cpudiff; + + +#ifdef __cplusplus + } +#endif + +#endif /* _common_types_ */ diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index d93c8ef9..b51d3611 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -20,15 +20,12 @@ ivv-itc@lists.nasa.gov /* ** Crypto Includes */ -#include "cfe.h" -#include "itc_aes128.h" -#include "itc_gcm128.h" -#include "crypto_config.h" -#include "crypto_events.h" -#include "crypto_structs.h" -#include "crypto_print.h" -#include +#ifdef NOS3 //NOS3/cFS build is ready +#include "cfe.h" +#else //Assume build outside of NOS3/cFS infrastructure +#include "cfe_minimum.h" +#endif #define CRYPTO_LIB_MAJOR_VERSION 1 #define CRYPTO_LIB_MINOR_VERSION 2 @@ -39,9 +36,9 @@ ivv-itc@lists.nasa.gov ** Prototypes */ // Initialization -extern int32 crypto_LibInit(void); +extern int32 Crypto_Init(void); // Telecommand (TC) -extern int32 Crypto_TC_ApplySecurity(char* ingest, int* len_ingest); +extern int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest); extern int32 Crypto_TC_ProcessSecurity(char* ingest, int* len_ingest); // Telemetry (TM) extern int32 Crypto_TM_ApplySecurity(char* ingest, int* len_ingest); diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index ab388c54..cf305d04 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -23,7 +23,7 @@ ivv-itc@lists.nasa.gov // Debug Defines //#define ARC_DEBUG //#define CCSDS_DEBUG - #define DEBUG + //#define DEBUG //(CMAKE option, not hardcoded) //#define FECF_DEBUG //#define MAC_DEBUG #define OCF_DEBUG diff --git a/fsw/public_inc/crypto_print.h b/fsw/public_inc/crypto_print.h index 10294129..41a5d858 100644 --- a/fsw/public_inc/crypto_print.h +++ b/fsw/public_inc/crypto_print.h @@ -22,6 +22,8 @@ ** Includes */ #include "crypto.h" +#include "crypto_structs.h" + /* ** Prototypes diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index ca06747b..e5c3e5ab 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -297,11 +297,13 @@ typedef struct } CCSDS_PUS_t; #define CCSDS_PUS_SIZE (sizeof(CCSDS_PUS_t)) +/* unused? typedef struct { uint8 CmdHeader[CFE_SB_CMD_HDR_SIZE]; } Crypto_NoArgsCmd_t; +*/ typedef struct { diff --git a/fsw/public_inc/itc_gcm128.h b/fsw/public_inc/itc_gcm128.h index 1013bf68..c9800af1 100644 --- a/fsw/public_inc/itc_gcm128.h +++ b/fsw/public_inc/itc_gcm128.h @@ -19,7 +19,11 @@ #define ITC_GCM128_H // CFS Includes +#ifdef NOS3 //NOS3/cFS build is ready #include "common_types.h" +#else //Assume build outside of NOS3/cFS infrastructure +#include "common_types_minimum.h" +#endif // Standard Includes #include "itc_aes128.h" diff --git a/fsw/public_inc/osapi_minimum.h b/fsw/public_inc/osapi_minimum.h new file mode 100644 index 00000000..53ee60cb --- /dev/null +++ b/fsw/public_inc/osapi_minimum.h @@ -0,0 +1,80 @@ +/* + * Minimal port of https://github.com/nasa-itc/osal/blob/master/src/os/inc/osapi.h + * needed to build standalone crypto library. + * + * Copyright (c) 2019 United States Government as represented by + * the Administrator of the National Aeronautics and Space Administration. + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef _osapi_minimum_ +#define _osapi_minimum_ + +#include +#include + +#include "common_types_minimum.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define OS_SUCCESS (0) +#define OS_ERROR (-1) +#define OS_INVALID_POINTER (-2) +#define OS_ERROR_ADDRESS_MISALIGNED (-3) +#define OS_ERROR_TIMEOUT (-4) +#define OS_INVALID_INT_NUM (-5) +#define OS_SEM_FAILURE (-6) +#define OS_SEM_TIMEOUT (-7) +#define OS_QUEUE_EMPTY (-8) +#define OS_QUEUE_FULL (-9) +#define OS_QUEUE_TIMEOUT (-10) +#define OS_QUEUE_INVALID_SIZE (-11) +#define OS_QUEUE_ID_ERROR (-12) +#define OS_ERR_NAME_TOO_LONG (-13) +#define OS_ERR_NO_FREE_IDS (-14) +#define OS_ERR_NAME_TAKEN (-15) +#define OS_ERR_INVALID_ID (-16) +#define OS_ERR_NAME_NOT_FOUND (-17) +#define OS_ERR_SEM_NOT_FULL (-18) +#define OS_ERR_INVALID_PRIORITY (-19) +#define OS_INVALID_SEM_VALUE (-20) +#define OS_ERR_FILE (-27) +#define OS_ERR_NOT_IMPLEMENTED (-28) +#define OS_TIMER_ERR_INVALID_ARGS (-29) +#define OS_TIMER_ERR_TIMER_ID (-30) +#define OS_TIMER_ERR_UNAVAILABLE (-31) +#define OS_TIMER_ERR_INTERNAL (-32) +#define OS_ERR_OBJECT_IN_USE (-33) +#define OS_ERR_BAD_ADDRESS (-34) +#define OS_ERR_INCORRECT_OBJ_STATE (-35) +#define OS_ERR_INCORRECT_OBJ_TYPE (-36) +#define OS_ERR_STREAM_DISCONNECTED (-37) + +/* +** Defines for Queue Timeout parameters +*/ +#define OS_PEND (-1) +#define OS_CHECK (0) + + +#ifdef __cplusplus + } +#endif + +#endif + diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 60f9649f..a1070845 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -22,6 +22,19 @@ ivv-itc@lists.nasa.gov */ #include "crypto.h" +#include "itc_aes128.h" +#include "itc_gcm128.h" + +#include "crypto_structs.h" +#include "crypto_print.h" +#include "crypto_config.h" +#include "crypto_events.h" + + + +#include + + /* ** Static Library Declaration */ @@ -682,13 +695,14 @@ static int32 Crypto_SA_config(void) return status; } -int32 crypto_Init(void) +int32 Crypto_Init(void) { int32 status = OS_SUCCESS; // Initialize libgcrypt if (!gcry_check_version(GCRYPT_VERSION)) { + fprintf(stderr, "Gcrypt Version: %s",GCRYPT_VERSION); OS_printf(KRED "ERROR: gcrypt version mismatch! \n" RESET); } if (gcry_control(GCRYCTL_SELFTEST) != GPG_ERR_NO_ERROR) @@ -2627,18 +2641,45 @@ static int32 Crypto_PDU(char* ingest) return status; } -int32 Crypto_TC_ApplySecurity(char* ingest, int* len_ingest) +int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest) { // Local Variables int32 status = OS_SUCCESS; + unsigned char* tc_ingest = *ingest; #ifdef DEBUG OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); #endif // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; + //len_ingest = len_ingest; + //ingest[0] = ingest[0]; + + int security_header_bytes = 18; + int security_trailer_bytes = 16; + int tc_size = *len_ingest + security_header_bytes + security_trailer_bytes; + + unsigned char * tempTC=NULL; + tempTC = (unsigned char *)malloc(tc_size * sizeof (unsigned char)); + CFE_PSP_MemSet(tempTC, 0, tc_size); + + int count = 0; + //Create Security Header + for (;count < security_header_bytes;count++){ + tempTC[count]= 0x55; //put dummy filler bits in security header for now. + } + + //Create Frame Body + CFE_PSP_MemCpy(&tempTC[security_header_bytes],&tc_ingest[0],*len_ingest); + count+=*len_ingest; + + //Create Security Trailer + for(;count < tc_size;count++){ + tempTC[count]=0x55; //put dummy filler bits in security trailer for now. + } + + *ingest = tempTC; + *len_ingest = tc_size; #ifdef DEBUG OS_printf(KYEL "----- Crypto_TC_ApplySecurity END -----\n" RESET); diff --git a/fsw/src/crypto_print.c b/fsw/src/crypto_print.c index ef98d633..96aef79c 100644 --- a/fsw/src/crypto_print.c +++ b/fsw/src/crypto_print.c @@ -21,6 +21,8 @@ ivv-itc@lists.nasa.gov ** Includes */ #include "crypto_print.h" +#include "crypto_structs.h" + /* ** Print Functions From 70a1c04803b5539c24d042dbaebf67d674752634 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Tue, 28 Sep 2021 11:44:44 -0700 Subject: [PATCH 002/184] AKMC-111: Remove AMMOS references in util header files --- fsw/crypto_util/include/apply_security.h | 6 +++--- fsw/crypto_util/include/crypto_sequence.h | 6 +++--- fsw/crypto_util/include/process_security.h | 6 +++--- fsw/crypto_util/include/shared_util.h | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/fsw/crypto_util/include/apply_security.h b/fsw/crypto_util/include/apply_security.h index c34ebf99..093fee15 100644 --- a/fsw/crypto_util/include/apply_security.h +++ b/fsw/crypto_util/include/apply_security.h @@ -15,8 +15,8 @@ ivv-itc@lists.nasa.gov */ -#ifndef AMMOS_CRYPTOLIB_APPLY_SECURITY_H -#define AMMOS_CRYPTOLIB_APPLY_SECURITY_H +#ifndef CRYPTOLIB_APPLY_SECURITY_H +#define CRYPTOLIB_APPLY_SECURITY_H #ifdef __cplusplus extern "C" { @@ -31,4 +31,4 @@ extern "C" { } /* Close scope of 'extern "C"' declaration which encloses file. */ #endif -#endif //AMMOS_CRYPTOLIB_APPLY_SECURITY_H +#endif //CRYPTOLIB_APPLY_SECURITY_H diff --git a/fsw/crypto_util/include/crypto_sequence.h b/fsw/crypto_util/include/crypto_sequence.h index 0de48f28..117c06dd 100644 --- a/fsw/crypto_util/include/crypto_sequence.h +++ b/fsw/crypto_util/include/crypto_sequence.h @@ -15,8 +15,8 @@ ivv-itc@lists.nasa.gov */ -#ifndef AMMOS_CRYPTOLIB_CRYPTO_SEQUENCE_H -#define AMMOS_CRYPTOLIB_CRYPTO_SEQUENCE_H +#ifndef CRYPTOLIB_CRYPTO_SEQUENCE_H +#define CRYPTOLIB_CRYPTO_SEQUENCE_H #ifdef __cplusplus extern "C" { @@ -31,4 +31,4 @@ extern "C" { } /* Close scope of 'extern "C"' declaration which encloses file. */ #endif -#endif //AMMOS_CRYPTOLIB_CRYPTO_SEQUENCE_H +#endif //CRYPTOLIB_CRYPTO_SEQUENCE_H diff --git a/fsw/crypto_util/include/process_security.h b/fsw/crypto_util/include/process_security.h index 5e1ca946..1a81bf24 100644 --- a/fsw/crypto_util/include/process_security.h +++ b/fsw/crypto_util/include/process_security.h @@ -15,8 +15,8 @@ ivv-itc@lists.nasa.gov */ -#ifndef AMMOS_CRYPTOLIB_PROCESS_SECURITY_H -#define AMMOS_CRYPTOLIB_PROCESS_SECURITY_H +#ifndef CRYPTOLIB_PROCESS_SECURITY_H +#define CRYPTOLIB_PROCESS_SECURITY_H #ifdef __cplusplus extern "C" { @@ -31,4 +31,4 @@ extern "C" { } /* Close scope of 'extern "C"' declaration which encloses file. */ #endif -#endif //AMMOS_CRYPTOLIB_PROCESS_SECURITY_H +#endif //CRYPTOLIB_PROCESS_SECURITY_H diff --git a/fsw/crypto_util/include/shared_util.h b/fsw/crypto_util/include/shared_util.h index 07973dee..f94a6a69 100644 --- a/fsw/crypto_util/include/shared_util.h +++ b/fsw/crypto_util/include/shared_util.h @@ -15,8 +15,8 @@ ivv-itc@lists.nasa.gov */ -#ifndef AMMOS_CRYPTOLIB_SHARED_UTIL_H -#define AMMOS_CRYPTOLIB_SHARED_UTIL_H +#ifndef CRYPTOLIB_SHARED_UTIL_H +#define CRYPTOLIB_SHARED_UTIL_H #ifdef __cplusplus extern "C" { @@ -40,4 +40,4 @@ void debug_hexprintf(const char* bin_data,int size_bin_data); } /* Close scope of 'extern "C"' declaration which encloses file. */ #endif -#endif //AMMOS_CRYPTOLIB_SHARED_UTIL_H +#endif //CRYPTOLIB_SHARED_UTIL_H From cbfa0072c3e6aed3d3f4493dea87b11471554407 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 1 Oct 2021 17:45:05 +0000 Subject: [PATCH 003/184] Initial branch commit From 447eaa31a2cb6cdf6d0fbf6ac8454a8efb93f38b Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Tue, 5 Oct 2021 14:35:04 -0700 Subject: [PATCH 004/184] AKMC-113: Refactor SA interface to support template configs for mariadb & inmemory setups --- fsw/public_inc/crypto.h | 11 + fsw/public_inc/crypto_error.h | 20 + fsw/public_inc/sadb_routine.h | 51 + fsw/src/crypto.c | 1367 ++++------------------ fsw/src/sadb_routine.c | 20 + fsw/src/sadb_routine_inmemory.template.c | 1048 +++++++++++++++++ fsw/src/sadb_routine_mariadb.template.c | 72 ++ 7 files changed, 1433 insertions(+), 1156 deletions(-) create mode 100644 fsw/public_inc/crypto_error.h create mode 100644 fsw/public_inc/sadb_routine.h create mode 100644 fsw/src/sadb_routine.c create mode 100644 fsw/src/sadb_routine_inmemory.template.c create mode 100644 fsw/src/sadb_routine_mariadb.template.c diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index b51d3611..e90f5902 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -27,6 +27,8 @@ ivv-itc@lists.nasa.gov #include "cfe_minimum.h" #endif +#include "crypto_structs.h" + #define CRYPTO_LIB_MAJOR_VERSION 1 #define CRYPTO_LIB_MINOR_VERSION 2 #define CRYPTO_LIB_REVISION 0 @@ -50,5 +52,14 @@ extern int32 Crypto_AOS_ProcessSecurity(char* ingest, int* len_ingest); extern int32 Crypto_ApplySecurity(char* ingest, int* len_ingest); extern int32 Crypto_ProcessSecurity(char* ingest, int* len_ingest); +// Data stores used in multiple components +extern TC_t tc_frame; +extern CCSDS_t sdls_frame; +extern TM_t tm_frame; +extern crypto_key_t ek_ring[NUM_KEYS]; +// Assisting functions used in multiple components +extern uint8 Crypto_Prep_Reply(char* ingest, uint8 appID); +extern int32 Crypto_increment(uint8 *num, int length); + #endif \ No newline at end of file diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h new file mode 100644 index 00000000..d69e7316 --- /dev/null +++ b/fsw/public_inc/crypto_error.h @@ -0,0 +1,20 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + +This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not +limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +any warranty that the software will be error free. + +In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +documentation or services provided hereunder + +ITC Team +NASA IV&V +ivv-itc@lists.nasa.gov +*/ +#ifndef _crypto_error_h_ +#define _crypto_error_h_ + +#endif //_crypto_error_h_ diff --git a/fsw/public_inc/sadb_routine.h b/fsw/public_inc/sadb_routine.h new file mode 100644 index 00000000..34e7b526 --- /dev/null +++ b/fsw/public_inc/sadb_routine.h @@ -0,0 +1,51 @@ +/* + * Copyright 2021, by the California Institute of Technology. + * ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged. + * Any commercial use must be negotiated with the Office of Technology + * Transfer at the California Institute of Technology. + * + * This software may be subject to U.S. export control laws. By accepting + * this software, the user agrees to comply with all applicable U.S. + * export laws and regulations. User has the responsibility to obtain + * export licenses, or other export authority as may be required before + * exporting such information to foreign countries or providing access to + * foreign persons. + */ + +#ifndef CRYPTOLIB_SADB_ROUTINE_H +#define CRYPTOLIB_SADB_ROUTINE_H + +#ifdef NOS3 //NOS3/cFS build is ready +#include "common_types.h" +#include "osapi.h" +#else //Assume build outside of NOS3/cFS infrastructure +#include "common_types_minimum.h" +#include "osapi_minimum.h" +#endif + +#include "crypto_structs.h" + +typedef struct { + // Security Association Initialization Functions + int32 (*sadb_config)(void); + int32 (*sadb_init)(void); + // Security Association Interaction Functions + int32 (*sadb_get_sa_from_spi)(uint16,SecurityAssociation_t**); + // Security Association Utility Functions + int32 (*sadb_sa_stop)(void); + int32 (*sadb_sa_start)(void); + int32 (*sadb_sa_expire)(void); + int32 (*sadb_sa_rekey)(void); + int32 (*sadb_sa_status)(char*); + int32 (*sadb_sa_create)(void); + int32 (*sadb_sa_setARSN)(void); + int32 (*sadb_sa_setARSNW)(void); + int32 (*sadb_sa_delete)(void); + +} SadbRoutineStruct, *SadbRoutine; + +SadbRoutine get_sadb_routine_mariadb(void); +SadbRoutine get_sadb_routine_inmemory(void); +SadbRoutine init_parse_sadb_routine(char *); + +#endif //CRYPTOLIB_SADB_ROUTINE_H diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index a1070845..f9809ef2 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -21,6 +21,7 @@ ivv-itc@lists.nasa.gov ** Includes */ #include "crypto.h" +#include "sadb_routine.h" #include "itc_aes128.h" #include "itc_gcm128.h" @@ -42,22 +43,21 @@ ivv-itc@lists.nasa.gov CFS_MODULE_DECLARE_LIB(crypto); #endif +static SadbRoutine sadb_routine = NULL; + /* ** Static Prototypes */ -// Initialization Functions -static int32 Crypto_SA_init(void); -static int32 Crypto_SA_config(void); // Assisting Functions static int32 Crypto_Get_tcPayloadLength(void); static int32 Crypto_Get_tmLength(int len); static void Crypto_TM_updatePDU(char* ingest, int len_ingest); static void Crypto_TM_updateOCF(void); +static void Crypto_Local_Config(void); +static void Crypto_Local_Init(void); //static int32 Crypto_gcm_err(int gcm_err); -static int32 Crypto_increment(uint8* num, int length); static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window); static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length); -static uint8 Crypto_Prep_Reply(char*, uint8); static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest); static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest); static void Crypto_Calc_CRC_Init_Table(void); @@ -67,16 +67,6 @@ static int32 Crypto_Key_OTAR(void); static int32 Crypto_Key_update(uint8 state); static int32 Crypto_Key_inventory(char*); static int32 Crypto_Key_verify(char*); -// Security Association Functions -static int32 Crypto_SA_stop(void); -static int32 Crypto_SA_start(void); -static int32 Crypto_SA_expire(void); -static int32 Crypto_SA_rekey(void); -static int32 Crypto_SA_status(char*); -static int32 Crypto_SA_create(void); -static int32 Crypto_SA_setARSN(void); -static int32 Crypto_SA_setARSNW(void); -static int32 Crypto_SA_delete(void); // Security Monitoring & Control Procedure static int32 Crypto_MC_ping(char* ingest); static int32 Crypto_MC_status(char* ingest); @@ -101,13 +91,12 @@ static int32 Crypto_PDU(char* ingest); ** Global Variables */ // Security -static SecurityAssociation_t sa[NUM_SA]; -static crypto_key_t ek_ring[NUM_KEYS]; +crypto_key_t ek_ring[NUM_KEYS]; //static crypto_key_t ak_ring[NUM_KEYS]; // Local Frames -static TC_t tc_frame; -static CCSDS_t sdls_frame; -static TM_t tm_frame; +TC_t tc_frame; +CCSDS_t sdls_frame; +TM_t tm_frame; // OCF static uint8 ocf = 0; static SDLS_FSR_t report; @@ -129,576 +118,12 @@ static uint16 crc16Table[256]; /* ** Initialization Functions */ -static int32 Crypto_SA_init(void) -// General security association initialization -{ - int32 status = OS_SUCCESS; - - for (int x = 0; x < NUM_SA; x++) - { - sa[x].ekid = x; - sa[x].akid = x; - sa[x].sa_state = SA_NONE; - sa[x].ecs_len = 0; - sa[x].ecs[0] = 0; - sa[x].ecs[1] = 0; - sa[x].ecs[2] = 0; - sa[x].ecs[3] = 0; - sa[x].iv_len = IV_SIZE; - sa[x].acs_len = 0; - sa[x].acs = 0; - sa[x].arc_len = 0; - sa[x].arc[0] = 5; - } - - // Initialize TM Frame - // TM Header - tm_frame.tm_header.tfvn = 0; // Shall be 00 for TM-/TC-SDLP - tm_frame.tm_header.scid = SCID & 0x3FF; - tm_frame.tm_header.vcid = 0; - tm_frame.tm_header.ocff = 1; - tm_frame.tm_header.mcfc = 1; - tm_frame.tm_header.vcfc = 1; - tm_frame.tm_header.tfsh = 0; - tm_frame.tm_header.sf = 0; - tm_frame.tm_header.pof = 0; // Shall be set to 0 - tm_frame.tm_header.slid = 3; // Shall be set to 11 - tm_frame.tm_header.fhp = 0; - // TM Security Header - tm_frame.tm_sec_header.spi = 0x0000; - for ( int x = 0; x < IV_SIZE; x++) - { // Initialization Vector - tm_frame.tm_sec_header.iv[x] = 0x00; - } - // TM Payload Data Unit - for ( int x = 0; x < TM_FRAME_DATA_SIZE; x++) - { // Zero TM PDU - tm_frame.tm_pdu[x] = 0x00; - } - // TM Security Trailer - for ( int x = 0; x < MAC_SIZE; x++) - { // Zero TM Message Authentication Code - tm_frame.tm_sec_trailer.mac[x] = 0x00; - } - for ( int x = 0; x < OCF_SIZE; x++) - { // Zero TM Operational Control Field - tm_frame.tm_sec_trailer.ocf[x] = 0x00; - } - tm_frame.tm_sec_trailer.fecf = 0xFECF; - - // Initialize CLCW - clcw.cwt = 0; // Control Word Type "0" - clcw.cvn = 0; // CLCW Version Number "00" - clcw.sf = 0; // Status Field - clcw.cie = 1; // COP In Effect - clcw.vci = 0; // Virtual Channel Identification - clcw.spare0 = 0; // Reserved Spare - clcw.nrfa = 0; // No RF Avaliable Flag - clcw.nbl = 0; // No Bit Lock Flag - clcw.lo = 0; // Lock-Out Flag - clcw.wait = 0; // Wait Flag - clcw.rt = 0; // Retransmit Flag - clcw.fbc = 0; // FARM-B Counter - clcw.spare1 = 0; // Reserved Spare - clcw.rv = 0; // Report Value - - // Initialize Frame Security Report - report.cwt = 1; // Control Word Type "0b1"" - report.vnum = 4; // FSR Version "0b100"" - report.af = 0; // Alarm Field - report.bsnf = 0; // Bad SN Flag - report.bmacf = 0; // Bad MAC Flag - report.ispif = 0; // Invalid SPI Flag - report.lspiu = 0; // Last SPI Used - report.snval = 0; // SN Value (LSB) - - return status; -} - -static int32 Crypto_SA_config(void) -// Initialize the mission specific security associations. -// Only need to initialize non-zero values. -{ - int32 status = OS_SUCCESS; - - // Master Keys - // 0 - 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F -> ACTIVE - ek_ring[0].value[0] = 0x00; - ek_ring[0].value[1] = 0x01; - ek_ring[0].value[2] = 0x02; - ek_ring[0].value[3] = 0x03; - ek_ring[0].value[4] = 0x04; - ek_ring[0].value[5] = 0x05; - ek_ring[0].value[6] = 0x06; - ek_ring[0].value[7] = 0x07; - ek_ring[0].value[8] = 0x08; - ek_ring[0].value[9] = 0x09; - ek_ring[0].value[10] = 0x0A; - ek_ring[0].value[11] = 0x0B; - ek_ring[0].value[12] = 0x0C; - ek_ring[0].value[13] = 0x0D; - ek_ring[0].value[14] = 0x0E; - ek_ring[0].value[15] = 0x0F; - ek_ring[0].value[16] = 0x00; - ek_ring[0].value[17] = 0x01; - ek_ring[0].value[18] = 0x02; - ek_ring[0].value[19] = 0x03; - ek_ring[0].value[20] = 0x04; - ek_ring[0].value[21] = 0x05; - ek_ring[0].value[22] = 0x06; - ek_ring[0].value[23] = 0x07; - ek_ring[0].value[24] = 0x08; - ek_ring[0].value[25] = 0x09; - ek_ring[0].value[26] = 0x0A; - ek_ring[0].value[27] = 0x0B; - ek_ring[0].value[28] = 0x0C; - ek_ring[0].value[29] = 0x0D; - ek_ring[0].value[30] = 0x0E; - ek_ring[0].value[31] = 0x0F; - ek_ring[0].key_state = KEY_ACTIVE; - // 1 - 101112131415161718191A1B1C1D1E1F101112131415161718191A1B1C1D1E1F -> ACTIVE - ek_ring[1].value[0] = 0x10; - ek_ring[1].value[1] = 0x11; - ek_ring[1].value[2] = 0x12; - ek_ring[1].value[3] = 0x13; - ek_ring[1].value[4] = 0x14; - ek_ring[1].value[5] = 0x15; - ek_ring[1].value[6] = 0x16; - ek_ring[1].value[7] = 0x17; - ek_ring[1].value[8] = 0x18; - ek_ring[1].value[9] = 0x19; - ek_ring[1].value[10] = 0x1A; - ek_ring[1].value[11] = 0x1B; - ek_ring[1].value[12] = 0x1C; - ek_ring[1].value[13] = 0x1D; - ek_ring[1].value[14] = 0x1E; - ek_ring[1].value[15] = 0x1F; - ek_ring[1].value[16] = 0x10; - ek_ring[1].value[17] = 0x11; - ek_ring[1].value[18] = 0x12; - ek_ring[1].value[19] = 0x13; - ek_ring[1].value[20] = 0x14; - ek_ring[1].value[21] = 0x15; - ek_ring[1].value[22] = 0x16; - ek_ring[1].value[23] = 0x17; - ek_ring[1].value[24] = 0x18; - ek_ring[1].value[25] = 0x19; - ek_ring[1].value[26] = 0x1A; - ek_ring[1].value[27] = 0x1B; - ek_ring[1].value[28] = 0x1C; - ek_ring[1].value[29] = 0x1D; - ek_ring[1].value[30] = 0x1E; - ek_ring[1].value[31] = 0x1F; - ek_ring[1].key_state = KEY_ACTIVE; - // 2 - 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F -> ACTIVE - ek_ring[2].value[0] = 0x20; - ek_ring[2].value[1] = 0x21; - ek_ring[2].value[2] = 0x22; - ek_ring[2].value[3] = 0x23; - ek_ring[2].value[4] = 0x24; - ek_ring[2].value[5] = 0x25; - ek_ring[2].value[6] = 0x26; - ek_ring[2].value[7] = 0x27; - ek_ring[2].value[8] = 0x28; - ek_ring[2].value[9] = 0x29; - ek_ring[2].value[10] = 0x2A; - ek_ring[2].value[11] = 0x2B; - ek_ring[2].value[12] = 0x2C; - ek_ring[2].value[13] = 0x2D; - ek_ring[2].value[14] = 0x2E; - ek_ring[2].value[15] = 0x2F; - ek_ring[2].value[16] = 0x20; - ek_ring[2].value[17] = 0x21; - ek_ring[2].value[18] = 0x22; - ek_ring[2].value[19] = 0x23; - ek_ring[2].value[20] = 0x24; - ek_ring[2].value[21] = 0x25; - ek_ring[2].value[22] = 0x26; - ek_ring[2].value[23] = 0x27; - ek_ring[2].value[24] = 0x28; - ek_ring[2].value[25] = 0x29; - ek_ring[2].value[26] = 0x2A; - ek_ring[2].value[27] = 0x2B; - ek_ring[2].value[28] = 0x2C; - ek_ring[2].value[29] = 0x2D; - ek_ring[2].value[30] = 0x2E; - ek_ring[2].value[31] = 0x2F; - ek_ring[2].key_state = KEY_ACTIVE; - - // Session Keys - // 128 - 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -> ACTIVE - ek_ring[128].value[0] = 0x01; - ek_ring[128].value[1] = 0x23; - ek_ring[128].value[2] = 0x45; - ek_ring[128].value[3] = 0x67; - ek_ring[128].value[4] = 0x89; - ek_ring[128].value[5] = 0xAB; - ek_ring[128].value[6] = 0xCD; - ek_ring[128].value[7] = 0xEF; - ek_ring[128].value[8] = 0x01; - ek_ring[128].value[9] = 0x23; - ek_ring[128].value[10] = 0x45; - ek_ring[128].value[11] = 0x67; - ek_ring[128].value[12] = 0x89; - ek_ring[128].value[13] = 0xAB; - ek_ring[128].value[14] = 0xCD; - ek_ring[128].value[15] = 0xEF; - ek_ring[128].value[16] = 0x01; - ek_ring[128].value[17] = 0x23; - ek_ring[128].value[18] = 0x45; - ek_ring[128].value[19] = 0x67; - ek_ring[128].value[20] = 0x89; - ek_ring[128].value[21] = 0xAB; - ek_ring[128].value[22] = 0xCD; - ek_ring[128].value[23] = 0xEF; - ek_ring[128].value[24] = 0x01; - ek_ring[128].value[25] = 0x23; - ek_ring[128].value[26] = 0x45; - ek_ring[128].value[27] = 0x67; - ek_ring[128].value[28] = 0x89; - ek_ring[128].value[29] = 0xAB; - ek_ring[128].value[30] = 0xCD; - ek_ring[128].value[31] = 0xEF; - ek_ring[128].key_state = KEY_ACTIVE; - // 129 - ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 -> ACTIVE - ek_ring[129].value[0] = 0xAB; - ek_ring[129].value[1] = 0xCD; - ek_ring[129].value[2] = 0xEF; - ek_ring[129].value[3] = 0x01; - ek_ring[129].value[4] = 0x23; - ek_ring[129].value[5] = 0x45; - ek_ring[129].value[6] = 0x67; - ek_ring[129].value[7] = 0x89; - ek_ring[129].value[8] = 0xAB; - ek_ring[129].value[9] = 0xCD; - ek_ring[129].value[10] = 0xEF; - ek_ring[129].value[11] = 0x01; - ek_ring[129].value[12] = 0x23; - ek_ring[129].value[13] = 0x45; - ek_ring[129].value[14] = 0x67; - ek_ring[129].value[15] = 0x89; - ek_ring[129].value[16] = 0xAB; - ek_ring[129].value[17] = 0xCD; - ek_ring[129].value[18] = 0xEF; - ek_ring[129].value[19] = 0x01; - ek_ring[129].value[20] = 0x23; - ek_ring[129].value[21] = 0x45; - ek_ring[129].value[22] = 0x67; - ek_ring[129].value[23] = 0x89; - ek_ring[129].value[24] = 0xAB; - ek_ring[129].value[25] = 0xCD; - ek_ring[129].value[26] = 0xEF; - ek_ring[129].value[27] = 0x01; - ek_ring[129].value[28] = 0x23; - ek_ring[129].value[29] = 0x45; - ek_ring[129].value[30] = 0x67; - ek_ring[129].value[31] = 0x89; - ek_ring[129].key_state = KEY_ACTIVE; - // 130 - FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210 -> ACTIVE - ek_ring[130].value[0] = 0xFE; - ek_ring[130].value[1] = 0xDC; - ek_ring[130].value[2] = 0xBA; - ek_ring[130].value[3] = 0x98; - ek_ring[130].value[4] = 0x76; - ek_ring[130].value[5] = 0x54; - ek_ring[130].value[6] = 0x32; - ek_ring[130].value[7] = 0x10; - ek_ring[130].value[8] = 0xFE; - ek_ring[130].value[9] = 0xDC; - ek_ring[130].value[10] = 0xBA; - ek_ring[130].value[11] = 0x98; - ek_ring[130].value[12] = 0x76; - ek_ring[130].value[13] = 0x54; - ek_ring[130].value[14] = 0x32; - ek_ring[130].value[15] = 0x10; - ek_ring[130].value[16] = 0xFE; - ek_ring[130].value[17] = 0xDC; - ek_ring[130].value[18] = 0xBA; - ek_ring[130].value[19] = 0x98; - ek_ring[130].value[20] = 0x76; - ek_ring[130].value[21] = 0x54; - ek_ring[130].value[22] = 0x32; - ek_ring[130].value[23] = 0x10; - ek_ring[130].value[24] = 0xFE; - ek_ring[130].value[25] = 0xDC; - ek_ring[130].value[26] = 0xBA; - ek_ring[130].value[27] = 0x98; - ek_ring[130].value[28] = 0x76; - ek_ring[130].value[29] = 0x54; - ek_ring[130].value[30] = 0x32; - ek_ring[130].value[31] = 0x10; - ek_ring[130].key_state = KEY_ACTIVE; - // 131 - 9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA -> ACTIVE - ek_ring[131].value[0] = 0x98; - ek_ring[131].value[1] = 0x76; - ek_ring[131].value[2] = 0x54; - ek_ring[131].value[3] = 0x32; - ek_ring[131].value[4] = 0x10; - ek_ring[131].value[5] = 0xFE; - ek_ring[131].value[6] = 0xDC; - ek_ring[131].value[7] = 0xBA; - ek_ring[131].value[8] = 0x98; - ek_ring[131].value[9] = 0x76; - ek_ring[131].value[10] = 0x54; - ek_ring[131].value[11] = 0x32; - ek_ring[131].value[12] = 0x10; - ek_ring[131].value[13] = 0xFE; - ek_ring[131].value[14] = 0xDC; - ek_ring[131].value[15] = 0xBA; - ek_ring[131].value[16] = 0x98; - ek_ring[131].value[17] = 0x76; - ek_ring[131].value[18] = 0x54; - ek_ring[131].value[19] = 0x32; - ek_ring[131].value[20] = 0x10; - ek_ring[131].value[21] = 0xFE; - ek_ring[131].value[22] = 0xDC; - ek_ring[131].value[23] = 0xBA; - ek_ring[131].value[24] = 0x98; - ek_ring[131].value[25] = 0x76; - ek_ring[131].value[26] = 0x54; - ek_ring[131].value[27] = 0x32; - ek_ring[131].value[28] = 0x10; - ek_ring[131].value[29] = 0xFE; - ek_ring[131].value[30] = 0xDC; - ek_ring[131].value[31] = 0xBA; - ek_ring[131].key_state = KEY_ACTIVE; - // 132 - 0123456789ABCDEFABCDEF01234567890123456789ABCDEFABCDEF0123456789 -> PRE_ACTIVATION - ek_ring[132].value[0] = 0x01; - ek_ring[132].value[1] = 0x23; - ek_ring[132].value[2] = 0x45; - ek_ring[132].value[3] = 0x67; - ek_ring[132].value[4] = 0x89; - ek_ring[132].value[5] = 0xAB; - ek_ring[132].value[6] = 0xCD; - ek_ring[132].value[7] = 0xEF; - ek_ring[132].value[8] = 0xAB; - ek_ring[132].value[9] = 0xCD; - ek_ring[132].value[10] = 0xEF; - ek_ring[132].value[11] = 0x01; - ek_ring[132].value[12] = 0x23; - ek_ring[132].value[13] = 0x45; - ek_ring[132].value[14] = 0x67; - ek_ring[132].value[15] = 0x89; - ek_ring[132].value[16] = 0x01; - ek_ring[132].value[17] = 0x23; - ek_ring[132].value[18] = 0x45; - ek_ring[132].value[19] = 0x67; - ek_ring[132].value[20] = 0x89; - ek_ring[132].value[21] = 0xAB; - ek_ring[132].value[22] = 0xCD; - ek_ring[132].value[23] = 0xEF; - ek_ring[132].value[24] = 0xAB; - ek_ring[132].value[25] = 0xCD; - ek_ring[132].value[26] = 0xEF; - ek_ring[132].value[27] = 0x01; - ek_ring[132].value[28] = 0x23; - ek_ring[132].value[29] = 0x45; - ek_ring[132].value[30] = 0x67; - ek_ring[132].value[31] = 0x89; - ek_ring[132].key_state = KEY_PREACTIVE; - // 133 - ABCDEF01234567890123456789ABCDEFABCDEF01234567890123456789ABCDEF -> ACTIVE - ek_ring[133].value[0] = 0xAB; - ek_ring[133].value[1] = 0xCD; - ek_ring[133].value[2] = 0xEF; - ek_ring[133].value[3] = 0x01; - ek_ring[133].value[4] = 0x23; - ek_ring[133].value[5] = 0x45; - ek_ring[133].value[6] = 0x67; - ek_ring[133].value[7] = 0x89; - ek_ring[133].value[8] = 0x01; - ek_ring[133].value[9] = 0x23; - ek_ring[133].value[10] = 0x45; - ek_ring[133].value[11] = 0x67; - ek_ring[133].value[12] = 0x89; - ek_ring[133].value[13] = 0xAB; - ek_ring[133].value[14] = 0xCD; - ek_ring[133].value[15] = 0xEF; - ek_ring[133].value[16] = 0xAB; - ek_ring[133].value[17] = 0xCD; - ek_ring[133].value[18] = 0xEF; - ek_ring[133].value[19] = 0x01; - ek_ring[133].value[20] = 0x23; - ek_ring[133].value[21] = 0x45; - ek_ring[133].value[22] = 0x67; - ek_ring[133].value[23] = 0x89; - ek_ring[133].value[24] = 0x01; - ek_ring[133].value[25] = 0x23; - ek_ring[133].value[26] = 0x45; - ek_ring[133].value[27] = 0x67; - ek_ring[133].value[28] = 0x89; - ek_ring[133].value[29] = 0xAB; - ek_ring[133].value[30] = 0xCD; - ek_ring[133].value[31] = 0xEF; - ek_ring[133].key_state = KEY_ACTIVE; - // 134 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE - ek_ring[134].value[0] = 0xAB; - ek_ring[134].value[1] = 0xCD; - ek_ring[134].value[2] = 0xEF; - ek_ring[134].value[3] = 0x01; - ek_ring[134].value[4] = 0x23; - ek_ring[134].value[5] = 0x45; - ek_ring[134].value[6] = 0x67; - ek_ring[134].value[7] = 0x89; - ek_ring[134].value[8] = 0xFE; - ek_ring[134].value[9] = 0xDC; - ek_ring[134].value[10] = 0xBA; - ek_ring[134].value[11] = 0x98; - ek_ring[134].value[12] = 0x76; - ek_ring[134].value[13] = 0x54; - ek_ring[134].value[14] = 0x32; - ek_ring[134].value[15] = 0x10; - ek_ring[134].value[16] = 0xAB; - ek_ring[134].value[17] = 0xCD; - ek_ring[134].value[18] = 0xEF; - ek_ring[134].value[19] = 0x01; - ek_ring[134].value[20] = 0x23; - ek_ring[134].value[21] = 0x45; - ek_ring[134].value[22] = 0x67; - ek_ring[134].value[23] = 0x89; - ek_ring[134].value[24] = 0xFE; - ek_ring[134].value[25] = 0xDC; - ek_ring[134].value[26] = 0xBA; - ek_ring[134].value[27] = 0x98; - ek_ring[134].value[28] = 0x76; - ek_ring[134].value[29] = 0x54; - ek_ring[134].value[30] = 0x32; - ek_ring[134].value[31] = 0x10; - ek_ring[134].key_state = KEY_DEACTIVATED; - - // Security Associations - // SA 1 - CLEAR MODE - sa[1].sa_state = SA_OPERATIONAL; - sa[1].est = 0; - sa[1].ast = 0; - sa[1].arc_len = 1; - sa[1].arcw_len = 1; - sa[1].arcw[0] = 5; - sa[1].gvcid_tc_blk[0].tfvn = 0; - sa[1].gvcid_tc_blk[0].scid = SCID & 0x3FF; - sa[1].gvcid_tc_blk[0].vcid = 0; - sa[1].gvcid_tc_blk[0].mapid = TYPE_TC; - sa[1].gvcid_tc_blk[1].tfvn = 0; - sa[1].gvcid_tc_blk[1].scid = SCID & 0x3FF; - sa[1].gvcid_tc_blk[1].vcid = 1; - sa[1].gvcid_tc_blk[1].mapid = TYPE_TC; - // SA 2 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 128 - sa[2].ekid = 128; - sa[2].sa_state = SA_KEYED; - sa[2].est = 1; - sa[2].ast = 1; - sa[2].shivf_len = 12; - sa[2].iv_len = IV_SIZE; - sa[2].iv[IV_SIZE-1] = 0; - sa[2].abm_len = 0x14; // 20 - for (int i = 0; i < sa[2].abm_len; i++) - { // Zero AAD bit mask - sa[2].abm[i] = 0x00; - } - sa[2].arcw_len = 1; - sa[2].arcw[0] = 5; - sa[2].arc_len = (sa[2].arcw[0] * 2) + 1; - // SA 3 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 129 - sa[3].ekid = 129; - sa[3].sa_state = SA_KEYED; - sa[3].est = 1; - sa[3].ast = 1; - sa[3].shivf_len = 12; - sa[3].iv_len = IV_SIZE; - sa[3].iv[IV_SIZE-1] = 0; - sa[3].abm_len = 0x14; // 20 - for (int i = 0; i < sa[3].abm_len; i++) - { // Zero AAD bit mask - sa[3].abm[i] = 0x00; - } - sa[3].arcw_len = 1; - sa[3].arcw[0] = 5; - sa[3].arc_len = (sa[3].arcw[0] * 2) + 1; - // SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 - sa[4].ekid = 130; - sa[4].sa_state = SA_KEYED; - sa[4].est = 1; - sa[4].ast = 1; - sa[4].shivf_len = 12; - sa[4].iv_len = IV_SIZE; - sa[4].iv[IV_SIZE-1] = 0; - sa[4].abm_len = 0x14; // 20 - for (int i = 0; i < sa[4].abm_len; i++) - { // Zero AAD bit mask - sa[4].abm[i] = 0x00; - } - sa[4].arcw_len = 1; - sa[4].arcw[0] = 5; - sa[4].arc_len = (sa[4].arcw[0] * 2) + 1; - sa[4].gvcid_tc_blk[0].tfvn = 0; - sa[4].gvcid_tc_blk[0].scid = SCID & 0x3FF; - sa[4].gvcid_tc_blk[0].vcid = 0; - sa[4].gvcid_tc_blk[0].mapid = TYPE_TC; - sa[4].gvcid_tc_blk[1].tfvn = 0; - sa[4].gvcid_tc_blk[1].scid = SCID & 0x3FF; - sa[4].gvcid_tc_blk[1].vcid = 1; - sa[4].gvcid_tc_blk[1].mapid = TYPE_TC; - // SA 5 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 131 - sa[5].ekid = 131; - sa[5].sa_state = SA_KEYED; - sa[5].est = 1; - sa[5].ast = 1; - sa[5].shivf_len = 12; - sa[5].iv_len = IV_SIZE; - sa[5].iv[IV_SIZE-1] = 0; - sa[5].abm_len = 0x14; // 20 - for (int i = 0; i < sa[5].abm_len; i++) - { // Zero AAD bit mask - sa[5].abm[i] = 0x00; - } - sa[5].arcw_len = 1; - sa[5].arcw[0] = 5; - sa[5].arc_len = (sa[5].arcw[0] * 2) + 1; - // SA 6 - UNKEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: - - sa[6].sa_state = SA_UNKEYED; - sa[6].est = 1; - sa[6].ast = 1; - sa[6].shivf_len = 12; - sa[6].iv_len = IV_SIZE; - sa[6].iv[IV_SIZE-1] = 0; - sa[6].abm_len = 0x14; // 20 - for (int i = 0; i < sa[6].abm_len; i++) - { // Zero AAD bit mask - sa[6].abm[i] = 0x00; - } - sa[6].arcw_len = 1; - sa[6].arcw[0] = 5; - sa[6].arc_len = (sa[6].arcw[0] * 2) + 1; - //itc_gcm128_init(&(sa[6].gcm_ctx), (unsigned char *)&(ek_ring[sa[6].ekid])); - - // Initial TM configuration - tm_frame.tm_sec_header.spi = 1; - - // Initialize Log - log_summary.num_se = 2; - log_summary.rs = LOG_SIZE; - // Add a two messages to the log - log_summary.rs--; - log.blk[log_count].emt = STARTUP; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - log_summary.rs--; - log.blk[log_count].emt = STARTUP; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - - return status; -} - int32 Crypto_Init(void) { int32 status = OS_SUCCESS; + sadb_routine = get_sadb_routine_inmemory(); + // Initialize libgcrypt if (!gcry_check_version(GCRYPT_VERSION)) { @@ -712,8 +137,11 @@ int32 Crypto_Init(void) gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); // Init Security Associations - status = Crypto_SA_init(); - status = Crypto_SA_config(); + status = sadb_routine->sadb_init(); + status = sadb_routine->sadb_config(); + + Crypto_Local_Init(); + Crypto_Local_Config(); // TODO - Add error checking @@ -730,6 +158,97 @@ int32 Crypto_Init(void) return status; } +static void Crypto_Local_Config(void) +{ + // Initial TM configuration + tm_frame.tm_sec_header.spi = 1; + + // Initialize Log + log_summary.num_se = 2; + log_summary.rs = LOG_SIZE; + // Add a two messages to the log + log_summary.rs--; + log.blk[log_count].emt = STARTUP; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + log_summary.rs--; + log.blk[log_count].emt = STARTUP; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; +} + +static void Crypto_Local_Init(void) +{ + + // Initialize TM Frame + // TM Header + tm_frame.tm_header.tfvn = 0; // Shall be 00 for TM-/TC-SDLP + tm_frame.tm_header.scid = SCID & 0x3FF; + tm_frame.tm_header.vcid = 0; + tm_frame.tm_header.ocff = 1; + tm_frame.tm_header.mcfc = 1; + tm_frame.tm_header.vcfc = 1; + tm_frame.tm_header.tfsh = 0; + tm_frame.tm_header.sf = 0; + tm_frame.tm_header.pof = 0; // Shall be set to 0 + tm_frame.tm_header.slid = 3; // Shall be set to 11 + tm_frame.tm_header.fhp = 0; + // TM Security Header + tm_frame.tm_sec_header.spi = 0x0000; + for ( int x = 0; x < IV_SIZE; x++) + { // Initialization Vector + tm_frame.tm_sec_header.iv[x] = 0x00; + } + // TM Payload Data Unit + for ( int x = 0; x < TM_FRAME_DATA_SIZE; x++) + { // Zero TM PDU + tm_frame.tm_pdu[x] = 0x00; + } + // TM Security Trailer + for ( int x = 0; x < MAC_SIZE; x++) + { // Zero TM Message Authentication Code + tm_frame.tm_sec_trailer.mac[x] = 0x00; + } + for ( int x = 0; x < OCF_SIZE; x++) + { // Zero TM Operational Control Field + tm_frame.tm_sec_trailer.ocf[x] = 0x00; + } + tm_frame.tm_sec_trailer.fecf = 0xFECF; + + // Initialize CLCW + clcw.cwt = 0; // Control Word Type "0" + clcw.cvn = 0; // CLCW Version Number "00" + clcw.sf = 0; // Status Field + clcw.cie = 1; // COP In Effect + clcw.vci = 0; // Virtual Channel Identification + clcw.spare0 = 0; // Reserved Spare + clcw.nrfa = 0; // No RF Avaliable Flag + clcw.nbl = 0; // No Bit Lock Flag + clcw.lo = 0; // Lock-Out Flag + clcw.wait = 0; // Wait Flag + clcw.rt = 0; // Retransmit Flag + clcw.fbc = 0; // FARM-B Counter + clcw.spare1 = 0; // Reserved Spare + clcw.rv = 0; // Report Value + + // Initialize Frame Security Report + report.cwt = 1; // Control Word Type "0b1"" + report.vnum = 4; // FSR Version "0b100"" + report.af = 0; // Alarm Field + report.bsnf = 0; // Bad SN Flag + report.bmacf = 0; // Bad MAC Flag + report.ispif = 0; // Invalid SPI Flag + report.lspiu = 0; // Last SPI Used + report.snval = 0; // SN Value (LSB) + +} + static void Crypto_Calc_CRC_Init_Table(void) { uint16 val; @@ -791,8 +310,14 @@ static void Crypto_TM_updatePDU(char* ingest, int len_ingest) { // Copy ingest to PDU int x = 0; int fill_size = 0; - - if ((sa[tm_frame.tm_sec_header.spi].est == 1) && (sa[tm_frame.tm_sec_header.spi].ast == 1)) + SecurityAssociation_t* sa_ptr; + + if(sadb_routine->sadb_get_sa_from_spi(tm_frame.tm_sec_header.spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return; //Error -- unable to get SA from SPI. + } + + if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) { fill_size = 1129 - MAC_SIZE - IV_SIZE + 2; // +2 for padding bytes } @@ -950,7 +475,7 @@ static void Crypto_TM_updateOCF(void) } } -static int32 Crypto_increment(uint8 *num, int length) +int32 Crypto_increment(uint8 *num, int length) { int i; /* go from right (least significant) to left (most signifcant) */ @@ -1017,7 +542,7 @@ static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int lengt return status; } -static uint8 Crypto_Prep_Reply(char* ingest, uint8 appID) +uint8 Crypto_Prep_Reply(char* ingest, uint8 appID) // Assumes that both the pkt_length and pdu_len are set properly { uint8 count = 0; @@ -1567,510 +1092,6 @@ static int32 Crypto_Key_verify(char* ingest) return count; } - -/* -** Security Association Management Services -*/ -static int32 Crypto_SA_start(void) -{ - // Local variables - uint8 count = 0; - uint16 spi = 0x0000; - crypto_gvcid_t gvcid; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - - // Overwrite last PID - sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; - - // Check SPI exists and in 'Keyed' state - if (spi < NUM_SA) - { - if (sa[spi].sa_state == SA_KEYED) - { - count = 2; - - for(int x = 0; x <= ((sdls_frame.pdu.pdu_len - 2) / 4); x++) - { // Read in GVCID - gvcid.tfvn = (sdls_frame.pdu.data[count] >> 4); - gvcid.scid = (sdls_frame.pdu.data[count] << 12) | - (sdls_frame.pdu.data[count + 1] << 4) | - (sdls_frame.pdu.data[count + 2] >> 4); - gvcid.vcid = (sdls_frame.pdu.data[count + 2] << 4) | - (sdls_frame.pdu.data[count + 3] && 0x3F); - gvcid.mapid = (sdls_frame.pdu.data[count + 3]); - - // TC - if (gvcid.vcid != tc_frame.tc_header.vcid) - { // Clear all GVCIDs for provided SPI - if (gvcid.mapid == TYPE_TC) - { - for (int i = 0; i < NUM_GVCID; i++) - { // TC - sa[spi].gvcid_tc_blk[x].tfvn = 0; - sa[spi].gvcid_tc_blk[x].scid = 0; - sa[spi].gvcid_tc_blk[x].vcid = 0; - sa[spi].gvcid_tc_blk[x].mapid = 0; - } - } - // Write channel to SA - if (gvcid.mapid != TYPE_MAP) - { // TC - sa[spi].gvcid_tc_blk[gvcid.vcid].tfvn = gvcid.tfvn; - sa[spi].gvcid_tc_blk[gvcid.vcid].scid = gvcid.scid; - sa[spi].gvcid_tc_blk[gvcid.vcid].mapid = gvcid.mapid; - } - else - { - // TODO: Handle TYPE_MAP - } - } - // TM - if (gvcid.vcid != tm_frame.tm_header.vcid) - { // Clear all GVCIDs for provided SPI - if (gvcid.mapid == TYPE_TM) - { - for (int i = 0; i < NUM_GVCID; i++) - { // TM - sa[spi].gvcid_tm_blk[x].tfvn = 0; - sa[spi].gvcid_tm_blk[x].scid = 0; - sa[spi].gvcid_tm_blk[x].vcid = 0; - sa[spi].gvcid_tm_blk[x].mapid = 0; - } - } - // Write channel to SA - if (gvcid.mapid != TYPE_MAP) - { // TM - sa[spi].gvcid_tm_blk[gvcid.vcid].tfvn = gvcid.tfvn; - sa[spi].gvcid_tm_blk[gvcid.vcid].scid = gvcid.scid; - sa[spi].gvcid_tm_blk[gvcid.vcid].vcid = gvcid.vcid; - sa[spi].gvcid_tm_blk[gvcid.vcid].mapid = gvcid.mapid; - } - else - { - // TODO: Handle TYPE_MAP - } - } - - #ifdef PDU_DEBUG - OS_printf("SPI %d changed to OPERATIONAL state. \n", spi); - switch (gvcid.mapid) - { - case TYPE_TC: - OS_printf("Type TC, "); - break; - case TYPE_MAP: - OS_printf("Type MAP, "); - break; - case TYPE_TM: - OS_printf("Type TM, "); - break; - default: - OS_printf("Type Unknown, "); - break; - } - #endif - - // Change to operational state - sa[spi].sa_state = SA_OPERATIONAL; - } - } - else - { - OS_printf(KRED "ERROR: SPI %d is not in the KEYED state.\n" RESET, spi); - } - } - else - { - OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); - } - - #ifdef DEBUG - OS_printf("\t spi = %d \n", spi); - #endif - - return OS_SUCCESS; -} - -static int32 Crypto_SA_stop(void) -{ - // Local variables - uint16 spi = 0x0000; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - OS_printf("spi = %d \n", spi); - - // Overwrite last PID - sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; - - // Check SPI exists and in 'Active' state - if (spi < NUM_SA) - { - if (sa[spi].sa_state == SA_OPERATIONAL) - { - // Remove all GVC/GMAP IDs - for (int x = 0; x < NUM_GVCID; x++) - { // TC - sa[spi].gvcid_tc_blk[x].tfvn = 0; - sa[spi].gvcid_tc_blk[x].scid = 0; - sa[spi].gvcid_tc_blk[x].vcid = 0; - sa[spi].gvcid_tc_blk[x].mapid = 0; - // TM - sa[spi].gvcid_tm_blk[x].tfvn = 0; - sa[spi].gvcid_tm_blk[x].scid = 0; - sa[spi].gvcid_tm_blk[x].vcid = 0; - sa[spi].gvcid_tm_blk[x].mapid = 0; - } - - // Change to operational state - sa[spi].sa_state = SA_KEYED; - #ifdef PDU_DEBUG - OS_printf("SPI %d changed to KEYED state. \n", spi); - #endif - } - else - { - OS_printf(KRED "ERROR: SPI %d is not in the OPERATIONAL state.\n" RESET, spi); - } - } - else - { - OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); - } - - #ifdef DEBUG - OS_printf("\t spi = %d \n", spi); - #endif - - return OS_SUCCESS; -} - -static int32 Crypto_SA_rekey(void) -{ - // Local variables - uint16 spi = 0x0000; - int count = 0; - int x = 0; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[count] << 8) | (uint8)sdls_frame.pdu.data[count+1]; - count = count + 2; - - // Overwrite last PID - sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; - - // Check SPI exists and in 'Unkeyed' state - if (spi < NUM_SA) - { - if (sa[spi].sa_state == SA_UNKEYED) - { // Encryption Key - sa[spi].ekid = ((uint8)sdls_frame.pdu.data[count] << 8) | (uint8)sdls_frame.pdu.data[count+1]; - count = count + 2; - - // Authentication Key - //sa[spi].akid = ((uint8)sdls_frame.pdu.data[count] << 8) | (uint8)sdls_frame.pdu.data[count+1]; - //count = count + 2; - - // Anti-Replay Counter - #ifdef PDU_DEBUG - OS_printf("SPI %d IV updated to: 0x", spi); - #endif - if (sa[spi].iv_len > 0) - { // Set IV - authenticated encryption - for (x = count; x < (sa[spi].iv_len + count); x++) - { - // TODO: Uncomment once fixed in ESA implementation - // TODO: Assuming this was fixed... - sa[spi].iv[x - count] = (uint8) sdls_frame.pdu.data[x]; - #ifdef PDU_DEBUG - OS_printf("%02x", sdls_frame.pdu.data[x]); - #endif - } - } - else - { // Set SN - // TODO - } - #ifdef PDU_DEBUG - OS_printf("\n"); - #endif - - // Change to keyed state - sa[spi].sa_state = SA_KEYED; - #ifdef PDU_DEBUG - OS_printf("SPI %d changed to KEYED state with encrypted Key ID %d. \n", spi, sa[spi].ekid); - #endif - } - else - { - OS_printf(KRED "ERROR: SPI %d is not in the UNKEYED state.\n" RESET, spi); - } - } - else - { - OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); - } - - #ifdef DEBUG - OS_printf("\t spi = %d \n", spi); - OS_printf("\t ekid = %d \n", sa[spi].ekid); - //OS_printf("\t akid = %d \n", sa[spi].akid); - #endif - - return OS_SUCCESS; -} - -static int32 Crypto_SA_expire(void) -{ - // Local variables - uint16 spi = 0x0000; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - OS_printf("spi = %d \n", spi); - - // Overwrite last PID - sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; - - // Check SPI exists and in 'Keyed' state - if (spi < NUM_SA) - { - if (sa[spi].sa_state == SA_KEYED) - { // Change to 'Unkeyed' state - sa[spi].sa_state = SA_UNKEYED; - #ifdef PDU_DEBUG - OS_printf("SPI %d changed to UNKEYED state. \n", spi); - #endif - } - else - { - OS_printf(KRED "ERROR: SPI %d is not in the KEYED state.\n" RESET, spi); - } - } - else - { - OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); - } - - return OS_SUCCESS; -} - -static int32 Crypto_SA_create(void) -{ - // Local variables - uint8 count = 6; - uint16 spi = 0x0000; - - // Read sdls_frame.pdu.data - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - OS_printf("spi = %d \n", spi); - - // Overwrite last PID - sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; - - // Write SA Configuration - sa[spi].est = ((uint8)sdls_frame.pdu.data[2] & 0x80) >> 7; - sa[spi].ast = ((uint8)sdls_frame.pdu.data[2] & 0x40) >> 6; - sa[spi].shivf_len = ((uint8)sdls_frame.pdu.data[2] & 0x3F); - sa[spi].shsnf_len = ((uint8)sdls_frame.pdu.data[3] & 0xFC) >> 2; - sa[spi].shplf_len = ((uint8)sdls_frame.pdu.data[3] & 0x03); - sa[spi].stmacf_len = ((uint8)sdls_frame.pdu.data[4]); - sa[spi].ecs_len = ((uint8)sdls_frame.pdu.data[5]); - for (int x = 0; x < sa[spi].ecs_len; x++) - { - sa[spi].ecs[x] = ((uint8)sdls_frame.pdu.data[count++]); - } - sa[spi].iv_len = ((uint8)sdls_frame.pdu.data[count++]); - for (int x = 0; x < sa[spi].iv_len; x++) - { - sa[spi].iv[x] = ((uint8)sdls_frame.pdu.data[count++]); - } - sa[spi].acs_len = ((uint8)sdls_frame.pdu.data[count++]); - for (int x = 0; x < sa[spi].acs_len; x++) - { - sa[spi].acs = ((uint8)sdls_frame.pdu.data[count++]); - } - sa[spi].abm_len = (uint8)((sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1])); - count = count + 2; - for (int x = 0; x < sa[spi].abm_len; x++) - { - sa[spi].abm[x] = ((uint8)sdls_frame.pdu.data[count++]); - } - sa[spi].arc_len = ((uint8)sdls_frame.pdu.data[count++]); - for (int x = 0; x < sa[spi].arc_len; x++) - { - sa[spi].arc[x] = ((uint8)sdls_frame.pdu.data[count++]); - } - sa[spi].arcw_len = ((uint8)sdls_frame.pdu.data[count++]); - for (int x = 0; x < sa[spi].arcw_len; x++) - { - sa[spi].arcw[x] = ((uint8)sdls_frame.pdu.data[count++]); - } - - // TODO: Checks for valid data - - // Set state to unkeyed - sa[spi].sa_state = SA_UNKEYED; - - #ifdef PDU_DEBUG - Crypto_saPrint(&sa[spi]); - #endif - - return OS_SUCCESS; -} - -static int32 Crypto_SA_delete(void) -{ - // Local variables - uint16 spi = 0x0000; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - OS_printf("spi = %d \n", spi); - - // Overwrite last PID - sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; - - // Check SPI exists and in 'Unkeyed' state - if (spi < NUM_SA) - { - if (sa[spi].sa_state == SA_UNKEYED) - { // Change to 'None' state - sa[spi].sa_state = SA_NONE; - #ifdef PDU_DEBUG - OS_printf("SPI %d changed to NONE state. \n", spi); - #endif - - // TODO: Zero entire SA - } - else - { - OS_printf(KRED "ERROR: SPI %d is not in the UNKEYED state.\n" RESET, spi); - } - } - else - { - OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); - } - - return OS_SUCCESS; -} - -static int32 Crypto_SA_setARSN(void) -{ - // Local variables - uint16 spi = 0x0000; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - OS_printf("spi = %d \n", spi); - - // TODO: Check SA type (authenticated, encrypted, both) and set appropriately - // TODO: Add more checks on bounds - - // Check SPI exists - if (spi < NUM_SA) - { - #ifdef PDU_DEBUG - OS_printf("SPI %d IV updated to: 0x", spi); - #endif - if (sa[spi].iv_len > 0) - { // Set IV - authenticated encryption - for (int x = 0; x < IV_SIZE; x++) - { - sa[spi].iv[x] = (uint8) sdls_frame.pdu.data[x + 2]; - #ifdef PDU_DEBUG - OS_printf("%02x", sa[spi].iv[x]); - #endif - } - Crypto_increment((uint8*)sa[spi].iv, IV_SIZE); - } - else - { // Set SN - // TODO - } - #ifdef PDU_DEBUG - OS_printf("\n"); - #endif - } - else - { - OS_printf("Crypto_SA_setARSN ERROR: SPI %d does not exist.\n", spi); - } - - return OS_SUCCESS; -} - -static int32 Crypto_SA_setARSNW(void) -{ - // Local variables - uint16 spi = 0x0000; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - OS_printf("spi = %d \n", spi); - - // Check SPI exists - if (spi < NUM_SA) - { - sa[spi].arcw_len = (uint8) sdls_frame.pdu.data[2]; - - // Check for out of bounds - if (sa[spi].arcw_len > (ARC_SIZE)) - { - sa[spi].arcw_len = ARC_SIZE; - } - - for(int x = 0; x < sa[spi].arcw_len; x++) - { - sa[spi].arcw[x] = (uint8) sdls_frame.pdu.data[x+3]; - } - } - else - { - OS_printf("Crypto_SA_setARSNW ERROR: SPI %d does not exist.\n", spi); - } - - return OS_SUCCESS; -} - -static int32 Crypto_SA_status(char* ingest) -{ - // Local variables - int count = 0; - uint16 spi = 0x0000; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - OS_printf("spi = %d \n", spi); - - // Check SPI exists - if (spi < NUM_SA) - { - // Prepare for Reply - sdls_frame.pdu.pdu_len = 3; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - // PDU - ingest[count++] = (spi & 0xFF00) >> 8; - ingest[count++] = (spi & 0x00FF); - ingest[count++] = sa[spi].lpid; - } - else - { - OS_printf("Crypto_SA_status ERROR: SPI %d does not exist.\n", spi); - } - - #ifdef SA_DEBUG - Crypto_saPrint(&sa[spi]); - #endif - - return count; -} - - /* ** Security Association Monitoring and Control */ @@ -2196,6 +1217,7 @@ static int32 Crypto_SA_readARSN(char* ingest) { uint8 count = 0; uint16 spi = 0x0000; + SecurityAssociation_t* sa_ptr; // Read ingest spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; @@ -2209,21 +1231,28 @@ static int32 Crypto_SA_readARSN(char* ingest) ingest[count++] = (spi & 0xFF00) >> 8; ingest[count++] = (spi & 0x00FF); - if (sa[spi].iv_len > 0) + + if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } + + + if (sa_ptr->iv_len > 0) { // Set IV - authenticated encryption - for (int x = 0; x < sa[spi].iv_len - 1; x++) + for (int x = 0; x < sa_ptr->iv_len - 1; x++) { - ingest[count++] = sa[spi].iv[x]; + ingest[count++] = sa_ptr->iv[x]; } // TODO: Do we need this? - if (sa[spi].iv[IV_SIZE - 1] > 0) + if (sa_ptr->iv[IV_SIZE - 1] > 0) { // Adjust to report last received, not expected - ingest[count++] = sa[spi].iv[IV_SIZE - 1] - 1; + ingest[count++] = sa_ptr->iv[IV_SIZE - 1] - 1; } else { - ingest[count++] = sa[spi].iv[IV_SIZE - 1]; + ingest[count++] = sa_ptr->iv[IV_SIZE - 1]; } } else @@ -2233,12 +1262,12 @@ static int32 Crypto_SA_readARSN(char* ingest) #ifdef PDU_DEBUG OS_printf("spi = %d \n", spi); - if (sa[spi].iv_len > 0) + if (sa_ptr->iv_len > 0) { OS_printf("ARSN = 0x"); - for (int x = 0; x < sa[spi].iv_len; x++) + for (int x = 0; x < sa_ptr->iv_len; x++) { - OS_printf("%02x", sa[spi].iv[x]); + OS_printf("%02x", sa_ptr->iv[x]); } OS_printf("\n"); } @@ -2361,14 +1390,20 @@ static int32 Crypto_User_ModifyActiveTM(void) static int32 Crypto_User_ModifyVCID(void) { tm_frame.tm_header.vcid = (uint8)sdls_frame.pdu.data[0]; + SecurityAssociation_t* sa_ptr; for (int i = 0; i < NUM_GVCID; i++) { + if(sadb_routine->sadb_get_sa_from_spi(i,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } for (int j = 0; j < NUM_SA; j++) { - if (sa[i].gvcid_tm_blk[j].mapid == TYPE_TM) + + if (sa_ptr->gvcid_tm_blk[j].mapid == TYPE_TM) { - if (sa[i].gvcid_tm_blk[j].vcid == tm_frame.tm_header.vcid) + if (sa_ptr->gvcid_tm_blk[j].vcid == tm_frame.tm_header.vcid) { tm_frame.tm_sec_header.spi = i; OS_printf("TM Frame SPI changed to %d \n",i); @@ -2447,49 +1482,49 @@ static int32 Crypto_PDU(char* ingest) #ifdef PDU_DEBUG OS_printf(KGRN "SA Create\n" RESET); #endif - status = Crypto_SA_create(); + status = sadb_routine->sadb_sa_create(); break; case PID_DELETE_SA: #ifdef PDU_DEBUG OS_printf(KGRN "SA Delete\n" RESET); #endif - status = Crypto_SA_delete(); + status = sadb_routine->sadb_sa_delete(); break; case PID_SET_ARSNW: #ifdef PDU_DEBUG OS_printf(KGRN "SA setARSNW\n" RESET); #endif - status = Crypto_SA_setARSNW(); + status = sadb_routine->sadb_sa_setARSNW(); break; case PID_REKEY_SA: #ifdef PDU_DEBUG OS_printf(KGRN "SA Rekey\n" RESET); #endif - status = Crypto_SA_rekey(); + status = sadb_routine->sadb_sa_rekey(); break; case PID_EXPIRE_SA: #ifdef PDU_DEBUG OS_printf(KGRN "SA Expire\n" RESET); #endif - status = Crypto_SA_expire(); + status = sadb_routine->sadb_sa_expire(); break; case PID_SET_ARSN: #ifdef PDU_DEBUG OS_printf(KGRN "SA SetARSN\n" RESET); #endif - status = Crypto_SA_setARSN(); + status = sadb_routine->sadb_sa_setARSN(); break; case PID_START_SA: #ifdef PDU_DEBUG OS_printf(KGRN "SA Start\n" RESET); #endif - status = Crypto_SA_start(); + status = sadb_routine->sadb_sa_start(); break; case PID_STOP_SA: #ifdef PDU_DEBUG OS_printf(KGRN "SA Stop\n" RESET); #endif - status = Crypto_SA_stop(); + status = sadb_routine->sadb_sa_stop(); break; case PID_READ_ARSN: #ifdef PDU_DEBUG @@ -2501,7 +1536,7 @@ static int32 Crypto_PDU(char* ingest) #ifdef PDU_DEBUG OS_printf(KGRN "SA Status\n" RESET); #endif - status = Crypto_SA_status(ingest); + status = sadb_routine->sadb_sa_status(ingest); break; default: OS_printf(KRED "Error: Crypto_PDU failed interpreting SA Procedure Identification Field! \n" RESET); @@ -2697,6 +1732,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) int y = 0; gcry_cipher_hd_t tmp_hd; gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + SecurityAssociation_t* sa_ptr = NULL; #ifdef DEBUG OS_printf(KYEL "\n----- Crypto_TC_ProcessSecurity START -----\n" RESET); @@ -2759,7 +1795,14 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) } if (status == OS_SUCCESS) { - if (sa[report.lspiu].gvcid_tc_blk[tc_frame.tc_header.vcid].mapid != TYPE_TC) + if(sadb_routine->sadb_get_sa_from_spi(report.lspiu,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + status = OS_ERROR; //Error -- unable to get SA from SPI. + } + } + if (status == OS_SUCCESS) + { + if (sa_ptr->gvcid_tc_blk[tc_frame.tc_header.vcid].mapid != TYPE_TC) { OS_printf(KRED "Error: SA invalid type! \n" RESET); status = OS_ERROR; @@ -2776,8 +1819,8 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) //} if (status == OS_SUCCESS) { - if (sa[report.lspiu].sa_state != SA_OPERATIONAL) - { + if (sa_ptr->sa_state != SA_OPERATIONAL) + { OS_printf(KRED "Error: SA state not operational! \n" RESET); status = OS_ERROR; } @@ -2800,10 +1843,14 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) return status; } } - + if(sadb_routine->sadb_get_sa_from_spi(tc_frame.tc_sec_header.spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + status = OS_ERROR; //Error -- unable to get SA from SPI. + return status; + } // Determine mode via SPI - if ((sa[tc_frame.tc_sec_header.spi].est == 1) && - (sa[tc_frame.tc_sec_header.spi].ast == 1)) + if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) { // Authenticated Encryption #ifdef DEBUG OS_printf(KBLU "ENCRYPTED TC Received!\n" RESET); @@ -2822,12 +1869,12 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) #ifdef DEBUG OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", IV_SIZE-1, tc_frame.tc_sec_header.iv[IV_SIZE-1]); - OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_frame.tc_sec_header.spi, IV_SIZE-1, sa[tc_frame.tc_sec_header.spi].iv[IV_SIZE-1]); + OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_frame.tc_sec_header.spi, IV_SIZE-1, sa_ptr->iv[IV_SIZE-1]); #endif // Check IV is in ARCW - if ( Crypto_window(tc_frame.tc_sec_header.iv, sa[tc_frame.tc_sec_header.spi].iv, IV_SIZE, - sa[tc_frame.tc_sec_header.spi].arcw[sa[tc_frame.tc_sec_header.spi].arcw_len-1]) != OS_SUCCESS ) + if ( Crypto_window(tc_frame.tc_sec_header.iv, sa_ptr->iv, IV_SIZE, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) { report.af = 1; report.bsnf = 1; @@ -2850,7 +1897,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) } else { - if ( Crypto_compare_less_equal(tc_frame.tc_sec_header.iv, sa[tc_frame.tc_sec_header.spi].iv, IV_SIZE) == OS_SUCCESS ) + if ( Crypto_compare_less_equal(tc_frame.tc_sec_header.iv, sa_ptr->iv, IV_SIZE) == OS_SUCCESS ) { // Replay - IV value lower than expected report.af = 1; report.bsnf = 1; @@ -2875,7 +1922,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) { // Adjust expected IV to acceptable received value for (int i = 0; i < (IV_SIZE); i++) { - sa[tc_frame.tc_sec_header.spi].iv[i] = tc_frame.tc_sec_header.iv[i]; + sa_ptr->iv[i] = tc_frame.tc_sec_header.iv[i]; } } } @@ -2929,16 +1976,16 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) return status; } #ifdef DEBUG - OS_printf("Key ID = %d, 0x", sa[tc_frame.tc_sec_header.spi].ekid); + OS_printf("Key ID = %d, 0x", sa_ptr->ekid); for(int y = 0; y < KEY_SIZE; y++) { - OS_printf("%02x", ek_ring[sa[tc_frame.tc_sec_header.spi].ekid].value[y]); + OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); } OS_printf("\n"); #endif gcry_error = gcry_cipher_setkey( tmp_hd, - &(ek_ring[sa[tc_frame.tc_sec_header.spi].ekid].value[0]), + &(ek_ring[sa_ptr->ekid].value[0]), KEY_SIZE ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -2949,8 +1996,8 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) } gcry_error = gcry_cipher_setiv( tmp_hd, - &(sa[tc_frame.tc_sec_header.spi].iv[0]), - sa[tc_frame.tc_sec_header.spi].iv_len + &(sa_ptr->iv[0]), + sa_ptr->iv_len ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { @@ -2962,9 +2009,9 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) OS_printf("AAD = 0x"); #endif // Prepare additional authenticated data (AAD) - for (y = 0; y < sa[tc_frame.tc_sec_header.spi].abm_len; y++) + for (y = 0; y < sa_ptr->abm_len; y++) { - ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa[tc_frame.tc_sec_header.spi].abm[y]); + ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); #ifdef MAC_DEBUG OS_printf("%02x", (uint8) ingest[y]); #endif @@ -3029,7 +2076,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) // Increment the IV for next time #ifdef INCREMENT - Crypto_increment(sa[tc_frame.tc_sec_header.spi].iv, IV_SIZE); + Crypto_increment(sa_ptr->iv, IV_SIZE); #endif } else @@ -3143,6 +2190,8 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) uint8 aad[20]; uint16 spi = tm_frame.tm_sec_header.spi; uint16 spp_crc = 0x0000; + SecurityAssociation_t* sa_ptr; + SecurityAssociation_t sa; gcry_cipher_hd_t tmp_hd; gcry_error_t gcry_error = GPG_ERR_NO_ERROR; @@ -3192,6 +2241,12 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) // Payload Data Unit Crypto_TM_updatePDU(ingest, *len_ingest); + if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } + + // Check test flags if (badSPI == 1) { @@ -3199,7 +2254,7 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) } if (badIV == 1) { - sa[tm_frame.tm_sec_header.spi].iv[IV_SIZE-1]++; + sa_ptr->iv[IV_SIZE-1]++; } if (badMAC == 1) { @@ -3218,22 +2273,22 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) // Security Header tempTM[count++] = (uint8) ((spi & 0xFF00) >> 8); tempTM[count++] = (uint8) ((spi & 0x00FF)); - CFE_PSP_MemCpy(tm_frame.tm_sec_header.iv, sa[spi].iv, IV_SIZE); + CFE_PSP_MemCpy(tm_frame.tm_sec_header.iv, sa_ptr->iv, IV_SIZE); // Padding Length pad_len = Crypto_Get_tmLength(*len_ingest) - TM_MIN_SIZE + IV_SIZE + TM_PAD_SIZE - *len_ingest; // Only add IV for authenticated encryption - if ((sa[spi].est == 1) && - (sa[spi].ast == 1)) + if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) { // Initialization Vector #ifdef INCREMENT - Crypto_increment(sa[tm_frame.tm_sec_header.spi].iv, IV_SIZE); + Crypto_increment(sa_ptr->iv, IV_SIZE); #endif - if ((sa[spi].est == 1) || (sa[spi].ast == 1)) + if ((sa_ptr->est == 1) || (sa_ptr->ast == 1)) { for (x = 0; x < IV_SIZE; x++) { - tempTM[count++] = sa[tm_frame.tm_sec_header.spi].iv[x]; + tempTM[count++] = sa_ptr->iv[x]; } } pdu_loc = count; @@ -3272,8 +2327,8 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) // Determine Mode // Clear - if ((sa[spi].est == 0) && - (sa[spi].ast == 0)) + if ((sa_ptr->est == 0) && + (sa_ptr->ast == 0)) { #ifdef DEBUG OS_printf(KBLU "Creating a TM - CLEAR! \n" RESET); @@ -3282,8 +2337,8 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) CFE_PSP_MemCpy(ingest, tempTM, count); } // Authenticated Encryption - else if ((sa[spi].est == 1) && - (sa[spi].ast == 1)) + else if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) { #ifdef DEBUG OS_printf(KBLU "Creating a TM - AUTHENTICATED ENCRYPTION! \n" RESET); @@ -3296,9 +2351,9 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) OS_printf("AAD = 0x"); #endif // Prepare additional authenticated data - for (y = 0; y < sa[spi].abm_len; y++) + for (y = 0; y < sa_ptr->abm_len; y++) { - aad[y] = ingest[y] & sa[spi].abm[y]; + aad[y] = ingest[y] & sa_ptr->abm[y]; #ifdef MAC_DEBUG OS_printf("%02x", aad[y]); #endif @@ -3321,7 +2376,7 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) } gcry_error = gcry_cipher_setkey( tmp_hd, - &(ek_ring[sa[spi].ekid].value[0]), + &(ek_ring[sa_ptr->ekid].value[0]), KEY_SIZE ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -3332,8 +2387,8 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) } gcry_error = gcry_cipher_setiv( tmp_hd, - &(sa[tm_frame.tm_sec_header.spi].iv[0]), - sa[tm_frame.tm_sec_header.spi].iv_len + &(sa_ptr->iv[0]), + sa_ptr->iv_len ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { @@ -3357,7 +2412,7 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) gcry_error = gcry_cipher_authenticate( tmp_hd, &(aad[0]), // additional authenticated data - sa[spi].abm_len // length of AAD + sa_ptr->abm_len // length of AAD ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { @@ -3399,8 +2454,8 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) ingest[fecf_loc + 1] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); } // Authentication - else if ((sa[spi].est == 0) && - (sa[spi].ast == 1)) + else if ((sa_ptr->est == 0) && + (sa_ptr->ast == 1)) { #ifdef DEBUG OS_printf(KBLU "Creating a TM - AUTHENTICATED! \n" RESET); @@ -3409,8 +2464,8 @@ int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) CFE_PSP_MemCpy(ingest, tempTM, count); } // Encryption - else if ((sa[spi].est == 1) && - (sa[spi].ast == 0)) + else if ((sa_ptr->est == 1) && + (sa_ptr->ast == 0)) { #ifdef DEBUG OS_printf(KBLU "Creating a TM - ENCRYPTED! \n" RESET); diff --git a/fsw/src/sadb_routine.c b/fsw/src/sadb_routine.c new file mode 100644 index 00000000..20d41efd --- /dev/null +++ b/fsw/src/sadb_routine.c @@ -0,0 +1,20 @@ +/* + * Copyright 2021, by the California Institute of Technology. + * ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged. + * Any commercial use must be negotiated with the Office of Technology + * Transfer at the California Institute of Technology. + * + * This software may be subject to U.S. export control laws. By accepting + * this software, the user agrees to comply with all applicable U.S. + * export laws and regulations. User has the responsibility to obtain + * export licenses, or other export authority as may be required before + * exporting such information to foreign countries or providing access to + * foreign persons. + */ + +#include "sadb_routine.h" +SadbRoutine init_parse_sadb_routine(char* config) +{ + SadbRoutine sadb_routine; + return sadb_routine; +} \ No newline at end of file diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c new file mode 100644 index 00000000..6241d316 --- /dev/null +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -0,0 +1,1048 @@ +/* + * Copyright 2021, by the California Institute of Technology. + * ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged. + * Any commercial use must be negotiated with the Office of Technology + * Transfer at the California Institute of Technology. + * + * This software may be subject to U.S. export control laws. By accepting + * this software, the user agrees to comply with all applicable U.S. + * export laws and regulations. User has the responsibility to obtain + * export licenses, or other export authority as may be required before + * exporting such information to foreign countries or providing access to + * foreign persons. + */ + +#include "sadb_routine.h" +#include "crypto_structs.h" +#include "crypto_print.h" +#include "crypto.h" + +// Security Association Initialization Functions +static int32 sadb_config(void); +static int32 sadb_init(void); +// Security Association Interaction Functions +static int32 sadb_get_sa_from_spi(uint16,SecurityAssociation_t**); +// Security Association Utility Functions +static int32 sadb_sa_start(void); +static int32 sadb_sa_expire(void); +static int32 sadb_sa_rekey(void); +static int32 sadb_sa_status(char*); +static int32 sadb_sa_create(void); +static int32 sadb_sa_setARSN(void); +static int32 sadb_sa_setARSNW(void); +static int32 sadb_sa_delete(void); + + +/* +** Global Variables +*/ +// Security +static SadbRoutineStruct sadb_routine; +static SecurityAssociation_t sa[NUM_SA]; + +SadbRoutine get_sadb_routine_inmemory(void) +{ + sadb_routine.sadb_config = sadb_config; + sadb_routine.sadb_init = sadb_init; + sadb_routine.sadb_get_sa_from_spi = sadb_get_sa_from_spi; + sadb_routine.sadb_sa_start = sadb_sa_start; + sadb_routine.sadb_sa_expire = sadb_sa_expire; + sadb_routine.sadb_sa_rekey = sadb_sa_rekey; + sadb_routine.sadb_sa_status = sadb_sa_status; + sadb_routine.sadb_sa_create = sadb_sa_create; + sadb_routine.sadb_sa_setARSN = sadb_sa_setARSN; + sadb_routine.sadb_sa_setARSNW = sadb_sa_setARSNW; + sadb_routine.sadb_sa_delete = sadb_sa_delete; + return &sadb_routine; +} + +int32 sadb_config(void) +{ + int32 status = OS_SUCCESS; + // Master Keys + // 0 - 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F -> ACTIVE + ek_ring[0].value[0] = 0x00; + ek_ring[0].value[1] = 0x01; + ek_ring[0].value[2] = 0x02; + ek_ring[0].value[3] = 0x03; + ek_ring[0].value[4] = 0x04; + ek_ring[0].value[5] = 0x05; + ek_ring[0].value[6] = 0x06; + ek_ring[0].value[7] = 0x07; + ek_ring[0].value[8] = 0x08; + ek_ring[0].value[9] = 0x09; + ek_ring[0].value[10] = 0x0A; + ek_ring[0].value[11] = 0x0B; + ek_ring[0].value[12] = 0x0C; + ek_ring[0].value[13] = 0x0D; + ek_ring[0].value[14] = 0x0E; + ek_ring[0].value[15] = 0x0F; + ek_ring[0].value[16] = 0x00; + ek_ring[0].value[17] = 0x01; + ek_ring[0].value[18] = 0x02; + ek_ring[0].value[19] = 0x03; + ek_ring[0].value[20] = 0x04; + ek_ring[0].value[21] = 0x05; + ek_ring[0].value[22] = 0x06; + ek_ring[0].value[23] = 0x07; + ek_ring[0].value[24] = 0x08; + ek_ring[0].value[25] = 0x09; + ek_ring[0].value[26] = 0x0A; + ek_ring[0].value[27] = 0x0B; + ek_ring[0].value[28] = 0x0C; + ek_ring[0].value[29] = 0x0D; + ek_ring[0].value[30] = 0x0E; + ek_ring[0].value[31] = 0x0F; + ek_ring[0].key_state = KEY_ACTIVE; + // 1 - 101112131415161718191A1B1C1D1E1F101112131415161718191A1B1C1D1E1F -> ACTIVE + ek_ring[1].value[0] = 0x10; + ek_ring[1].value[1] = 0x11; + ek_ring[1].value[2] = 0x12; + ek_ring[1].value[3] = 0x13; + ek_ring[1].value[4] = 0x14; + ek_ring[1].value[5] = 0x15; + ek_ring[1].value[6] = 0x16; + ek_ring[1].value[7] = 0x17; + ek_ring[1].value[8] = 0x18; + ek_ring[1].value[9] = 0x19; + ek_ring[1].value[10] = 0x1A; + ek_ring[1].value[11] = 0x1B; + ek_ring[1].value[12] = 0x1C; + ek_ring[1].value[13] = 0x1D; + ek_ring[1].value[14] = 0x1E; + ek_ring[1].value[15] = 0x1F; + ek_ring[1].value[16] = 0x10; + ek_ring[1].value[17] = 0x11; + ek_ring[1].value[18] = 0x12; + ek_ring[1].value[19] = 0x13; + ek_ring[1].value[20] = 0x14; + ek_ring[1].value[21] = 0x15; + ek_ring[1].value[22] = 0x16; + ek_ring[1].value[23] = 0x17; + ek_ring[1].value[24] = 0x18; + ek_ring[1].value[25] = 0x19; + ek_ring[1].value[26] = 0x1A; + ek_ring[1].value[27] = 0x1B; + ek_ring[1].value[28] = 0x1C; + ek_ring[1].value[29] = 0x1D; + ek_ring[1].value[30] = 0x1E; + ek_ring[1].value[31] = 0x1F; + ek_ring[1].key_state = KEY_ACTIVE; + // 2 - 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F -> ACTIVE + ek_ring[2].value[0] = 0x20; + ek_ring[2].value[1] = 0x21; + ek_ring[2].value[2] = 0x22; + ek_ring[2].value[3] = 0x23; + ek_ring[2].value[4] = 0x24; + ek_ring[2].value[5] = 0x25; + ek_ring[2].value[6] = 0x26; + ek_ring[2].value[7] = 0x27; + ek_ring[2].value[8] = 0x28; + ek_ring[2].value[9] = 0x29; + ek_ring[2].value[10] = 0x2A; + ek_ring[2].value[11] = 0x2B; + ek_ring[2].value[12] = 0x2C; + ek_ring[2].value[13] = 0x2D; + ek_ring[2].value[14] = 0x2E; + ek_ring[2].value[15] = 0x2F; + ek_ring[2].value[16] = 0x20; + ek_ring[2].value[17] = 0x21; + ek_ring[2].value[18] = 0x22; + ek_ring[2].value[19] = 0x23; + ek_ring[2].value[20] = 0x24; + ek_ring[2].value[21] = 0x25; + ek_ring[2].value[22] = 0x26; + ek_ring[2].value[23] = 0x27; + ek_ring[2].value[24] = 0x28; + ek_ring[2].value[25] = 0x29; + ek_ring[2].value[26] = 0x2A; + ek_ring[2].value[27] = 0x2B; + ek_ring[2].value[28] = 0x2C; + ek_ring[2].value[29] = 0x2D; + ek_ring[2].value[30] = 0x2E; + ek_ring[2].value[31] = 0x2F; + ek_ring[2].key_state = KEY_ACTIVE; + + // Session Keys + // 128 - 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -> ACTIVE + ek_ring[128].value[0] = 0x01; + ek_ring[128].value[1] = 0x23; + ek_ring[128].value[2] = 0x45; + ek_ring[128].value[3] = 0x67; + ek_ring[128].value[4] = 0x89; + ek_ring[128].value[5] = 0xAB; + ek_ring[128].value[6] = 0xCD; + ek_ring[128].value[7] = 0xEF; + ek_ring[128].value[8] = 0x01; + ek_ring[128].value[9] = 0x23; + ek_ring[128].value[10] = 0x45; + ek_ring[128].value[11] = 0x67; + ek_ring[128].value[12] = 0x89; + ek_ring[128].value[13] = 0xAB; + ek_ring[128].value[14] = 0xCD; + ek_ring[128].value[15] = 0xEF; + ek_ring[128].value[16] = 0x01; + ek_ring[128].value[17] = 0x23; + ek_ring[128].value[18] = 0x45; + ek_ring[128].value[19] = 0x67; + ek_ring[128].value[20] = 0x89; + ek_ring[128].value[21] = 0xAB; + ek_ring[128].value[22] = 0xCD; + ek_ring[128].value[23] = 0xEF; + ek_ring[128].value[24] = 0x01; + ek_ring[128].value[25] = 0x23; + ek_ring[128].value[26] = 0x45; + ek_ring[128].value[27] = 0x67; + ek_ring[128].value[28] = 0x89; + ek_ring[128].value[29] = 0xAB; + ek_ring[128].value[30] = 0xCD; + ek_ring[128].value[31] = 0xEF; + ek_ring[128].key_state = KEY_ACTIVE; + // 129 - ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 -> ACTIVE + ek_ring[129].value[0] = 0xAB; + ek_ring[129].value[1] = 0xCD; + ek_ring[129].value[2] = 0xEF; + ek_ring[129].value[3] = 0x01; + ek_ring[129].value[4] = 0x23; + ek_ring[129].value[5] = 0x45; + ek_ring[129].value[6] = 0x67; + ek_ring[129].value[7] = 0x89; + ek_ring[129].value[8] = 0xAB; + ek_ring[129].value[9] = 0xCD; + ek_ring[129].value[10] = 0xEF; + ek_ring[129].value[11] = 0x01; + ek_ring[129].value[12] = 0x23; + ek_ring[129].value[13] = 0x45; + ek_ring[129].value[14] = 0x67; + ek_ring[129].value[15] = 0x89; + ek_ring[129].value[16] = 0xAB; + ek_ring[129].value[17] = 0xCD; + ek_ring[129].value[18] = 0xEF; + ek_ring[129].value[19] = 0x01; + ek_ring[129].value[20] = 0x23; + ek_ring[129].value[21] = 0x45; + ek_ring[129].value[22] = 0x67; + ek_ring[129].value[23] = 0x89; + ek_ring[129].value[24] = 0xAB; + ek_ring[129].value[25] = 0xCD; + ek_ring[129].value[26] = 0xEF; + ek_ring[129].value[27] = 0x01; + ek_ring[129].value[28] = 0x23; + ek_ring[129].value[29] = 0x45; + ek_ring[129].value[30] = 0x67; + ek_ring[129].value[31] = 0x89; + ek_ring[129].key_state = KEY_ACTIVE; + // 130 - FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210 -> ACTIVE + ek_ring[130].value[0] = 0xFE; + ek_ring[130].value[1] = 0xDC; + ek_ring[130].value[2] = 0xBA; + ek_ring[130].value[3] = 0x98; + ek_ring[130].value[4] = 0x76; + ek_ring[130].value[5] = 0x54; + ek_ring[130].value[6] = 0x32; + ek_ring[130].value[7] = 0x10; + ek_ring[130].value[8] = 0xFE; + ek_ring[130].value[9] = 0xDC; + ek_ring[130].value[10] = 0xBA; + ek_ring[130].value[11] = 0x98; + ek_ring[130].value[12] = 0x76; + ek_ring[130].value[13] = 0x54; + ek_ring[130].value[14] = 0x32; + ek_ring[130].value[15] = 0x10; + ek_ring[130].value[16] = 0xFE; + ek_ring[130].value[17] = 0xDC; + ek_ring[130].value[18] = 0xBA; + ek_ring[130].value[19] = 0x98; + ek_ring[130].value[20] = 0x76; + ek_ring[130].value[21] = 0x54; + ek_ring[130].value[22] = 0x32; + ek_ring[130].value[23] = 0x10; + ek_ring[130].value[24] = 0xFE; + ek_ring[130].value[25] = 0xDC; + ek_ring[130].value[26] = 0xBA; + ek_ring[130].value[27] = 0x98; + ek_ring[130].value[28] = 0x76; + ek_ring[130].value[29] = 0x54; + ek_ring[130].value[30] = 0x32; + ek_ring[130].value[31] = 0x10; + ek_ring[130].key_state = KEY_ACTIVE; + // 131 - 9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA -> ACTIVE + ek_ring[131].value[0] = 0x98; + ek_ring[131].value[1] = 0x76; + ek_ring[131].value[2] = 0x54; + ek_ring[131].value[3] = 0x32; + ek_ring[131].value[4] = 0x10; + ek_ring[131].value[5] = 0xFE; + ek_ring[131].value[6] = 0xDC; + ek_ring[131].value[7] = 0xBA; + ek_ring[131].value[8] = 0x98; + ek_ring[131].value[9] = 0x76; + ek_ring[131].value[10] = 0x54; + ek_ring[131].value[11] = 0x32; + ek_ring[131].value[12] = 0x10; + ek_ring[131].value[13] = 0xFE; + ek_ring[131].value[14] = 0xDC; + ek_ring[131].value[15] = 0xBA; + ek_ring[131].value[16] = 0x98; + ek_ring[131].value[17] = 0x76; + ek_ring[131].value[18] = 0x54; + ek_ring[131].value[19] = 0x32; + ek_ring[131].value[20] = 0x10; + ek_ring[131].value[21] = 0xFE; + ek_ring[131].value[22] = 0xDC; + ek_ring[131].value[23] = 0xBA; + ek_ring[131].value[24] = 0x98; + ek_ring[131].value[25] = 0x76; + ek_ring[131].value[26] = 0x54; + ek_ring[131].value[27] = 0x32; + ek_ring[131].value[28] = 0x10; + ek_ring[131].value[29] = 0xFE; + ek_ring[131].value[30] = 0xDC; + ek_ring[131].value[31] = 0xBA; + ek_ring[131].key_state = KEY_ACTIVE; + // 132 - 0123456789ABCDEFABCDEF01234567890123456789ABCDEFABCDEF0123456789 -> PRE_ACTIVATION + ek_ring[132].value[0] = 0x01; + ek_ring[132].value[1] = 0x23; + ek_ring[132].value[2] = 0x45; + ek_ring[132].value[3] = 0x67; + ek_ring[132].value[4] = 0x89; + ek_ring[132].value[5] = 0xAB; + ek_ring[132].value[6] = 0xCD; + ek_ring[132].value[7] = 0xEF; + ek_ring[132].value[8] = 0xAB; + ek_ring[132].value[9] = 0xCD; + ek_ring[132].value[10] = 0xEF; + ek_ring[132].value[11] = 0x01; + ek_ring[132].value[12] = 0x23; + ek_ring[132].value[13] = 0x45; + ek_ring[132].value[14] = 0x67; + ek_ring[132].value[15] = 0x89; + ek_ring[132].value[16] = 0x01; + ek_ring[132].value[17] = 0x23; + ek_ring[132].value[18] = 0x45; + ek_ring[132].value[19] = 0x67; + ek_ring[132].value[20] = 0x89; + ek_ring[132].value[21] = 0xAB; + ek_ring[132].value[22] = 0xCD; + ek_ring[132].value[23] = 0xEF; + ek_ring[132].value[24] = 0xAB; + ek_ring[132].value[25] = 0xCD; + ek_ring[132].value[26] = 0xEF; + ek_ring[132].value[27] = 0x01; + ek_ring[132].value[28] = 0x23; + ek_ring[132].value[29] = 0x45; + ek_ring[132].value[30] = 0x67; + ek_ring[132].value[31] = 0x89; + ek_ring[132].key_state = KEY_PREACTIVE; + // 133 - ABCDEF01234567890123456789ABCDEFABCDEF01234567890123456789ABCDEF -> ACTIVE + ek_ring[133].value[0] = 0xAB; + ek_ring[133].value[1] = 0xCD; + ek_ring[133].value[2] = 0xEF; + ek_ring[133].value[3] = 0x01; + ek_ring[133].value[4] = 0x23; + ek_ring[133].value[5] = 0x45; + ek_ring[133].value[6] = 0x67; + ek_ring[133].value[7] = 0x89; + ek_ring[133].value[8] = 0x01; + ek_ring[133].value[9] = 0x23; + ek_ring[133].value[10] = 0x45; + ek_ring[133].value[11] = 0x67; + ek_ring[133].value[12] = 0x89; + ek_ring[133].value[13] = 0xAB; + ek_ring[133].value[14] = 0xCD; + ek_ring[133].value[15] = 0xEF; + ek_ring[133].value[16] = 0xAB; + ek_ring[133].value[17] = 0xCD; + ek_ring[133].value[18] = 0xEF; + ek_ring[133].value[19] = 0x01; + ek_ring[133].value[20] = 0x23; + ek_ring[133].value[21] = 0x45; + ek_ring[133].value[22] = 0x67; + ek_ring[133].value[23] = 0x89; + ek_ring[133].value[24] = 0x01; + ek_ring[133].value[25] = 0x23; + ek_ring[133].value[26] = 0x45; + ek_ring[133].value[27] = 0x67; + ek_ring[133].value[28] = 0x89; + ek_ring[133].value[29] = 0xAB; + ek_ring[133].value[30] = 0xCD; + ek_ring[133].value[31] = 0xEF; + ek_ring[133].key_state = KEY_ACTIVE; + // 134 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE + ek_ring[134].value[0] = 0xAB; + ek_ring[134].value[1] = 0xCD; + ek_ring[134].value[2] = 0xEF; + ek_ring[134].value[3] = 0x01; + ek_ring[134].value[4] = 0x23; + ek_ring[134].value[5] = 0x45; + ek_ring[134].value[6] = 0x67; + ek_ring[134].value[7] = 0x89; + ek_ring[134].value[8] = 0xFE; + ek_ring[134].value[9] = 0xDC; + ek_ring[134].value[10] = 0xBA; + ek_ring[134].value[11] = 0x98; + ek_ring[134].value[12] = 0x76; + ek_ring[134].value[13] = 0x54; + ek_ring[134].value[14] = 0x32; + ek_ring[134].value[15] = 0x10; + ek_ring[134].value[16] = 0xAB; + ek_ring[134].value[17] = 0xCD; + ek_ring[134].value[18] = 0xEF; + ek_ring[134].value[19] = 0x01; + ek_ring[134].value[20] = 0x23; + ek_ring[134].value[21] = 0x45; + ek_ring[134].value[22] = 0x67; + ek_ring[134].value[23] = 0x89; + ek_ring[134].value[24] = 0xFE; + ek_ring[134].value[25] = 0xDC; + ek_ring[134].value[26] = 0xBA; + ek_ring[134].value[27] = 0x98; + ek_ring[134].value[28] = 0x76; + ek_ring[134].value[29] = 0x54; + ek_ring[134].value[30] = 0x32; + ek_ring[134].value[31] = 0x10; + ek_ring[134].key_state = KEY_DEACTIVATED; + + // Security Associations + // SA 1 - CLEAR MODE + sa[1].sa_state = SA_OPERATIONAL; + sa[1].est = 0; + sa[1].ast = 0; + sa[1].arc_len = 1; + sa[1].arcw_len = 1; + sa[1].arcw[0] = 5; + sa[1].gvcid_tc_blk[0].tfvn = 0; + sa[1].gvcid_tc_blk[0].scid = SCID & 0x3FF; + sa[1].gvcid_tc_blk[0].vcid = 0; + sa[1].gvcid_tc_blk[0].mapid = TYPE_TC; + sa[1].gvcid_tc_blk[1].tfvn = 0; + sa[1].gvcid_tc_blk[1].scid = SCID & 0x3FF; + sa[1].gvcid_tc_blk[1].vcid = 1; + sa[1].gvcid_tc_blk[1].mapid = TYPE_TC; + // SA 2 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 128 + sa[2].ekid = 128; + sa[2].sa_state = SA_KEYED; + sa[2].est = 1; + sa[2].ast = 1; + sa[2].shivf_len = 12; + sa[2].iv_len = IV_SIZE; + sa[2].iv[IV_SIZE-1] = 0; + sa[2].abm_len = 0x14; // 20 + for (int i = 0; i < sa[2].abm_len; i++) + { // Zero AAD bit mask + sa[2].abm[i] = 0x00; + } + sa[2].arcw_len = 1; + sa[2].arcw[0] = 5; + sa[2].arc_len = (sa[2].arcw[0] * 2) + 1; + // SA 3 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 129 + sa[3].ekid = 129; + sa[3].sa_state = SA_KEYED; + sa[3].est = 1; + sa[3].ast = 1; + sa[3].shivf_len = 12; + sa[3].iv_len = IV_SIZE; + sa[3].iv[IV_SIZE-1] = 0; + sa[3].abm_len = 0x14; // 20 + for (int i = 0; i < sa[3].abm_len; i++) + { // Zero AAD bit mask + sa[3].abm[i] = 0x00; + } + sa[3].arcw_len = 1; + sa[3].arcw[0] = 5; + sa[3].arc_len = (sa[3].arcw[0] * 2) + 1; + // SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 + sa[4].ekid = 130; + sa[4].sa_state = SA_KEYED; + sa[4].est = 1; + sa[4].ast = 1; + sa[4].shivf_len = 12; + sa[4].iv_len = IV_SIZE; + sa[4].iv[IV_SIZE-1] = 0; + sa[4].abm_len = 0x14; // 20 + for (int i = 0; i < sa[4].abm_len; i++) + { // Zero AAD bit mask + sa[4].abm[i] = 0x00; + } + sa[4].arcw_len = 1; + sa[4].arcw[0] = 5; + sa[4].arc_len = (sa[4].arcw[0] * 2) + 1; + sa[4].gvcid_tc_blk[0].tfvn = 0; + sa[4].gvcid_tc_blk[0].scid = SCID & 0x3FF; + sa[4].gvcid_tc_blk[0].vcid = 0; + sa[4].gvcid_tc_blk[0].mapid = TYPE_TC; + sa[4].gvcid_tc_blk[1].tfvn = 0; + sa[4].gvcid_tc_blk[1].scid = SCID & 0x3FF; + sa[4].gvcid_tc_blk[1].vcid = 1; + sa[4].gvcid_tc_blk[1].mapid = TYPE_TC; + // SA 5 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 131 + sa[5].ekid = 131; + sa[5].sa_state = SA_KEYED; + sa[5].est = 1; + sa[5].ast = 1; + sa[5].shivf_len = 12; + sa[5].iv_len = IV_SIZE; + sa[5].iv[IV_SIZE-1] = 0; + sa[5].abm_len = 0x14; // 20 + for (int i = 0; i < sa[5].abm_len; i++) + { // Zero AAD bit mask + sa[5].abm[i] = 0x00; + } + sa[5].arcw_len = 1; + sa[5].arcw[0] = 5; + sa[5].arc_len = (sa[5].arcw[0] * 2) + 1; + // SA 6 - UNKEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: - + sa[6].sa_state = SA_UNKEYED; + sa[6].est = 1; + sa[6].ast = 1; + sa[6].shivf_len = 12; + sa[6].iv_len = IV_SIZE; + sa[6].iv[IV_SIZE-1] = 0; + sa[6].abm_len = 0x14; // 20 + for (int i = 0; i < sa[6].abm_len; i++) + { // Zero AAD bit mask + sa[6].abm[i] = 0x00; + } + sa[6].arcw_len = 1; + sa[6].arcw[0] = 5; + sa[6].arc_len = (sa[6].arcw[0] * 2) + 1; + //itc_gcm128_init(&(sa[6].gcm_ctx), (unsigned char *)&(ek_ring[sa[6].ekid])); + + return status; +} + +int32 sadb_init(void) +{ + int32 status = OS_SUCCESS; + + for (int x = 0; x < NUM_SA; x++) + { + sa[x].ekid = x; + sa[x].akid = x; + sa[x].sa_state = SA_NONE; + sa[x].ecs_len = 0; + sa[x].ecs[0] = 0; + sa[x].ecs[1] = 0; + sa[x].ecs[2] = 0; + sa[x].ecs[3] = 0; + sa[x].iv_len = IV_SIZE; + sa[x].acs_len = 0; + sa[x].acs = 0; + sa[x].arc_len = 0; + sa[x].arc[0] = 5; + } + return status; +} + + +/* +** Security Association Interaction Functions +*/ +static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_association) +{ + int32 status = OS_SUCCESS; + *security_association = &sa[spi]; + return status; +} + +/* +** Security Association Management Services +*/ +static int32 sadb_sa_start(void) +{ + // Local variables + uint8 count = 0; + uint16 spi = 0x0000; + crypto_gvcid_t gvcid; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + + // Overwrite last PID + sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; + + // Check SPI exists and in 'Keyed' state + if (spi < NUM_SA) + { + if (sa[spi].sa_state == SA_KEYED) + { + count = 2; + + for(int x = 0; x <= ((sdls_frame.pdu.pdu_len - 2) / 4); x++) + { // Read in GVCID + gvcid.tfvn = (sdls_frame.pdu.data[count] >> 4); + gvcid.scid = (sdls_frame.pdu.data[count] << 12) | + (sdls_frame.pdu.data[count + 1] << 4) | + (sdls_frame.pdu.data[count + 2] >> 4); + gvcid.vcid = (sdls_frame.pdu.data[count + 2] << 4) | + (sdls_frame.pdu.data[count + 3] && 0x3F); + gvcid.mapid = (sdls_frame.pdu.data[count + 3]); + + // TC + if (gvcid.vcid != tc_frame.tc_header.vcid) + { // Clear all GVCIDs for provided SPI + if (gvcid.mapid == TYPE_TC) + { + for (int i = 0; i < NUM_GVCID; i++) + { // TC + sa[spi].gvcid_tc_blk[x].tfvn = 0; + sa[spi].gvcid_tc_blk[x].scid = 0; + sa[spi].gvcid_tc_blk[x].vcid = 0; + sa[spi].gvcid_tc_blk[x].mapid = 0; + } + } + // Write channel to SA + if (gvcid.mapid != TYPE_MAP) + { // TC + sa[spi].gvcid_tc_blk[gvcid.vcid].tfvn = gvcid.tfvn; + sa[spi].gvcid_tc_blk[gvcid.vcid].scid = gvcid.scid; + sa[spi].gvcid_tc_blk[gvcid.vcid].mapid = gvcid.mapid; + } + else + { + // TODO: Handle TYPE_MAP + } + } + // TM + if (gvcid.vcid != tm_frame.tm_header.vcid) + { // Clear all GVCIDs for provided SPI + if (gvcid.mapid == TYPE_TM) + { + for (int i = 0; i < NUM_GVCID; i++) + { // TM + sa[spi].gvcid_tm_blk[x].tfvn = 0; + sa[spi].gvcid_tm_blk[x].scid = 0; + sa[spi].gvcid_tm_blk[x].vcid = 0; + sa[spi].gvcid_tm_blk[x].mapid = 0; + } + } + // Write channel to SA + if (gvcid.mapid != TYPE_MAP) + { // TM + sa[spi].gvcid_tm_blk[gvcid.vcid].tfvn = gvcid.tfvn; + sa[spi].gvcid_tm_blk[gvcid.vcid].scid = gvcid.scid; + sa[spi].gvcid_tm_blk[gvcid.vcid].vcid = gvcid.vcid; + sa[spi].gvcid_tm_blk[gvcid.vcid].mapid = gvcid.mapid; + } + else + { + // TODO: Handle TYPE_MAP + } + } + +#ifdef PDU_DEBUG + OS_printf("SPI %d changed to OPERATIONAL state. \n", spi); + switch (gvcid.mapid) + { + case TYPE_TC: + OS_printf("Type TC, "); + break; + case TYPE_MAP: + OS_printf("Type MAP, "); + break; + case TYPE_TM: + OS_printf("Type TM, "); + break; + default: + OS_printf("Type Unknown, "); + break; + } +#endif + + // Change to operational state + sa[spi].sa_state = SA_OPERATIONAL; + } + } + else + { + OS_printf(KRED "ERROR: SPI %d is not in the KEYED state.\n" RESET, spi); + } + } + else + { + OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); + } + +#ifdef DEBUG + OS_printf("\t spi = %d \n", spi); +#endif + + return OS_SUCCESS; +} + +static int32 sadb_sa_stop(void) +{ + // Local variables + uint16 spi = 0x0000; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + OS_printf("spi = %d \n", spi); + + // Overwrite last PID + sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; + + // Check SPI exists and in 'Active' state + if (spi < NUM_SA) + { + if (sa[spi].sa_state == SA_OPERATIONAL) + { + // Remove all GVC/GMAP IDs + for (int x = 0; x < NUM_GVCID; x++) + { // TC + sa[spi].gvcid_tc_blk[x].tfvn = 0; + sa[spi].gvcid_tc_blk[x].scid = 0; + sa[spi].gvcid_tc_blk[x].vcid = 0; + sa[spi].gvcid_tc_blk[x].mapid = 0; + // TM + sa[spi].gvcid_tm_blk[x].tfvn = 0; + sa[spi].gvcid_tm_blk[x].scid = 0; + sa[spi].gvcid_tm_blk[x].vcid = 0; + sa[spi].gvcid_tm_blk[x].mapid = 0; + } + + // Change to operational state + sa[spi].sa_state = SA_KEYED; +#ifdef PDU_DEBUG + OS_printf("SPI %d changed to KEYED state. \n", spi); +#endif + } + else + { + OS_printf(KRED "ERROR: SPI %d is not in the OPERATIONAL state.\n" RESET, spi); + } + } + else + { + OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); + } + +#ifdef DEBUG + OS_printf("\t spi = %d \n", spi); +#endif + + return OS_SUCCESS; +} + +static int32 sadb_sa_rekey(void) +{ + // Local variables + uint16 spi = 0x0000; + int count = 0; + int x = 0; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[count] << 8) | (uint8)sdls_frame.pdu.data[count+1]; + count = count + 2; + + // Overwrite last PID + sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; + + // Check SPI exists and in 'Unkeyed' state + if (spi < NUM_SA) + { + if (sa[spi].sa_state == SA_UNKEYED) + { // Encryption Key + sa[spi].ekid = ((uint8)sdls_frame.pdu.data[count] << 8) | (uint8)sdls_frame.pdu.data[count+1]; + count = count + 2; + + // Authentication Key + //sa[spi].akid = ((uint8)sdls_frame.pdu.data[count] << 8) | (uint8)sdls_frame.pdu.data[count+1]; + //count = count + 2; + + // Anti-Replay Counter +#ifdef PDU_DEBUG + OS_printf("SPI %d IV updated to: 0x", spi); +#endif + if (sa[spi].iv_len > 0) + { // Set IV - authenticated encryption + for (x = count; x < (sa[spi].iv_len + count); x++) + { + // TODO: Uncomment once fixed in ESA implementation + // TODO: Assuming this was fixed... + sa[spi].iv[x - count] = (uint8) sdls_frame.pdu.data[x]; +#ifdef PDU_DEBUG + OS_printf("%02x", sdls_frame.pdu.data[x]); +#endif + } + } + else + { // Set SN + // TODO + } +#ifdef PDU_DEBUG + OS_printf("\n"); +#endif + + // Change to keyed state + sa[spi].sa_state = SA_KEYED; +#ifdef PDU_DEBUG + OS_printf("SPI %d changed to KEYED state with encrypted Key ID %d. \n", spi, sa[spi].ekid); +#endif + } + else + { + OS_printf(KRED "ERROR: SPI %d is not in the UNKEYED state.\n" RESET, spi); + } + } + else + { + OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); + } + +#ifdef DEBUG + OS_printf("\t spi = %d \n", spi); + OS_printf("\t ekid = %d \n", sa[spi].ekid); + //OS_printf("\t akid = %d \n", sa[spi].akid); +#endif + + return OS_SUCCESS; +} + +static int32 sadb_sa_expire(void) +{ + // Local variables + uint16 spi = 0x0000; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + OS_printf("spi = %d \n", spi); + + // Overwrite last PID + sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; + + // Check SPI exists and in 'Keyed' state + if (spi < NUM_SA) + { + if (sa[spi].sa_state == SA_KEYED) + { // Change to 'Unkeyed' state + sa[spi].sa_state = SA_UNKEYED; +#ifdef PDU_DEBUG + OS_printf("SPI %d changed to UNKEYED state. \n", spi); +#endif + } + else + { + OS_printf(KRED "ERROR: SPI %d is not in the KEYED state.\n" RESET, spi); + } + } + else + { + OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); + } + + return OS_SUCCESS; +} + +static int32 sadb_sa_create(void) +{ + // Local variables + uint8 count = 6; + uint16 spi = 0x0000; + + // Read sdls_frame.pdu.data + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + OS_printf("spi = %d \n", spi); + + // Overwrite last PID + sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; + + // Write SA Configuration + sa[spi].est = ((uint8)sdls_frame.pdu.data[2] & 0x80) >> 7; + sa[spi].ast = ((uint8)sdls_frame.pdu.data[2] & 0x40) >> 6; + sa[spi].shivf_len = ((uint8)sdls_frame.pdu.data[2] & 0x3F); + sa[spi].shsnf_len = ((uint8)sdls_frame.pdu.data[3] & 0xFC) >> 2; + sa[spi].shplf_len = ((uint8)sdls_frame.pdu.data[3] & 0x03); + sa[spi].stmacf_len = ((uint8)sdls_frame.pdu.data[4]); + sa[spi].ecs_len = ((uint8)sdls_frame.pdu.data[5]); + for (int x = 0; x < sa[spi].ecs_len; x++) + { + sa[spi].ecs[x] = ((uint8)sdls_frame.pdu.data[count++]); + } + sa[spi].iv_len = ((uint8)sdls_frame.pdu.data[count++]); + for (int x = 0; x < sa[spi].iv_len; x++) + { + sa[spi].iv[x] = ((uint8)sdls_frame.pdu.data[count++]); + } + sa[spi].acs_len = ((uint8)sdls_frame.pdu.data[count++]); + for (int x = 0; x < sa[spi].acs_len; x++) + { + sa[spi].acs = ((uint8)sdls_frame.pdu.data[count++]); + } + sa[spi].abm_len = (uint8)((sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1])); + count = count + 2; + for (int x = 0; x < sa[spi].abm_len; x++) + { + sa[spi].abm[x] = ((uint8)sdls_frame.pdu.data[count++]); + } + sa[spi].arc_len = ((uint8)sdls_frame.pdu.data[count++]); + for (int x = 0; x < sa[spi].arc_len; x++) + { + sa[spi].arc[x] = ((uint8)sdls_frame.pdu.data[count++]); + } + sa[spi].arcw_len = ((uint8)sdls_frame.pdu.data[count++]); + for (int x = 0; x < sa[spi].arcw_len; x++) + { + sa[spi].arcw[x] = ((uint8)sdls_frame.pdu.data[count++]); + } + + // TODO: Checks for valid data + + // Set state to unkeyed + sa[spi].sa_state = SA_UNKEYED; + +#ifdef PDU_DEBUG + Crypto_saPrint(&sa[spi]); +#endif + + return OS_SUCCESS; +} + +static int32 sadb_sa_delete(void) +{ + // Local variables + uint16 spi = 0x0000; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + OS_printf("spi = %d \n", spi); + + // Overwrite last PID + sa[spi].lpid = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | sdls_frame.pdu.pid; + + // Check SPI exists and in 'Unkeyed' state + if (spi < NUM_SA) + { + if (sa[spi].sa_state == SA_UNKEYED) + { // Change to 'None' state + sa[spi].sa_state = SA_NONE; +#ifdef PDU_DEBUG + OS_printf("SPI %d changed to NONE state. \n", spi); +#endif + + // TODO: Zero entire SA + } + else + { + OS_printf(KRED "ERROR: SPI %d is not in the UNKEYED state.\n" RESET, spi); + } + } + else + { + OS_printf(KRED "ERROR: SPI %d does not exist.\n" RESET, spi); + } + + return OS_SUCCESS; +} + +static int32 sadb_sa_setARSN(void) +{ + // Local variables + uint16 spi = 0x0000; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + OS_printf("spi = %d \n", spi); + + // TODO: Check SA type (authenticated, encrypted, both) and set appropriately + // TODO: Add more checks on bounds + + // Check SPI exists + if (spi < NUM_SA) + { +#ifdef PDU_DEBUG + OS_printf("SPI %d IV updated to: 0x", spi); +#endif + if (sa[spi].iv_len > 0) + { // Set IV - authenticated encryption + for (int x = 0; x < IV_SIZE; x++) + { + sa[spi].iv[x] = (uint8) sdls_frame.pdu.data[x + 2]; +#ifdef PDU_DEBUG + OS_printf("%02x", sa[spi].iv[x]); +#endif + } + Crypto_increment((uint8*)sa[spi].iv, IV_SIZE); + } + else + { // Set SN + // TODO + } +#ifdef PDU_DEBUG + OS_printf("\n"); +#endif + } + else + { + OS_printf("sadb_sa_setARSN ERROR: SPI %d does not exist.\n", spi); + } + + return OS_SUCCESS; +} + +static int32 sadb_sa_setARSNW(void) +{ + // Local variables + uint16 spi = 0x0000; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + OS_printf("spi = %d \n", spi); + + // Check SPI exists + if (spi < NUM_SA) + { + sa[spi].arcw_len = (uint8) sdls_frame.pdu.data[2]; + + // Check for out of bounds + if (sa[spi].arcw_len > (ARC_SIZE)) + { + sa[spi].arcw_len = ARC_SIZE; + } + + for(int x = 0; x < sa[spi].arcw_len; x++) + { + sa[spi].arcw[x] = (uint8) sdls_frame.pdu.data[x+3]; + } + } + else + { + OS_printf("sadb_sa_setARSNW ERROR: SPI %d does not exist.\n", spi); + } + + return OS_SUCCESS; +} + +static int32 sadb_sa_status(char* ingest) +{ + // Local variables + int count = 0; + uint16 spi = 0x0000; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + OS_printf("spi = %d \n", spi); + + // Check SPI exists + if (spi < NUM_SA) + { + // Prepare for Reply + sdls_frame.pdu.pdu_len = 3; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + // PDU + ingest[count++] = (spi & 0xFF00) >> 8; + ingest[count++] = (spi & 0x00FF); + ingest[count++] = sa[spi].lpid; + } + else + { + OS_printf("sadb_sa_status ERROR: SPI %d does not exist.\n", spi); + } + +#ifdef SA_DEBUG + Crypto_saPrint(&sa[spi]); +#endif + + return count; +} \ No newline at end of file diff --git a/fsw/src/sadb_routine_mariadb.template.c b/fsw/src/sadb_routine_mariadb.template.c new file mode 100644 index 00000000..4fc48313 --- /dev/null +++ b/fsw/src/sadb_routine_mariadb.template.c @@ -0,0 +1,72 @@ +/* + * Copyright 2021, by the California Institute of Technology. + * ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged. + * Any commercial use must be negotiated with the Office of Technology + * Transfer at the California Institute of Technology. + * + * This software may be subject to U.S. export control laws. By accepting + * this software, the user agrees to comply with all applicable U.S. + * export laws and regulations. User has the responsibility to obtain + * export licenses, or other export authority as may be required before + * exporting such information to foreign countries or providing access to + * foreign persons. + */ + +#include "sadb_routine.h" +#include "crypto_structs.h" + +// Security Association Initialization Functions +static int32 sadb_config(void); +static int32 sadb_init(void); +// Security Association Interaction Functions +static int32 sadb_get_sa_from_spi(uint16,SecurityAssociation_t**); +// Security Association Utility Functions +static int32 sadb_sa_start(void); +static int32 sadb_sa_expire(void); +static int32 sadb_sa_rekey(void); +static int32 sadb_sa_status(char*); +static int32 sadb_sa_create(void); +static int32 sadb_sa_setARSN(void); +static int32 sadb_sa_setARSNW(void); +static int32 sadb_sa_delete(void); + + +/* +** Global Variables +*/ +// Security +static SadbRoutineStruct sadb_routine; +static SecurityAssociation_t sa[NUM_SA]; + +static crypto_key_t ek_ring[NUM_KEYS]; + + +SadbRoutine get_sadb_routine_mariadb(void) +{ + sadb_routine.sadb_config = sadb_config; + sadb_routine.sadb_init = sadb_init; + sadb_routine.sadb_get_sa_from_spi = sadb_get_sa_from_spi; + sadb_routine.sadb_sa_start = sadb_sa_start; + sadb_routine.sadb_sa_expire = sadb_sa_expire; + sadb_routine.sadb_sa_rekey = sadb_sa_rekey; + sadb_routine.sadb_sa_status = sadb_sa_status; + sadb_routine.sadb_sa_create = sadb_sa_create; + sadb_routine.sadb_sa_setARSN = sadb_sa_setARSN; + sadb_routine.sadb_sa_setARSNW = sadb_sa_setARSNW; + sadb_routine.sadb_sa_delete = sadb_sa_delete; + return &sadb_routine; +} + +int32 sadb_config(void){return 0;} +int32 sadb_init(void){return 0;} +// Security Association Interaction Functions +int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_association){return 0;} +// Security Association Utility Functions +int32 sadb_sa_start(void){return 0;} +int32 sadb_sa_expire(void){return 0;} +int32 sadb_sa_rekey(void){return 0;} +int32 sadb_sa_status(char* ingest){return 0;} +int32 sadb_sa_create(void){return 0;} +int32 sadb_sa_setARSN(void){return 0;} +int32 sadb_sa_setARSNW(void){return 0;} +int32 sadb_sa_delete(void){return 0;} From 7b42f0ae0a718d20d9a3b73f536cfb4e7ebdba95 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Fri, 15 Oct 2021 10:17:55 -0700 Subject: [PATCH 005/184] AKMC-108: Update Crypto_TC_ProcessSecurity to return unencrypted frame data, use local TC_t --- CMakeLists.txt | 2 +- fsw/crypto_tests/data/tc5.1.dat | Bin 0 -> 49 bytes fsw/crypto_tests/data/tc5.2.dat | Bin 0 -> 35 bytes fsw/crypto_tests/data/tc5.3.dat | Bin 0 -> 56 bytes fsw/crypto_util/app/crypto_sequence.c | 3 +- fsw/crypto_util/app/process_security.c | 3 +- fsw/public_inc/common_types_minimum.h | 5 - fsw/public_inc/crypto.h | 4 +- fsw/public_inc/crypto_config.h | 17 +- fsw/public_inc/crypto_structs.h | 8 +- fsw/public_inc/itc_common_types_minimum.h | 41 +++ fsw/src/crypto.c | 318 +++++++++++++--------- 12 files changed, 260 insertions(+), 141 deletions(-) create mode 100644 fsw/crypto_tests/data/tc5.1.dat create mode 100644 fsw/crypto_tests/data/tc5.2.dat create mode 100644 fsw/crypto_tests/data/tc5.3.dat create mode 100644 fsw/public_inc/itc_common_types_minimum.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2651840b..8eda60d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") OPTION(DEBUG "Debug" OFF) # Disabled by default IF(DEBUG) - ADD_DEFINITIONS(-DDEBUG) + ADD_DEFINITIONS(-DDEBUG -DOCF_DEBUG -DFECF_DEBUG -DSA_DEBUG -DPDU_DEBUG -DCCSDS_DEBUG -DTC_DEBUG -DMAC_DEBUG -DTM_DEBUG) add_compile_options(-ggdb) ENDIF(DEBUG) diff --git a/fsw/crypto_tests/data/tc5.1.dat b/fsw/crypto_tests/data/tc5.1.dat new file mode 100644 index 0000000000000000000000000000000000000000..7526bfcf5b3d352da23ed123c5b0160ddf131a53 GIT binary patch literal 49 scmY#jX3%2z&%nsQAklDP4TFSaJvW0G0}lfmLn{LkxHWbDiBK>A0M2F!o&W#< literal 0 HcmV?d00001 diff --git a/fsw/crypto_tests/data/tc5.2.dat b/fsw/crypto_tests/data/tc5.2.dat new file mode 100644 index 0000000000000000000000000000000000000000..cb4f0e79cddb79a71680b63be37e6fdbe7811c13 GIT binary patch literal 35 qcmY#jW>8@G&%nsQAklDPEd!rqJvW0i0}BHi1A~FXx9`iOLPG&}FbDPk literal 0 HcmV?d00001 diff --git a/fsw/crypto_tests/data/tc5.3.dat b/fsw/crypto_tests/data/tc5.3.dat new file mode 100644 index 0000000000000000000000000000000000000000..ed021679f47a744f0d274d70f499f110b73670ca GIT binary patch literal 56 zcmY#jW-(#-&%nlj0E~(+PKOqI9rW&u4s@-w+Im-YwV<|7eD%zmtgM1eD<2vi4h; -#include -#include /* * NOTE - NOT DEFINING STRUCT_LOW_BIT_FIRST or STRUCT_HIGH_BIT_FIRST @@ -59,9 +57,6 @@ typedef uint32_t uint32; typedef uint64_t uint64; typedef intptr_t intptr; - typedef uintptr_t cpuaddr; - typedef size_t cpusize; - typedef ptrdiff_t cpudiff; #ifdef __cplusplus diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index b51d3611..4ac8a351 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -27,6 +27,8 @@ ivv-itc@lists.nasa.gov #include "cfe_minimum.h" #endif +#include "crypto_structs.h" + #define CRYPTO_LIB_MAJOR_VERSION 1 #define CRYPTO_LIB_MINOR_VERSION 2 #define CRYPTO_LIB_REVISION 0 @@ -39,7 +41,7 @@ ivv-itc@lists.nasa.gov extern int32 Crypto_Init(void); // Telecommand (TC) extern int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest); -extern int32 Crypto_TC_ProcessSecurity(char* ingest, int* len_ingest); +extern int32 Crypto_TC_ProcessSecurity(char* ingest, int* len_ingest, TC_t* tc_sdls_processed_frame); // Telemetry (TM) extern int32 Crypto_TM_ApplySecurity(char* ingest, int* len_ingest); extern int32 Crypto_TM_ProcessSecurity(char* ingest, int* len_ingest); diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index cf305d04..caf8e124 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -20,14 +20,14 @@ ivv-itc@lists.nasa.gov // Build Defines //#define BUILD_STATIC -// Debug Defines +// Debug Defines -- Use CMAKE options //#define ARC_DEBUG //#define CCSDS_DEBUG //#define DEBUG //(CMAKE option, not hardcoded) //#define FECF_DEBUG //#define MAC_DEBUG - #define OCF_DEBUG - #define PDU_DEBUG + //#define OCF_DEBUG + //#define PDU_DEBUG //#define SA_DEBUG //#define TC_DEBUG //#define TM_DEBUG @@ -98,7 +98,8 @@ ivv-itc@lists.nasa.gov #define NUM_KEYS 256 #define DISABLED 0 #define ENABLED 1 - #define IV_SIZE 12 + #define IV_SIZE 12 /* TM IV size bytes */ + #define IV_SIZE_TC 4 /* TC IV size bytes */ #define OCF_SIZE 4 #define MAC_SIZE 16 /* bytes */ #define FECF_SIZE 2 @@ -155,10 +156,18 @@ ivv-itc@lists.nasa.gov // CCSDS PUS Defines #define TLV_DATA_SIZE 494 /* bytes */ + #define PUS_HDR 1 //(1=true,0=false) // TM Defines #define TM_FRAME_DATA_SIZE 1740 /* bytes */ #define TM_FILL_SIZE 1145 /* bytes */ #define TM_PAD_SIZE 2 /* bytes */ +// TC Behavior Defines + #define TC_PROCESS_SDLS_PDUS 1 //(1=true,0=false) + #define TC_SDLS_EP_VCID 4 //VCID which has SDLS PDUs (JPL uses VCIDs to determine TC type, there is no space packet layer with APIDs). Set to -1 if uses SP APIDs. + #define VCID_BITMASK 0b111111 //Some JPL missions do not use the entire CCSDS 6 bit field for VCID. + #define SEGMENTATION_HDR 1 //(1=true,0=false) + #define HAS_FECF 1 //(1=true,0=false) + #endif \ No newline at end of file diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index e5c3e5ab..45696575 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -18,7 +18,12 @@ ivv-itc@lists.nasa.gov #define _crypto_structs_h_ #include "crypto_config.h" -#include + +#ifdef NOS3 //NOS3/cFS build is ready +#include "common_types.h" +#else //Assume build outside of NOS3/cFS infrastructure +#include "common_types_minimum.h" +#endif /* ** Key Definitions @@ -266,6 +271,7 @@ typedef struct TC_FramePrimaryHeader_t tc_header; TC_FrameSecurityHeader_t tc_sec_header; uint8 tc_pdu[TC_FRAME_DATA_SIZE]; + uint16 tc_pdu_len; TC_FrameSecurityTrailer_t tc_sec_trailer; } TC_t; #define TC_SIZE (sizeof(TC_t)) diff --git a/fsw/public_inc/itc_common_types_minimum.h b/fsw/public_inc/itc_common_types_minimum.h new file mode 100644 index 00000000..10408298 --- /dev/null +++ b/fsw/public_inc/itc_common_types_minimum.h @@ -0,0 +1,41 @@ +/* + * Minimal port of https://github.com/nasa-itc/osal/blob/master/src/os/inc/common_types.h + * needed to build standalone crypto library. + * + * Copyright (c) 2019 United States Government as represented by + * the Administrator of the National Aeronautics and Space Administration. + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _itc_common_types_minimum_ +#define _itc_common_types_minimum_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +typedef uintptr_t cpuaddr; +typedef size_t cpusize; +typedef ptrdiff_t cpudiff; + +#ifdef __cplusplus +} +#endif + + +#endif //itc_common_types_minimum_.h diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index a1070845..d40ffca3 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -49,7 +49,7 @@ ivv-itc@lists.nasa.gov static int32 Crypto_SA_init(void); static int32 Crypto_SA_config(void); // Assisting Functions -static int32 Crypto_Get_tcPayloadLength(void); +static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame); static int32 Crypto_Get_tmLength(int len); static void Crypto_TM_updatePDU(char* ingest, int len_ingest); static void Crypto_TM_updateOCF(void); @@ -58,7 +58,7 @@ static int32 Crypto_increment(uint8* num, int length); static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window); static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length); static uint8 Crypto_Prep_Reply(char*, uint8); -static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest); +static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame); static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest); static void Crypto_Calc_CRC_Init_Table(void); static uint16 Crypto_Calc_CRC16(char* data, int size); @@ -66,10 +66,10 @@ static uint16 Crypto_Calc_CRC16(char* data, int size); static int32 Crypto_Key_OTAR(void); static int32 Crypto_Key_update(uint8 state); static int32 Crypto_Key_inventory(char*); -static int32 Crypto_Key_verify(char*); +static int32 Crypto_Key_verify(char*,TC_t* tc_frame); // Security Association Functions static int32 Crypto_SA_stop(void); -static int32 Crypto_SA_start(void); +static int32 Crypto_SA_start(TC_t* tc_frame); static int32 Crypto_SA_expire(void); static int32 Crypto_SA_rekey(void); static int32 Crypto_SA_status(char*); @@ -95,7 +95,7 @@ static int32 Crypto_User_ModifyKey(void); static int32 Crypto_User_ModifyActiveTM(void); static int32 Crypto_User_ModifyVCID(void); // Determine Payload Data Unit -static int32 Crypto_PDU(char* ingest); +static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); /* ** Global Variables @@ -105,7 +105,6 @@ static SecurityAssociation_t sa[NUM_SA]; static crypto_key_t ek_ring[NUM_KEYS]; //static crypto_key_t ak_ring[NUM_KEYS]; // Local Frames -static TC_t tc_frame; static CCSDS_t sdls_frame; static TM_t tm_frame; // OCF @@ -768,10 +767,17 @@ static void Crypto_Calc_CRC_Init_Table(void) /* ** Assisting Functions */ -static int32 Crypto_Get_tcPayloadLength(void) +static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame) // Returns the payload length of current tc_frame in BYTES! { - return (tc_frame.tc_header.fl - (5 + 2 + IV_SIZE ) - (MAC_SIZE + FECF_SIZE) ); + int seg_hdr = 0;if(SEGMENTATION_HDR){seg_hdr=1;} + int fecf = 0;if(HAS_FECF){fecf=FECF_SIZE;} + int pus_hdr = 0; if(PUS_HDR){pus_hdr=9;} //Why do we need this? Shouldn't it just be part of the TC data? + int tf_hdr = 5; + + return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + pus_hdr + IV_SIZE_TC ) - (MAC_SIZE + FECF_SIZE) ); + //return (tc_frame->tc_header.fl - (5 + 2 + IV_SIZE ) - (MAC_SIZE + FECF_SIZE) ); + //TFHDR=5bytes, SegHdr=1byte,SPI=2bytes,SeqNum=4bytes,MAC=16bytes,FECF=2bytes -- should be 30 bytes max, above calculation seems incorrect. } static int32 Crypto_Get_tmLength(int len) @@ -1052,7 +1058,7 @@ static uint8 Crypto_Prep_Reply(char* ingest, uint8 appID) return count; } -static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest) +static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame) // Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) { int32 result = OS_SUCCESS; @@ -1079,7 +1085,7 @@ static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest) log.blk[log_count++].em_len = 4; } #ifdef FECF_DEBUG - OS_printf("\t Calculated = 0x%04x \n\t Received = 0x%04x \n", calc_fecf, tc_frame.tc_sec_trailer.fecf); + OS_printf("\t Calculated = 0x%04x \n\t Received = 0x%04x \n", calc_fecf, tc_frame->tc_sec_trailer.fecf); #endif result = OS_ERROR; } @@ -1445,7 +1451,7 @@ static int32 Crypto_Key_inventory(char* ingest) return count; } -static int32 Crypto_Key_verify(char* ingest) +static int32 Crypto_Key_verify(char* ingest,TC_t* tc_frame) { // Local variables SDLS_KEYV_CMD_t packet; @@ -1495,7 +1501,7 @@ static int32 Crypto_Key_verify(char* ingest) iv_loc = count; for (int y = 0; y < IV_SIZE; y++) { - ingest[count++] = tc_frame.tc_sec_header.iv[y]; + ingest[count++] = tc_frame->tc_sec_header.iv[y]; } ingest[count-1] = ingest[count-1] + x + 1; @@ -1571,7 +1577,7 @@ static int32 Crypto_Key_verify(char* ingest) /* ** Security Association Management Services */ -static int32 Crypto_SA_start(void) +static int32 Crypto_SA_start(TC_t* tc_frame) { // Local variables uint8 count = 0; @@ -1602,7 +1608,7 @@ static int32 Crypto_SA_start(void) gvcid.mapid = (sdls_frame.pdu.data[count + 3]); // TC - if (gvcid.vcid != tc_frame.tc_header.vcid) + if (gvcid.vcid != tc_frame->tc_header.vcid) { // Clear all GVCIDs for provided SPI if (gvcid.mapid == TYPE_TC) { @@ -2384,7 +2390,7 @@ static int32 Crypto_User_ModifyVCID(void) /* ** Procedures Specifications */ -static int32 Crypto_PDU(char* ingest) +static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) { int32 status = OS_SUCCESS; @@ -2421,7 +2427,7 @@ static int32 Crypto_PDU(char* ingest) #ifdef PDU_DEBUG OS_printf(KGRN "Key Verify\n" RESET); #endif - status = Crypto_Key_verify(ingest); + status = Crypto_Key_verify(ingest,tc_frame); break; case PID_KEY_DESTRUCTION: #ifdef PDU_DEBUG @@ -2483,7 +2489,7 @@ static int32 Crypto_PDU(char* ingest) #ifdef PDU_DEBUG OS_printf(KGRN "SA Start\n" RESET); #endif - status = Crypto_SA_start(); + status = Crypto_SA_start(tc_frame); break; case PID_STOP_SA: #ifdef PDU_DEBUG @@ -2688,8 +2694,8 @@ int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest) return status; } -int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) -// Loads the ingest frame into the global tc_frame while performing decrpytion +int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_processed_frame) +// Loads the ingest frame into the global tc_frame while performing decryption { // Local Variables int32 status = OS_SUCCESS; @@ -2702,37 +2708,47 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) OS_printf(KYEL "\n----- Crypto_TC_ProcessSecurity START -----\n" RESET); #endif + int byte_idx = 0; // Primary Header - tc_frame.tc_header.tfvn = ((uint8)ingest[0] & 0xC0) >> 6; - tc_frame.tc_header.bypass = ((uint8)ingest[0] & 0x20) >> 5; - tc_frame.tc_header.cc = ((uint8)ingest[0] & 0x10) >> 4; - tc_frame.tc_header.spare = ((uint8)ingest[0] & 0x0C) >> 2; - tc_frame.tc_header.scid = ((uint8)ingest[0] & 0x03) << 8; - tc_frame.tc_header.scid = tc_frame.tc_header.scid | (uint8)ingest[1]; - tc_frame.tc_header.vcid = ((uint8)ingest[2] & 0xFC) >> 2; - tc_frame.tc_header.fl = ((uint8)ingest[2] & 0x03) << 8; - tc_frame.tc_header.fl = tc_frame.tc_header.fl | (uint8)ingest[3]; - tc_frame.tc_header.fsn = (uint8)ingest[4]; + tc_sdls_processed_frame->tc_header.tfvn = ((uint8)ingest[byte_idx] & 0xC0) >> 6; + tc_sdls_processed_frame->tc_header.bypass = ((uint8)ingest[byte_idx] & 0x20) >> 5; + tc_sdls_processed_frame->tc_header.cc = ((uint8)ingest[byte_idx] & 0x10) >> 4; + tc_sdls_processed_frame->tc_header.spare = ((uint8)ingest[byte_idx] & 0x0C) >> 2; + tc_sdls_processed_frame->tc_header.scid = ((uint8)ingest[byte_idx] & 0x03) << 8; + byte_idx++; + tc_sdls_processed_frame->tc_header.scid = tc_sdls_processed_frame->tc_header.scid | (uint8)ingest[byte_idx]; + byte_idx++; + tc_sdls_processed_frame->tc_header.vcid = (((uint8)ingest[byte_idx] & 0xFC) >> 2) & VCID_BITMASK; + tc_sdls_processed_frame->tc_header.fl = ((uint8)ingest[byte_idx] & 0x03) << 8; + byte_idx++; + tc_sdls_processed_frame->tc_header.fl = tc_sdls_processed_frame->tc_header.fl | (uint8)ingest[byte_idx]; + byte_idx++; + tc_sdls_processed_frame->tc_header.fsn = (uint8)ingest[byte_idx]; + byte_idx++; // Security Header - tc_frame.tc_sec_header.sh = (uint8)ingest[5]; - tc_frame.tc_sec_header.spi = ((uint8)ingest[6] << 8) | (uint8)ingest[7]; + if(SEGMENTATION_HDR){ + tc_sdls_processed_frame->tc_sec_header.sh = (uint8)ingest[byte_idx]; + byte_idx++; + } + tc_sdls_processed_frame->tc_sec_header.spi = ((uint8)ingest[byte_idx] << 8) | (uint8)ingest[byte_idx+1]; + byte_idx+=2; #ifdef TC_DEBUG - OS_printf("vcid = %d \n", tc_frame.tc_header.vcid ); - OS_printf("spi = %d \n", tc_frame.tc_sec_header.spi); + OS_printf("vcid = %d \n", tc_sdls_processed_frame->tc_header.vcid ); + OS_printf("spi = %d \n", tc_sdls_processed_frame->tc_sec_header.spi); #endif // Checks - if (((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) + if (PUS_HDR && ((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) { // User packet check only used for ESA Testing! } else { // Update last spi used - report.lspiu = tc_frame.tc_sec_header.spi; + report.lspiu = tc_sdls_processed_frame->tc_sec_header.spi; // Verify - if (tc_frame.tc_header.scid != (SCID & 0x3FF)) + if (tc_sdls_processed_frame->tc_header.scid != (SCID & 0x3FF)) { OS_printf(KRED "Error: SCID incorrect! \n" RESET); status = OS_ERROR; @@ -2751,6 +2767,8 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) break; } } + + if ((report.lspiu > NUM_SA) && (status == OS_SUCCESS)) { report.ispif = 1; @@ -2759,7 +2777,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) } if (status == OS_SUCCESS) { - if (sa[report.lspiu].gvcid_tc_blk[tc_frame.tc_header.vcid].mapid != TYPE_TC) + if (sa[report.lspiu].gvcid_tc_blk[tc_sdls_processed_frame->tc_header.vcid].mapid != TYPE_TC) { OS_printf(KRED "Error: SA invalid type! \n" RESET); status = OS_ERROR; @@ -2768,7 +2786,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) // TODO: I don't think this is needed. //if (status == OS_SUCCESS) //{ - // if (sa[report.lspiu].gvcid_tc_blk[tc_frame.tc_header.vcid].vcid != tc_frame.tc_header.vcid) + // if (sa[report.lspiu].gvcid_tc_blk[tc_sdls_processed_frame->tc_header.vcid].vcid != tc_sdls_processed_frame->tc_header.vcid) // { // OS_printf(KRED "Error: VCID not mapped to provided SPI! \n" RESET); // status = OS_ERROR; @@ -2802,8 +2820,8 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) } // Determine mode via SPI - if ((sa[tc_frame.tc_sec_header.spi].est == 1) && - (sa[tc_frame.tc_sec_header.spi].ast == 1)) + if ((sa[tc_sdls_processed_frame->tc_sec_header.spi].est == 1) && + (sa[tc_sdls_processed_frame->tc_sec_header.spi].ast == 1)) { // Authenticated Encryption #ifdef DEBUG OS_printf(KBLU "ENCRYPTED TC Received!\n" RESET); @@ -2811,23 +2829,24 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) #ifdef TC_DEBUG OS_printf("IV: \n"); #endif - for (x = 8; x < (8 + IV_SIZE); x++) + for (x = byte_idx; x < (byte_idx + IV_SIZE); x++) { - tc_frame.tc_sec_header.iv[x-8] = (uint8)ingest[x]; + tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; #ifdef TC_DEBUG - OS_printf("\t iv[%d] = 0x%02x\n", x-8, tc_frame.tc_sec_header.iv[x-8]); + OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); #endif } - report.snval = tc_frame.tc_sec_header.iv[IV_SIZE-1]; + byte_idx += IV_SIZE; + report.snval = tc_sdls_processed_frame->tc_sec_header.iv[IV_SIZE-1]; #ifdef DEBUG - OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", IV_SIZE-1, tc_frame.tc_sec_header.iv[IV_SIZE-1]); - OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_frame.tc_sec_header.spi, IV_SIZE-1, sa[tc_frame.tc_sec_header.spi].iv[IV_SIZE-1]); + OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", IV_SIZE-1, tc_sdls_processed_frame->tc_sec_header.iv[IV_SIZE-1]); + OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, IV_SIZE-1, sa[tc_sdls_processed_frame->tc_sec_header.spi].iv[IV_SIZE-1]); #endif // Check IV is in ARCW - if ( Crypto_window(tc_frame.tc_sec_header.iv, sa[tc_frame.tc_sec_header.spi].iv, IV_SIZE, - sa[tc_frame.tc_sec_header.spi].arcw[sa[tc_frame.tc_sec_header.spi].arcw_len-1]) != OS_SUCCESS ) + if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa[tc_sdls_processed_frame->tc_sec_header.spi].iv, IV_SIZE, + sa[tc_sdls_processed_frame->tc_sec_header.spi].arcw[sa[tc_sdls_processed_frame->tc_sec_header.spi].arcw_len-1]) != OS_SUCCESS ) { report.af = 1; report.bsnf = 1; @@ -2850,7 +2869,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) } else { - if ( Crypto_compare_less_equal(tc_frame.tc_sec_header.iv, sa[tc_frame.tc_sec_header.spi].iv, IV_SIZE) == OS_SUCCESS ) + if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa[tc_sdls_processed_frame->tc_sec_header.spi].iv, IV_SIZE) == OS_SUCCESS ) { // Replay - IV value lower than expected report.af = 1; report.bsnf = 1; @@ -2875,7 +2894,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) { // Adjust expected IV to acceptable received value for (int i = 0; i < (IV_SIZE); i++) { - sa[tc_frame.tc_sec_header.spi].iv[i] = tc_frame.tc_sec_header.iv[i]; + sa[tc_sdls_processed_frame->tc_sec_header.spi].iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; } } } @@ -2886,11 +2905,13 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) return status; } - x = x + Crypto_Get_tcPayloadLength(); + tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame); + + x = x + tc_sdls_processed_frame->tc_pdu_len; #ifdef TC_DEBUG OS_printf("TC: \n"); - for (int temp = 0; temp < Crypto_Get_tcPayloadLength(); temp++) + for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) { OS_printf("\t ingest[%d] = 0x%02x \n", temp, (uint8)ingest[temp+20]); } @@ -2902,19 +2923,19 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) #endif for (y = x; y < (x + MAC_SIZE); y++) { - tc_frame.tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; + tc_sdls_processed_frame->tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; #ifdef TC_DEBUG - OS_printf("\t mac[%d] = 0x%02x\n", y-x, tc_frame.tc_sec_trailer.mac[y-x]); + OS_printf("\t mac[%d] = 0x%02x\n", y-x, tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); #endif } x = x + MAC_SIZE; // FECF - tc_frame.tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); - Crypto_FECF(tc_frame.tc_sec_trailer.fecf, ingest, (tc_frame.tc_header.fl - 2)); + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); + Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 2),tc_sdls_processed_frame); // Initialize the key - //itc_gcm128_init(&sa[tc_frame.tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[tc_frame.tc_sec_header.spi].ekid]); + //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[tc_sdls_processed_frame->tc_sec_header.spi].ekid]); gcry_error = gcry_cipher_open( &(tmp_hd), @@ -2929,16 +2950,16 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) return status; } #ifdef DEBUG - OS_printf("Key ID = %d, 0x", sa[tc_frame.tc_sec_header.spi].ekid); + OS_printf("Key ID = %d, 0x", sa[tc_sdls_processed_frame->tc_sec_header.spi].ekid); for(int y = 0; y < KEY_SIZE; y++) { - OS_printf("%02x", ek_ring[sa[tc_frame.tc_sec_header.spi].ekid].value[y]); + OS_printf("%02x", ek_ring[sa[tc_sdls_processed_frame->tc_sec_header.spi].ekid].value[y]); } OS_printf("\n"); #endif gcry_error = gcry_cipher_setkey( tmp_hd, - &(ek_ring[sa[tc_frame.tc_sec_header.spi].ekid].value[0]), + &(ek_ring[sa[tc_sdls_processed_frame->tc_sec_header.spi].ekid].value[0]), KEY_SIZE ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -2949,8 +2970,8 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) } gcry_error = gcry_cipher_setiv( tmp_hd, - &(sa[tc_frame.tc_sec_header.spi].iv[0]), - sa[tc_frame.tc_sec_header.spi].iv_len + &(sa[tc_sdls_processed_frame->tc_sec_header.spi].iv[0]), + sa[tc_sdls_processed_frame->tc_sec_header.spi].iv_len ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { @@ -2962,9 +2983,9 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) OS_printf("AAD = 0x"); #endif // Prepare additional authenticated data (AAD) - for (y = 0; y < sa[tc_frame.tc_sec_header.spi].abm_len; y++) + for (y = 0; y < sa[tc_sdls_processed_frame->tc_sec_header.spi].abm_len; y++) { - ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa[tc_frame.tc_sec_header.spi].abm[y]); + ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa[tc_sdls_processed_frame->tc_sec_header.spi].abm[y]); #ifdef MAC_DEBUG OS_printf("%02x", (uint8) ingest[y]); #endif @@ -2975,10 +2996,10 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) gcry_error = gcry_cipher_decrypt( tmp_hd, - &(tc_frame.tc_pdu[0]), // plaintext output - Crypto_Get_tcPayloadLength(), // length of data + &(tc_sdls_processed_frame->tc_pdu[0]), // plaintext output + tc_sdls_processed_frame->tc_pdu_len, // length of data &(ingest[20]), // ciphertext input - Crypto_Get_tcPayloadLength() // in data length + tc_sdls_processed_frame->tc_pdu_len // in data length ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { @@ -2988,7 +3009,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) } gcry_error = gcry_cipher_checktag( tmp_hd, - &(tc_frame.tc_sec_trailer.mac[0]), // tag input + &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag input MAC_SIZE // tag size ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -2998,13 +3019,13 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) OS_printf("Actual MAC = 0x"); for (int z = 0; z < MAC_SIZE; z++) { - OS_printf("%02x",tc_frame.tc_sec_trailer.mac[z]); + OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); } OS_printf("\n"); gcry_error = gcry_cipher_gettag( tmp_hd, - &(tc_frame.tc_sec_trailer.mac[0]), // tag output + &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output MAC_SIZE // tag size ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -3015,7 +3036,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) OS_printf("Expected MAC = 0x"); for (int z = 0; z < MAC_SIZE; z++) { - OS_printf("%02x",tc_frame.tc_sec_trailer.mac[z]); + OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); } OS_printf("\n"); status = OS_ERROR; @@ -3029,7 +3050,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) // Increment the IV for next time #ifdef INCREMENT - Crypto_increment(sa[tc_frame.tc_sec_header.spi].iv, IV_SIZE); + Crypto_increment(sa[tc_sdls_processed_frame->tc_sec_header.spi].iv, IV_SIZE); #endif } else @@ -3038,17 +3059,17 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) OS_printf(KBLU "CLEAR TC Received!\n" RESET); #endif - for (y = 10; y <= (tc_frame.tc_header.fl - 2); y++) + for (y = 10; y <= (tc_sdls_processed_frame->tc_header.fl - 2); y++) //tfhdr+seghdr+sechdr=5+1+6=12 { - tc_frame.tc_pdu[y - 10] = (uint8)ingest[y]; + tc_sdls_processed_frame->tc_pdu[y - 10] = (uint8)ingest[y]; } // FECF - tc_frame.tc_sec_trailer.fecf = ((uint8)ingest[y] << 8) | ((uint8)ingest[y+1]); - Crypto_FECF((int) tc_frame.tc_sec_trailer.fecf, ingest, (tc_frame.tc_header.fl - 2)); + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[y] << 8) | ((uint8)ingest[y+1]); + Crypto_FECF((int) tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 2),tc_sdls_processed_frame); } #ifdef TC_DEBUG - Crypto_tcPrint(&tc_frame); + Crypto_tcPrint(tc_sdls_processed_frame); #endif // Zero ingest @@ -3056,64 +3077,108 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) { ingest[x] = 0; } - - if ((tc_frame.tc_pdu[0] == 0x18) && (tc_frame.tc_pdu[1] == 0x80)) - // Crypto Lib Application ID + + + if(!TC_PROCESS_SDLS_PDUS) //If we don't want to process frame data for SDLS PDUs, only reverse security & return content. { + // CCSDS Pass-through #ifdef DEBUG - OS_printf(KGRN "Received SDLS command: " RESET); + OS_printf(KGRN "CCSDS Pass-through \n" RESET); #endif - // CCSDS Header - sdls_frame.hdr.pvn = (tc_frame.tc_pdu[0] & 0xE0) >> 5; - sdls_frame.hdr.type = (tc_frame.tc_pdu[0] & 0x10) >> 4; - sdls_frame.hdr.shdr = (tc_frame.tc_pdu[0] & 0x08) >> 3; - sdls_frame.hdr.appID = ((tc_frame.tc_pdu[0] & 0x07) << 8) | tc_frame.tc_pdu[1]; - sdls_frame.hdr.seq = (tc_frame.tc_pdu[2] & 0xC0) >> 6; - sdls_frame.hdr.pktid = ((tc_frame.tc_pdu[2] & 0x3F) << 8) | tc_frame.tc_pdu[3]; - sdls_frame.hdr.pkt_length = (tc_frame.tc_pdu[4] << 8) | tc_frame.tc_pdu[5]; - - // CCSDS PUS - sdls_frame.pus.shf = (tc_frame.tc_pdu[6] & 0x80) >> 7; - sdls_frame.pus.pusv = (tc_frame.tc_pdu[6] & 0x70) >> 4; - sdls_frame.pus.ack = (tc_frame.tc_pdu[6] & 0x0F); - sdls_frame.pus.st = tc_frame.tc_pdu[7]; - sdls_frame.pus.sst = tc_frame.tc_pdu[8]; - sdls_frame.pus.sid = (tc_frame.tc_pdu[9] & 0xF0) >> 4; - sdls_frame.pus.spare = (tc_frame.tc_pdu[9] & 0x0F); - - // SDLS TLV PDU - sdls_frame.pdu.type = (tc_frame.tc_pdu[10] & 0x80) >> 7; - sdls_frame.pdu.uf = (tc_frame.tc_pdu[10] & 0x40) >> 6; - sdls_frame.pdu.sg = (tc_frame.tc_pdu[10] & 0x30) >> 4; - sdls_frame.pdu.pid = (tc_frame.tc_pdu[10] & 0x0F); - sdls_frame.pdu.pdu_len = (tc_frame.tc_pdu[11] << 8) | tc_frame.tc_pdu[12]; - for (x = 13; x < (13 + sdls_frame.hdr.pkt_length); x++) - { - sdls_frame.pdu.data[x-13] = tc_frame.tc_pdu[x]; + if (PUS_HDR) { + for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl - 11); x++) { + ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; + #ifdef CCSDS_DEBUG + OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); + #endif + *len_ingest = x; + } + } else { + for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl); x++) { //with no PUS header, entire PDU is data + ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; + #ifdef CCSDS_DEBUG + OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); + #endif + *len_ingest = x; + } } - - #ifdef CCSDS_DEBUG - Crypto_ccsdsPrint(&sdls_frame); - #endif - - // Determine type of PDU - *len_ingest = Crypto_PDU(ingest); } - else - { // CCSDS Pass-through - #ifdef DEBUG - OS_printf(KGRN "CCSDS Pass-through \n" RESET); - #endif - // TODO: Remove PUS Header - for (x = 0; x < (tc_frame.tc_header.fl - 11); x++) + else //Process SDLS PDU + { + if (PUS_HDR) + { + if ((tc_sdls_processed_frame->tc_pdu[0] == 0x18) && (tc_sdls_processed_frame->tc_pdu[1] == 0x80)) + // Crypto Lib Application ID + { + #ifdef DEBUG + OS_printf(KGRN "Received SDLS command: " RESET); + #endif + // CCSDS Header + sdls_frame.hdr.pvn = (tc_sdls_processed_frame->tc_pdu[0] & 0xE0) >> 5; + sdls_frame.hdr.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x10) >> 4; + sdls_frame.hdr.shdr = (tc_sdls_processed_frame->tc_pdu[0] & 0x08) >> 3; + sdls_frame.hdr.appID = + ((tc_sdls_processed_frame->tc_pdu[0] & 0x07) << 8) | tc_sdls_processed_frame->tc_pdu[1]; + sdls_frame.hdr.seq = (tc_sdls_processed_frame->tc_pdu[2] & 0xC0) >> 6; + sdls_frame.hdr.pktid = + ((tc_sdls_processed_frame->tc_pdu[2] & 0x3F) << 8) | tc_sdls_processed_frame->tc_pdu[3]; + sdls_frame.hdr.pkt_length = (tc_sdls_processed_frame->tc_pdu[4] << 8) | tc_sdls_processed_frame->tc_pdu[5]; + + // CCSDS PUS + sdls_frame.pus.shf = (tc_sdls_processed_frame->tc_pdu[6] & 0x80) >> 7; + sdls_frame.pus.pusv = (tc_sdls_processed_frame->tc_pdu[6] & 0x70) >> 4; + sdls_frame.pus.ack = (tc_sdls_processed_frame->tc_pdu[6] & 0x0F); + sdls_frame.pus.st = tc_sdls_processed_frame->tc_pdu[7]; + sdls_frame.pus.sst = tc_sdls_processed_frame->tc_pdu[8]; + sdls_frame.pus.sid = (tc_sdls_processed_frame->tc_pdu[9] & 0xF0) >> 4; + sdls_frame.pus.spare = (tc_sdls_processed_frame->tc_pdu[9] & 0x0F); + + // SDLS TLV PDU + sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[10] & 0x80) >> 7; + sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[10] & 0x40) >> 6; + sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[10] & 0x30) >> 4; + sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[10] & 0x0F); + sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[11] << 8) | tc_sdls_processed_frame->tc_pdu[12]; + for (x = 13; x < (13 + sdls_frame.hdr.pkt_length); x++) { + sdls_frame.pdu.data[x - 13] = tc_sdls_processed_frame->tc_pdu[x]; + } + + #ifdef CCSDS_DEBUG + Crypto_ccsdsPrint(&sdls_frame); + #endif + + // Determine type of PDU + *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); + } + } + else if (tc_sdls_processed_frame->tc_header.vcid == TC_SDLS_EP_VCID) //TC SDLS PDU with no packet layer { - ingest[x] = tc_frame.tc_pdu[x]; + #ifdef DEBUG + OS_printf(KGRN "Received SDLS command: " RESET); + #endif + // No Packet HDR or PUS in these frames + // SDLS TLV PDU + sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x80) >> 7; + sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[0] & 0x40) >> 6; + sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[0] & 0x30) >> 4; + sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[0] & 0x0F); + sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[1] << 8) | tc_sdls_processed_frame->tc_pdu[2]; + for (x = 3; x < (3 + tc_sdls_processed_frame->tc_header.fl); x++) { + //Todo - Consider how this behaves with large OTAR PDUs that are larger than 1 TC in size. Most likely fails. Must consider Uplink Sessions (sequence numbers). + sdls_frame.pdu.data[x - 3] = tc_sdls_processed_frame->tc_pdu[x]; + } + #ifdef CCSDS_DEBUG - OS_printf("tc_frame.tc_pdu[%d] = 0x%02x\n", x, tc_frame.tc_pdu[x]); + Crypto_ccsdsPrint(&sdls_frame); #endif + + // Determine type of PDU + *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); } - *len_ingest = x; - } + else { + //TODO - Process SDLS PDU with Packet Layer without PUS_HDR + } + }//End Process SDLS PDU #ifdef OCF_DEBUG Crypto_fsrPrint(&report); @@ -3126,7 +3191,6 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest) return status; } - int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) // Accepts CCSDS message in ingest, and packs into TM before encryption { From c88c964c24b252eb56b58c839602d84ad70509cb Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Fri, 15 Oct 2021 12:21:45 -0700 Subject: [PATCH 006/184] AKMC-105: Free memory used to store processed frame data in utility apps --- fsw/crypto_util/app/crypto_sequence.c | 1 + fsw/crypto_util/app/process_security.c | 1 + 2 files changed, 2 insertions(+) diff --git a/fsw/crypto_util/app/crypto_sequence.c b/fsw/crypto_util/app/crypto_sequence.c index 8e61bc46..8c55c563 100644 --- a/fsw/crypto_util/app/crypto_sequence.c +++ b/fsw/crypto_util/app/crypto_sequence.c @@ -64,6 +64,7 @@ int main(int argc, char *argv[]) { } else if (strcmp(security_type,"tc_p")==0){ TC_t* tc_sdls_processed_frame = malloc(sizeof(TC_t)); Crypto_TC_ProcessSecurity(buffer, &buffer_size_i,tc_sdls_processed_frame); + free(tc_sdls_processed_frame); } else if (strcmp(security_type,"tm_p")==0){ Crypto_TM_ProcessSecurity(buffer, &buffer_size_i); } else if (strcmp(security_type,"aos_p")==0){ diff --git a/fsw/crypto_util/app/process_security.c b/fsw/crypto_util/app/process_security.c index 330ec7fe..37682c70 100644 --- a/fsw/crypto_util/app/process_security.c +++ b/fsw/crypto_util/app/process_security.c @@ -54,6 +54,7 @@ int main(int argc, char *argv[]) { if (strcmp(security_type,"tc")==0){ TC_t* tc_sdls_processed_frame = malloc(sizeof(TC_t)); Crypto_TC_ProcessSecurity(buffer, &buffer_size_i,tc_sdls_processed_frame); + free(tc_sdls_processed_frame); } else if (strcmp(security_type,"tm")==0){ Crypto_TM_ProcessSecurity(buffer, &buffer_size_i); } else if (strcmp(security_type,"aos")==0){ From 508243712e1d1a057a401160b26ba076539192a1 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Mon, 18 Oct 2021 09:10:17 -0700 Subject: [PATCH 007/184] AKMC-105: change TC payloadLength calculation to account for PUS_HDR interop test frames --- fsw/src/crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index d40ffca3..301f0a51 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -772,10 +772,10 @@ static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame) { int seg_hdr = 0;if(SEGMENTATION_HDR){seg_hdr=1;} int fecf = 0;if(HAS_FECF){fecf=FECF_SIZE;} - int pus_hdr = 0; if(PUS_HDR){pus_hdr=9;} //Why do we need this? Shouldn't it just be part of the TC data? + int iv_size = IV_SIZE_TC; if(PUS_HDR){iv_size=IV_SIZE;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. int tf_hdr = 5; - return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + pus_hdr + IV_SIZE_TC ) - (MAC_SIZE + FECF_SIZE) ); + return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + iv_size ) - (MAC_SIZE + FECF_SIZE) ); //return (tc_frame->tc_header.fl - (5 + 2 + IV_SIZE ) - (MAC_SIZE + FECF_SIZE) ); //TFHDR=5bytes, SegHdr=1byte,SPI=2bytes,SeqNum=4bytes,MAC=16bytes,FECF=2bytes -- should be 30 bytes max, above calculation seems incorrect. } From ba3e1c642bd9fbb0cbe947e12653f94c989f160a Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Mon, 18 Oct 2021 09:25:14 -0700 Subject: [PATCH 008/184] AKMC-105: Add SPI to calculation and PUS_HDR adjustments --- fsw/src/crypto.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 301f0a51..87ecb1a8 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -772,10 +772,11 @@ static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame) { int seg_hdr = 0;if(SEGMENTATION_HDR){seg_hdr=1;} int fecf = 0;if(HAS_FECF){fecf=FECF_SIZE;} - int iv_size = IV_SIZE_TC; if(PUS_HDR){iv_size=IV_SIZE;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. + int spi = 2; + int iv_size = IV_SIZE_TC; if(PUS_HDR){iv_size=IV_SIZE - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. int tf_hdr = 5; - return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + iv_size ) - (MAC_SIZE + FECF_SIZE) ); + return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (MAC_SIZE + FECF_SIZE) ); //return (tc_frame->tc_header.fl - (5 + 2 + IV_SIZE ) - (MAC_SIZE + FECF_SIZE) ); //TFHDR=5bytes, SegHdr=1byte,SPI=2bytes,SeqNum=4bytes,MAC=16bytes,FECF=2bytes -- should be 30 bytes max, above calculation seems incorrect. } From d2e600f0419c08ff810e781deaeaca41d9965493 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Tue, 26 Oct 2021 11:44:18 -0700 Subject: [PATCH 009/184] AKMC-113: Change inmemory keyring initialization location --- fsw/src/crypto.c | 344 +++++++++++++++++++++++ fsw/src/sadb_routine_inmemory.template.c | 343 ---------------------- 2 files changed, 344 insertions(+), 343 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index e88c58a3..f87c9218 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -179,6 +179,350 @@ static void Crypto_Local_Config(void) log.blk[log_count].emv[2] = 0x53; log.blk[log_count].emv[3] = 0x41; log.blk[log_count++].em_len = 4; + + // Master Keys + // 0 - 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F -> ACTIVE + ek_ring[0].value[0] = 0x00; + ek_ring[0].value[1] = 0x01; + ek_ring[0].value[2] = 0x02; + ek_ring[0].value[3] = 0x03; + ek_ring[0].value[4] = 0x04; + ek_ring[0].value[5] = 0x05; + ek_ring[0].value[6] = 0x06; + ek_ring[0].value[7] = 0x07; + ek_ring[0].value[8] = 0x08; + ek_ring[0].value[9] = 0x09; + ek_ring[0].value[10] = 0x0A; + ek_ring[0].value[11] = 0x0B; + ek_ring[0].value[12] = 0x0C; + ek_ring[0].value[13] = 0x0D; + ek_ring[0].value[14] = 0x0E; + ek_ring[0].value[15] = 0x0F; + ek_ring[0].value[16] = 0x00; + ek_ring[0].value[17] = 0x01; + ek_ring[0].value[18] = 0x02; + ek_ring[0].value[19] = 0x03; + ek_ring[0].value[20] = 0x04; + ek_ring[0].value[21] = 0x05; + ek_ring[0].value[22] = 0x06; + ek_ring[0].value[23] = 0x07; + ek_ring[0].value[24] = 0x08; + ek_ring[0].value[25] = 0x09; + ek_ring[0].value[26] = 0x0A; + ek_ring[0].value[27] = 0x0B; + ek_ring[0].value[28] = 0x0C; + ek_ring[0].value[29] = 0x0D; + ek_ring[0].value[30] = 0x0E; + ek_ring[0].value[31] = 0x0F; + ek_ring[0].key_state = KEY_ACTIVE; + // 1 - 101112131415161718191A1B1C1D1E1F101112131415161718191A1B1C1D1E1F -> ACTIVE + ek_ring[1].value[0] = 0x10; + ek_ring[1].value[1] = 0x11; + ek_ring[1].value[2] = 0x12; + ek_ring[1].value[3] = 0x13; + ek_ring[1].value[4] = 0x14; + ek_ring[1].value[5] = 0x15; + ek_ring[1].value[6] = 0x16; + ek_ring[1].value[7] = 0x17; + ek_ring[1].value[8] = 0x18; + ek_ring[1].value[9] = 0x19; + ek_ring[1].value[10] = 0x1A; + ek_ring[1].value[11] = 0x1B; + ek_ring[1].value[12] = 0x1C; + ek_ring[1].value[13] = 0x1D; + ek_ring[1].value[14] = 0x1E; + ek_ring[1].value[15] = 0x1F; + ek_ring[1].value[16] = 0x10; + ek_ring[1].value[17] = 0x11; + ek_ring[1].value[18] = 0x12; + ek_ring[1].value[19] = 0x13; + ek_ring[1].value[20] = 0x14; + ek_ring[1].value[21] = 0x15; + ek_ring[1].value[22] = 0x16; + ek_ring[1].value[23] = 0x17; + ek_ring[1].value[24] = 0x18; + ek_ring[1].value[25] = 0x19; + ek_ring[1].value[26] = 0x1A; + ek_ring[1].value[27] = 0x1B; + ek_ring[1].value[28] = 0x1C; + ek_ring[1].value[29] = 0x1D; + ek_ring[1].value[30] = 0x1E; + ek_ring[1].value[31] = 0x1F; + ek_ring[1].key_state = KEY_ACTIVE; + // 2 - 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F -> ACTIVE + ek_ring[2].value[0] = 0x20; + ek_ring[2].value[1] = 0x21; + ek_ring[2].value[2] = 0x22; + ek_ring[2].value[3] = 0x23; + ek_ring[2].value[4] = 0x24; + ek_ring[2].value[5] = 0x25; + ek_ring[2].value[6] = 0x26; + ek_ring[2].value[7] = 0x27; + ek_ring[2].value[8] = 0x28; + ek_ring[2].value[9] = 0x29; + ek_ring[2].value[10] = 0x2A; + ek_ring[2].value[11] = 0x2B; + ek_ring[2].value[12] = 0x2C; + ek_ring[2].value[13] = 0x2D; + ek_ring[2].value[14] = 0x2E; + ek_ring[2].value[15] = 0x2F; + ek_ring[2].value[16] = 0x20; + ek_ring[2].value[17] = 0x21; + ek_ring[2].value[18] = 0x22; + ek_ring[2].value[19] = 0x23; + ek_ring[2].value[20] = 0x24; + ek_ring[2].value[21] = 0x25; + ek_ring[2].value[22] = 0x26; + ek_ring[2].value[23] = 0x27; + ek_ring[2].value[24] = 0x28; + ek_ring[2].value[25] = 0x29; + ek_ring[2].value[26] = 0x2A; + ek_ring[2].value[27] = 0x2B; + ek_ring[2].value[28] = 0x2C; + ek_ring[2].value[29] = 0x2D; + ek_ring[2].value[30] = 0x2E; + ek_ring[2].value[31] = 0x2F; + ek_ring[2].key_state = KEY_ACTIVE; + + // Session Keys + // 128 - 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -> ACTIVE + ek_ring[128].value[0] = 0x01; + ek_ring[128].value[1] = 0x23; + ek_ring[128].value[2] = 0x45; + ek_ring[128].value[3] = 0x67; + ek_ring[128].value[4] = 0x89; + ek_ring[128].value[5] = 0xAB; + ek_ring[128].value[6] = 0xCD; + ek_ring[128].value[7] = 0xEF; + ek_ring[128].value[8] = 0x01; + ek_ring[128].value[9] = 0x23; + ek_ring[128].value[10] = 0x45; + ek_ring[128].value[11] = 0x67; + ek_ring[128].value[12] = 0x89; + ek_ring[128].value[13] = 0xAB; + ek_ring[128].value[14] = 0xCD; + ek_ring[128].value[15] = 0xEF; + ek_ring[128].value[16] = 0x01; + ek_ring[128].value[17] = 0x23; + ek_ring[128].value[18] = 0x45; + ek_ring[128].value[19] = 0x67; + ek_ring[128].value[20] = 0x89; + ek_ring[128].value[21] = 0xAB; + ek_ring[128].value[22] = 0xCD; + ek_ring[128].value[23] = 0xEF; + ek_ring[128].value[24] = 0x01; + ek_ring[128].value[25] = 0x23; + ek_ring[128].value[26] = 0x45; + ek_ring[128].value[27] = 0x67; + ek_ring[128].value[28] = 0x89; + ek_ring[128].value[29] = 0xAB; + ek_ring[128].value[30] = 0xCD; + ek_ring[128].value[31] = 0xEF; + ek_ring[128].key_state = KEY_ACTIVE; + // 129 - ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 -> ACTIVE + ek_ring[129].value[0] = 0xAB; + ek_ring[129].value[1] = 0xCD; + ek_ring[129].value[2] = 0xEF; + ek_ring[129].value[3] = 0x01; + ek_ring[129].value[4] = 0x23; + ek_ring[129].value[5] = 0x45; + ek_ring[129].value[6] = 0x67; + ek_ring[129].value[7] = 0x89; + ek_ring[129].value[8] = 0xAB; + ek_ring[129].value[9] = 0xCD; + ek_ring[129].value[10] = 0xEF; + ek_ring[129].value[11] = 0x01; + ek_ring[129].value[12] = 0x23; + ek_ring[129].value[13] = 0x45; + ek_ring[129].value[14] = 0x67; + ek_ring[129].value[15] = 0x89; + ek_ring[129].value[16] = 0xAB; + ek_ring[129].value[17] = 0xCD; + ek_ring[129].value[18] = 0xEF; + ek_ring[129].value[19] = 0x01; + ek_ring[129].value[20] = 0x23; + ek_ring[129].value[21] = 0x45; + ek_ring[129].value[22] = 0x67; + ek_ring[129].value[23] = 0x89; + ek_ring[129].value[24] = 0xAB; + ek_ring[129].value[25] = 0xCD; + ek_ring[129].value[26] = 0xEF; + ek_ring[129].value[27] = 0x01; + ek_ring[129].value[28] = 0x23; + ek_ring[129].value[29] = 0x45; + ek_ring[129].value[30] = 0x67; + ek_ring[129].value[31] = 0x89; + ek_ring[129].key_state = KEY_ACTIVE; + // 130 - FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210 -> ACTIVE + ek_ring[130].value[0] = 0xFE; + ek_ring[130].value[1] = 0xDC; + ek_ring[130].value[2] = 0xBA; + ek_ring[130].value[3] = 0x98; + ek_ring[130].value[4] = 0x76; + ek_ring[130].value[5] = 0x54; + ek_ring[130].value[6] = 0x32; + ek_ring[130].value[7] = 0x10; + ek_ring[130].value[8] = 0xFE; + ek_ring[130].value[9] = 0xDC; + ek_ring[130].value[10] = 0xBA; + ek_ring[130].value[11] = 0x98; + ek_ring[130].value[12] = 0x76; + ek_ring[130].value[13] = 0x54; + ek_ring[130].value[14] = 0x32; + ek_ring[130].value[15] = 0x10; + ek_ring[130].value[16] = 0xFE; + ek_ring[130].value[17] = 0xDC; + ek_ring[130].value[18] = 0xBA; + ek_ring[130].value[19] = 0x98; + ek_ring[130].value[20] = 0x76; + ek_ring[130].value[21] = 0x54; + ek_ring[130].value[22] = 0x32; + ek_ring[130].value[23] = 0x10; + ek_ring[130].value[24] = 0xFE; + ek_ring[130].value[25] = 0xDC; + ek_ring[130].value[26] = 0xBA; + ek_ring[130].value[27] = 0x98; + ek_ring[130].value[28] = 0x76; + ek_ring[130].value[29] = 0x54; + ek_ring[130].value[30] = 0x32; + ek_ring[130].value[31] = 0x10; + ek_ring[130].key_state = KEY_ACTIVE; + // 131 - 9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA -> ACTIVE + ek_ring[131].value[0] = 0x98; + ek_ring[131].value[1] = 0x76; + ek_ring[131].value[2] = 0x54; + ek_ring[131].value[3] = 0x32; + ek_ring[131].value[4] = 0x10; + ek_ring[131].value[5] = 0xFE; + ek_ring[131].value[6] = 0xDC; + ek_ring[131].value[7] = 0xBA; + ek_ring[131].value[8] = 0x98; + ek_ring[131].value[9] = 0x76; + ek_ring[131].value[10] = 0x54; + ek_ring[131].value[11] = 0x32; + ek_ring[131].value[12] = 0x10; + ek_ring[131].value[13] = 0xFE; + ek_ring[131].value[14] = 0xDC; + ek_ring[131].value[15] = 0xBA; + ek_ring[131].value[16] = 0x98; + ek_ring[131].value[17] = 0x76; + ek_ring[131].value[18] = 0x54; + ek_ring[131].value[19] = 0x32; + ek_ring[131].value[20] = 0x10; + ek_ring[131].value[21] = 0xFE; + ek_ring[131].value[22] = 0xDC; + ek_ring[131].value[23] = 0xBA; + ek_ring[131].value[24] = 0x98; + ek_ring[131].value[25] = 0x76; + ek_ring[131].value[26] = 0x54; + ek_ring[131].value[27] = 0x32; + ek_ring[131].value[28] = 0x10; + ek_ring[131].value[29] = 0xFE; + ek_ring[131].value[30] = 0xDC; + ek_ring[131].value[31] = 0xBA; + ek_ring[131].key_state = KEY_ACTIVE; + // 132 - 0123456789ABCDEFABCDEF01234567890123456789ABCDEFABCDEF0123456789 -> PRE_ACTIVATION + ek_ring[132].value[0] = 0x01; + ek_ring[132].value[1] = 0x23; + ek_ring[132].value[2] = 0x45; + ek_ring[132].value[3] = 0x67; + ek_ring[132].value[4] = 0x89; + ek_ring[132].value[5] = 0xAB; + ek_ring[132].value[6] = 0xCD; + ek_ring[132].value[7] = 0xEF; + ek_ring[132].value[8] = 0xAB; + ek_ring[132].value[9] = 0xCD; + ek_ring[132].value[10] = 0xEF; + ek_ring[132].value[11] = 0x01; + ek_ring[132].value[12] = 0x23; + ek_ring[132].value[13] = 0x45; + ek_ring[132].value[14] = 0x67; + ek_ring[132].value[15] = 0x89; + ek_ring[132].value[16] = 0x01; + ek_ring[132].value[17] = 0x23; + ek_ring[132].value[18] = 0x45; + ek_ring[132].value[19] = 0x67; + ek_ring[132].value[20] = 0x89; + ek_ring[132].value[21] = 0xAB; + ek_ring[132].value[22] = 0xCD; + ek_ring[132].value[23] = 0xEF; + ek_ring[132].value[24] = 0xAB; + ek_ring[132].value[25] = 0xCD; + ek_ring[132].value[26] = 0xEF; + ek_ring[132].value[27] = 0x01; + ek_ring[132].value[28] = 0x23; + ek_ring[132].value[29] = 0x45; + ek_ring[132].value[30] = 0x67; + ek_ring[132].value[31] = 0x89; + ek_ring[132].key_state = KEY_PREACTIVE; + // 133 - ABCDEF01234567890123456789ABCDEFABCDEF01234567890123456789ABCDEF -> ACTIVE + ek_ring[133].value[0] = 0xAB; + ek_ring[133].value[1] = 0xCD; + ek_ring[133].value[2] = 0xEF; + ek_ring[133].value[3] = 0x01; + ek_ring[133].value[4] = 0x23; + ek_ring[133].value[5] = 0x45; + ek_ring[133].value[6] = 0x67; + ek_ring[133].value[7] = 0x89; + ek_ring[133].value[8] = 0x01; + ek_ring[133].value[9] = 0x23; + ek_ring[133].value[10] = 0x45; + ek_ring[133].value[11] = 0x67; + ek_ring[133].value[12] = 0x89; + ek_ring[133].value[13] = 0xAB; + ek_ring[133].value[14] = 0xCD; + ek_ring[133].value[15] = 0xEF; + ek_ring[133].value[16] = 0xAB; + ek_ring[133].value[17] = 0xCD; + ek_ring[133].value[18] = 0xEF; + ek_ring[133].value[19] = 0x01; + ek_ring[133].value[20] = 0x23; + ek_ring[133].value[21] = 0x45; + ek_ring[133].value[22] = 0x67; + ek_ring[133].value[23] = 0x89; + ek_ring[133].value[24] = 0x01; + ek_ring[133].value[25] = 0x23; + ek_ring[133].value[26] = 0x45; + ek_ring[133].value[27] = 0x67; + ek_ring[133].value[28] = 0x89; + ek_ring[133].value[29] = 0xAB; + ek_ring[133].value[30] = 0xCD; + ek_ring[133].value[31] = 0xEF; + ek_ring[133].key_state = KEY_ACTIVE; + // 134 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE + ek_ring[134].value[0] = 0xAB; + ek_ring[134].value[1] = 0xCD; + ek_ring[134].value[2] = 0xEF; + ek_ring[134].value[3] = 0x01; + ek_ring[134].value[4] = 0x23; + ek_ring[134].value[5] = 0x45; + ek_ring[134].value[6] = 0x67; + ek_ring[134].value[7] = 0x89; + ek_ring[134].value[8] = 0xFE; + ek_ring[134].value[9] = 0xDC; + ek_ring[134].value[10] = 0xBA; + ek_ring[134].value[11] = 0x98; + ek_ring[134].value[12] = 0x76; + ek_ring[134].value[13] = 0x54; + ek_ring[134].value[14] = 0x32; + ek_ring[134].value[15] = 0x10; + ek_ring[134].value[16] = 0xAB; + ek_ring[134].value[17] = 0xCD; + ek_ring[134].value[18] = 0xEF; + ek_ring[134].value[19] = 0x01; + ek_ring[134].value[20] = 0x23; + ek_ring[134].value[21] = 0x45; + ek_ring[134].value[22] = 0x67; + ek_ring[134].value[23] = 0x89; + ek_ring[134].value[24] = 0xFE; + ek_ring[134].value[25] = 0xDC; + ek_ring[134].value[26] = 0xBA; + ek_ring[134].value[27] = 0x98; + ek_ring[134].value[28] = 0x76; + ek_ring[134].value[29] = 0x54; + ek_ring[134].value[30] = 0x32; + ek_ring[134].value[31] = 0x10; + ek_ring[134].key_state = KEY_DEACTIVATED; } static void Crypto_Local_Init(void) diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c index 700fd858..e8ef6e28 100644 --- a/fsw/src/sadb_routine_inmemory.template.c +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -59,349 +59,6 @@ SadbRoutine get_sadb_routine_inmemory(void) int32 sadb_config(void) { int32 status = OS_SUCCESS; - // Master Keys - // 0 - 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F -> ACTIVE - ek_ring[0].value[0] = 0x00; - ek_ring[0].value[1] = 0x01; - ek_ring[0].value[2] = 0x02; - ek_ring[0].value[3] = 0x03; - ek_ring[0].value[4] = 0x04; - ek_ring[0].value[5] = 0x05; - ek_ring[0].value[6] = 0x06; - ek_ring[0].value[7] = 0x07; - ek_ring[0].value[8] = 0x08; - ek_ring[0].value[9] = 0x09; - ek_ring[0].value[10] = 0x0A; - ek_ring[0].value[11] = 0x0B; - ek_ring[0].value[12] = 0x0C; - ek_ring[0].value[13] = 0x0D; - ek_ring[0].value[14] = 0x0E; - ek_ring[0].value[15] = 0x0F; - ek_ring[0].value[16] = 0x00; - ek_ring[0].value[17] = 0x01; - ek_ring[0].value[18] = 0x02; - ek_ring[0].value[19] = 0x03; - ek_ring[0].value[20] = 0x04; - ek_ring[0].value[21] = 0x05; - ek_ring[0].value[22] = 0x06; - ek_ring[0].value[23] = 0x07; - ek_ring[0].value[24] = 0x08; - ek_ring[0].value[25] = 0x09; - ek_ring[0].value[26] = 0x0A; - ek_ring[0].value[27] = 0x0B; - ek_ring[0].value[28] = 0x0C; - ek_ring[0].value[29] = 0x0D; - ek_ring[0].value[30] = 0x0E; - ek_ring[0].value[31] = 0x0F; - ek_ring[0].key_state = KEY_ACTIVE; - // 1 - 101112131415161718191A1B1C1D1E1F101112131415161718191A1B1C1D1E1F -> ACTIVE - ek_ring[1].value[0] = 0x10; - ek_ring[1].value[1] = 0x11; - ek_ring[1].value[2] = 0x12; - ek_ring[1].value[3] = 0x13; - ek_ring[1].value[4] = 0x14; - ek_ring[1].value[5] = 0x15; - ek_ring[1].value[6] = 0x16; - ek_ring[1].value[7] = 0x17; - ek_ring[1].value[8] = 0x18; - ek_ring[1].value[9] = 0x19; - ek_ring[1].value[10] = 0x1A; - ek_ring[1].value[11] = 0x1B; - ek_ring[1].value[12] = 0x1C; - ek_ring[1].value[13] = 0x1D; - ek_ring[1].value[14] = 0x1E; - ek_ring[1].value[15] = 0x1F; - ek_ring[1].value[16] = 0x10; - ek_ring[1].value[17] = 0x11; - ek_ring[1].value[18] = 0x12; - ek_ring[1].value[19] = 0x13; - ek_ring[1].value[20] = 0x14; - ek_ring[1].value[21] = 0x15; - ek_ring[1].value[22] = 0x16; - ek_ring[1].value[23] = 0x17; - ek_ring[1].value[24] = 0x18; - ek_ring[1].value[25] = 0x19; - ek_ring[1].value[26] = 0x1A; - ek_ring[1].value[27] = 0x1B; - ek_ring[1].value[28] = 0x1C; - ek_ring[1].value[29] = 0x1D; - ek_ring[1].value[30] = 0x1E; - ek_ring[1].value[31] = 0x1F; - ek_ring[1].key_state = KEY_ACTIVE; - // 2 - 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F -> ACTIVE - ek_ring[2].value[0] = 0x20; - ek_ring[2].value[1] = 0x21; - ek_ring[2].value[2] = 0x22; - ek_ring[2].value[3] = 0x23; - ek_ring[2].value[4] = 0x24; - ek_ring[2].value[5] = 0x25; - ek_ring[2].value[6] = 0x26; - ek_ring[2].value[7] = 0x27; - ek_ring[2].value[8] = 0x28; - ek_ring[2].value[9] = 0x29; - ek_ring[2].value[10] = 0x2A; - ek_ring[2].value[11] = 0x2B; - ek_ring[2].value[12] = 0x2C; - ek_ring[2].value[13] = 0x2D; - ek_ring[2].value[14] = 0x2E; - ek_ring[2].value[15] = 0x2F; - ek_ring[2].value[16] = 0x20; - ek_ring[2].value[17] = 0x21; - ek_ring[2].value[18] = 0x22; - ek_ring[2].value[19] = 0x23; - ek_ring[2].value[20] = 0x24; - ek_ring[2].value[21] = 0x25; - ek_ring[2].value[22] = 0x26; - ek_ring[2].value[23] = 0x27; - ek_ring[2].value[24] = 0x28; - ek_ring[2].value[25] = 0x29; - ek_ring[2].value[26] = 0x2A; - ek_ring[2].value[27] = 0x2B; - ek_ring[2].value[28] = 0x2C; - ek_ring[2].value[29] = 0x2D; - ek_ring[2].value[30] = 0x2E; - ek_ring[2].value[31] = 0x2F; - ek_ring[2].key_state = KEY_ACTIVE; - - // Session Keys - // 128 - 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -> ACTIVE - ek_ring[128].value[0] = 0x01; - ek_ring[128].value[1] = 0x23; - ek_ring[128].value[2] = 0x45; - ek_ring[128].value[3] = 0x67; - ek_ring[128].value[4] = 0x89; - ek_ring[128].value[5] = 0xAB; - ek_ring[128].value[6] = 0xCD; - ek_ring[128].value[7] = 0xEF; - ek_ring[128].value[8] = 0x01; - ek_ring[128].value[9] = 0x23; - ek_ring[128].value[10] = 0x45; - ek_ring[128].value[11] = 0x67; - ek_ring[128].value[12] = 0x89; - ek_ring[128].value[13] = 0xAB; - ek_ring[128].value[14] = 0xCD; - ek_ring[128].value[15] = 0xEF; - ek_ring[128].value[16] = 0x01; - ek_ring[128].value[17] = 0x23; - ek_ring[128].value[18] = 0x45; - ek_ring[128].value[19] = 0x67; - ek_ring[128].value[20] = 0x89; - ek_ring[128].value[21] = 0xAB; - ek_ring[128].value[22] = 0xCD; - ek_ring[128].value[23] = 0xEF; - ek_ring[128].value[24] = 0x01; - ek_ring[128].value[25] = 0x23; - ek_ring[128].value[26] = 0x45; - ek_ring[128].value[27] = 0x67; - ek_ring[128].value[28] = 0x89; - ek_ring[128].value[29] = 0xAB; - ek_ring[128].value[30] = 0xCD; - ek_ring[128].value[31] = 0xEF; - ek_ring[128].key_state = KEY_ACTIVE; - // 129 - ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 -> ACTIVE - ek_ring[129].value[0] = 0xAB; - ek_ring[129].value[1] = 0xCD; - ek_ring[129].value[2] = 0xEF; - ek_ring[129].value[3] = 0x01; - ek_ring[129].value[4] = 0x23; - ek_ring[129].value[5] = 0x45; - ek_ring[129].value[6] = 0x67; - ek_ring[129].value[7] = 0x89; - ek_ring[129].value[8] = 0xAB; - ek_ring[129].value[9] = 0xCD; - ek_ring[129].value[10] = 0xEF; - ek_ring[129].value[11] = 0x01; - ek_ring[129].value[12] = 0x23; - ek_ring[129].value[13] = 0x45; - ek_ring[129].value[14] = 0x67; - ek_ring[129].value[15] = 0x89; - ek_ring[129].value[16] = 0xAB; - ek_ring[129].value[17] = 0xCD; - ek_ring[129].value[18] = 0xEF; - ek_ring[129].value[19] = 0x01; - ek_ring[129].value[20] = 0x23; - ek_ring[129].value[21] = 0x45; - ek_ring[129].value[22] = 0x67; - ek_ring[129].value[23] = 0x89; - ek_ring[129].value[24] = 0xAB; - ek_ring[129].value[25] = 0xCD; - ek_ring[129].value[26] = 0xEF; - ek_ring[129].value[27] = 0x01; - ek_ring[129].value[28] = 0x23; - ek_ring[129].value[29] = 0x45; - ek_ring[129].value[30] = 0x67; - ek_ring[129].value[31] = 0x89; - ek_ring[129].key_state = KEY_ACTIVE; - // 130 - FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210 -> ACTIVE - ek_ring[130].value[0] = 0xFE; - ek_ring[130].value[1] = 0xDC; - ek_ring[130].value[2] = 0xBA; - ek_ring[130].value[3] = 0x98; - ek_ring[130].value[4] = 0x76; - ek_ring[130].value[5] = 0x54; - ek_ring[130].value[6] = 0x32; - ek_ring[130].value[7] = 0x10; - ek_ring[130].value[8] = 0xFE; - ek_ring[130].value[9] = 0xDC; - ek_ring[130].value[10] = 0xBA; - ek_ring[130].value[11] = 0x98; - ek_ring[130].value[12] = 0x76; - ek_ring[130].value[13] = 0x54; - ek_ring[130].value[14] = 0x32; - ek_ring[130].value[15] = 0x10; - ek_ring[130].value[16] = 0xFE; - ek_ring[130].value[17] = 0xDC; - ek_ring[130].value[18] = 0xBA; - ek_ring[130].value[19] = 0x98; - ek_ring[130].value[20] = 0x76; - ek_ring[130].value[21] = 0x54; - ek_ring[130].value[22] = 0x32; - ek_ring[130].value[23] = 0x10; - ek_ring[130].value[24] = 0xFE; - ek_ring[130].value[25] = 0xDC; - ek_ring[130].value[26] = 0xBA; - ek_ring[130].value[27] = 0x98; - ek_ring[130].value[28] = 0x76; - ek_ring[130].value[29] = 0x54; - ek_ring[130].value[30] = 0x32; - ek_ring[130].value[31] = 0x10; - ek_ring[130].key_state = KEY_ACTIVE; - // 131 - 9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA -> ACTIVE - ek_ring[131].value[0] = 0x98; - ek_ring[131].value[1] = 0x76; - ek_ring[131].value[2] = 0x54; - ek_ring[131].value[3] = 0x32; - ek_ring[131].value[4] = 0x10; - ek_ring[131].value[5] = 0xFE; - ek_ring[131].value[6] = 0xDC; - ek_ring[131].value[7] = 0xBA; - ek_ring[131].value[8] = 0x98; - ek_ring[131].value[9] = 0x76; - ek_ring[131].value[10] = 0x54; - ek_ring[131].value[11] = 0x32; - ek_ring[131].value[12] = 0x10; - ek_ring[131].value[13] = 0xFE; - ek_ring[131].value[14] = 0xDC; - ek_ring[131].value[15] = 0xBA; - ek_ring[131].value[16] = 0x98; - ek_ring[131].value[17] = 0x76; - ek_ring[131].value[18] = 0x54; - ek_ring[131].value[19] = 0x32; - ek_ring[131].value[20] = 0x10; - ek_ring[131].value[21] = 0xFE; - ek_ring[131].value[22] = 0xDC; - ek_ring[131].value[23] = 0xBA; - ek_ring[131].value[24] = 0x98; - ek_ring[131].value[25] = 0x76; - ek_ring[131].value[26] = 0x54; - ek_ring[131].value[27] = 0x32; - ek_ring[131].value[28] = 0x10; - ek_ring[131].value[29] = 0xFE; - ek_ring[131].value[30] = 0xDC; - ek_ring[131].value[31] = 0xBA; - ek_ring[131].key_state = KEY_ACTIVE; - // 132 - 0123456789ABCDEFABCDEF01234567890123456789ABCDEFABCDEF0123456789 -> PRE_ACTIVATION - ek_ring[132].value[0] = 0x01; - ek_ring[132].value[1] = 0x23; - ek_ring[132].value[2] = 0x45; - ek_ring[132].value[3] = 0x67; - ek_ring[132].value[4] = 0x89; - ek_ring[132].value[5] = 0xAB; - ek_ring[132].value[6] = 0xCD; - ek_ring[132].value[7] = 0xEF; - ek_ring[132].value[8] = 0xAB; - ek_ring[132].value[9] = 0xCD; - ek_ring[132].value[10] = 0xEF; - ek_ring[132].value[11] = 0x01; - ek_ring[132].value[12] = 0x23; - ek_ring[132].value[13] = 0x45; - ek_ring[132].value[14] = 0x67; - ek_ring[132].value[15] = 0x89; - ek_ring[132].value[16] = 0x01; - ek_ring[132].value[17] = 0x23; - ek_ring[132].value[18] = 0x45; - ek_ring[132].value[19] = 0x67; - ek_ring[132].value[20] = 0x89; - ek_ring[132].value[21] = 0xAB; - ek_ring[132].value[22] = 0xCD; - ek_ring[132].value[23] = 0xEF; - ek_ring[132].value[24] = 0xAB; - ek_ring[132].value[25] = 0xCD; - ek_ring[132].value[26] = 0xEF; - ek_ring[132].value[27] = 0x01; - ek_ring[132].value[28] = 0x23; - ek_ring[132].value[29] = 0x45; - ek_ring[132].value[30] = 0x67; - ek_ring[132].value[31] = 0x89; - ek_ring[132].key_state = KEY_PREACTIVE; - // 133 - ABCDEF01234567890123456789ABCDEFABCDEF01234567890123456789ABCDEF -> ACTIVE - ek_ring[133].value[0] = 0xAB; - ek_ring[133].value[1] = 0xCD; - ek_ring[133].value[2] = 0xEF; - ek_ring[133].value[3] = 0x01; - ek_ring[133].value[4] = 0x23; - ek_ring[133].value[5] = 0x45; - ek_ring[133].value[6] = 0x67; - ek_ring[133].value[7] = 0x89; - ek_ring[133].value[8] = 0x01; - ek_ring[133].value[9] = 0x23; - ek_ring[133].value[10] = 0x45; - ek_ring[133].value[11] = 0x67; - ek_ring[133].value[12] = 0x89; - ek_ring[133].value[13] = 0xAB; - ek_ring[133].value[14] = 0xCD; - ek_ring[133].value[15] = 0xEF; - ek_ring[133].value[16] = 0xAB; - ek_ring[133].value[17] = 0xCD; - ek_ring[133].value[18] = 0xEF; - ek_ring[133].value[19] = 0x01; - ek_ring[133].value[20] = 0x23; - ek_ring[133].value[21] = 0x45; - ek_ring[133].value[22] = 0x67; - ek_ring[133].value[23] = 0x89; - ek_ring[133].value[24] = 0x01; - ek_ring[133].value[25] = 0x23; - ek_ring[133].value[26] = 0x45; - ek_ring[133].value[27] = 0x67; - ek_ring[133].value[28] = 0x89; - ek_ring[133].value[29] = 0xAB; - ek_ring[133].value[30] = 0xCD; - ek_ring[133].value[31] = 0xEF; - ek_ring[133].key_state = KEY_ACTIVE; - // 134 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE - ek_ring[134].value[0] = 0xAB; - ek_ring[134].value[1] = 0xCD; - ek_ring[134].value[2] = 0xEF; - ek_ring[134].value[3] = 0x01; - ek_ring[134].value[4] = 0x23; - ek_ring[134].value[5] = 0x45; - ek_ring[134].value[6] = 0x67; - ek_ring[134].value[7] = 0x89; - ek_ring[134].value[8] = 0xFE; - ek_ring[134].value[9] = 0xDC; - ek_ring[134].value[10] = 0xBA; - ek_ring[134].value[11] = 0x98; - ek_ring[134].value[12] = 0x76; - ek_ring[134].value[13] = 0x54; - ek_ring[134].value[14] = 0x32; - ek_ring[134].value[15] = 0x10; - ek_ring[134].value[16] = 0xAB; - ek_ring[134].value[17] = 0xCD; - ek_ring[134].value[18] = 0xEF; - ek_ring[134].value[19] = 0x01; - ek_ring[134].value[20] = 0x23; - ek_ring[134].value[21] = 0x45; - ek_ring[134].value[22] = 0x67; - ek_ring[134].value[23] = 0x89; - ek_ring[134].value[24] = 0xFE; - ek_ring[134].value[25] = 0xDC; - ek_ring[134].value[26] = 0xBA; - ek_ring[134].value[27] = 0x98; - ek_ring[134].value[28] = 0x76; - ek_ring[134].value[29] = 0x54; - ek_ring[134].value[30] = 0x32; - ek_ring[134].value[31] = 0x10; - ek_ring[134].key_state = KEY_DEACTIVATED; // Security Associations // SA 1 - CLEAR MODE From f09e0a3155e90df34dfaaebef463f757b4efe3ec Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 27 Oct 2021 17:39:04 -0700 Subject: [PATCH 010/184] AKMC-113: intermediate commit of SQL scripts --- .../create_sadb.sql | 31 +++++++++++++++++++ .../create_sadb_user_grant_permissions.sql | 3 ++ fsw/src/sadb_routine_mariadb.template.c | 28 ++++++++--------- 3 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql create mode 100644 fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql new file mode 100644 index 00000000..0a817c9a --- /dev/null +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql @@ -0,0 +1,31 @@ +CREATE DATABASE IF NOT EXISTS sadb; + +USE sadb; + +CREATE TABLE security_associations +( + sa_id INT NOT NULL + ,ekid MEDIUMINT NOT NULL + ,akid mediumint NOT NULL + ,sa_state SMALLINT NOT NULL + ,gvcid INT + ,lpid SMALLINT + ,est SMALLINT + ,ast SMALLINT + ,shivf_len SMALLINT + ,shsnf_len SMALLINT + ,shplf_len SMALLINT + ,stmacf_len SMALLINT + ,ecs_len SMALLINT + ,ecs SMALLINT + ,iv_len SMALLINT + ,iv SMALLINT + ,acs_len SMALLINT + ,acs SMALLINT + ,abm_len MEDIUMINT + ,abm SMALLINT + ,arc_len SMALLINT + ,arc SMALLINT + ,arcw_len SMALLINT + ,arcw SMALLINT +); \ No newline at end of file diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql new file mode 100644 index 00000000..e4d959c9 --- /dev/null +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql @@ -0,0 +1,3 @@ +Create User IF NOT EXISTS sadb_user; + +GRANT ALL PRIVILEGES ON sadb.* TO 'sadb_user' @ '%'; \ No newline at end of file diff --git a/fsw/src/sadb_routine_mariadb.template.c b/fsw/src/sadb_routine_mariadb.template.c index 7e307295..a93fac11 100644 --- a/fsw/src/sadb_routine_mariadb.template.c +++ b/fsw/src/sadb_routine_mariadb.template.c @@ -38,9 +38,6 @@ static int32 sadb_sa_delete(void); static SadbRoutineStruct sadb_routine; static SecurityAssociation_t sa[NUM_SA]; -static crypto_key_t ek_ring[NUM_KEYS]; - - SadbRoutine get_sadb_routine_mariadb(void) { sadb_routine.sadb_config = sadb_config; @@ -57,16 +54,19 @@ SadbRoutine get_sadb_routine_mariadb(void) return &sadb_routine; } -int32 sadb_config(void){return 0;} -int32 sadb_init(void){return 0;} +int32 sadb_config(void) +{ + return OS_SUCCESS; +} +int32 sadb_init(void){return OS_SUCCESS;} // Security Association Interaction Functions -int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_association){return 0;} +int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_association){return OS_SUCCESS;} // Security Association Utility Functions -int32 sadb_sa_start(TC_t* tc_frame){return 0;} -int32 sadb_sa_expire(void){return 0;} -int32 sadb_sa_rekey(void){return 0;} -int32 sadb_sa_status(char* ingest){return 0;} -int32 sadb_sa_create(void){return 0;} -int32 sadb_sa_setARSN(void){return 0;} -int32 sadb_sa_setARSNW(void){return 0;} -int32 sadb_sa_delete(void){return 0;} +int32 sadb_sa_start(TC_t* tc_frame){return OS_SUCCESS;} +int32 sadb_sa_expire(void){return OS_SUCCESS;} +int32 sadb_sa_rekey(void){return OS_SUCCESS;} +int32 sadb_sa_status(char* ingest){return OS_SUCCESS;} +int32 sadb_sa_create(void){return OS_SUCCESS;} +int32 sadb_sa_setARSN(void){return OS_SUCCESS;} +int32 sadb_sa_setARSNW(void){return OS_SUCCESS;} +int32 sadb_sa_delete(void){return OS_SUCCESS;} From 67f00bf1df72cbfad216dc5bd5d7ec127a2627cc Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 29 Oct 2021 11:12:37 -0400 Subject: [PATCH 011/184] Ignore .dat files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4fe5d94d..be4e9b05 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ core *.so build venv +*.dat #CMake.gitignore CMakeLists.txt.user From 16b02b1113619e212438da4c9816ace95f004098 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 29 Oct 2021 12:54:23 -0400 Subject: [PATCH 012/184] Add Raw TC SDLS for testing --- fsw/crypto_tests/data/raw_tc_sdls_ping.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping.txt diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping.txt b/fsw/crypto_tests/data/raw_tc_sdls_ping.txt new file mode 100644 index 00000000..896e7b31 --- /dev/null +++ b/fsw/crypto_tests/data/raw_tc_sdls_ping.txt @@ -0,0 +1 @@ +20030015001880d2c70008197f0b00310000b1fe3128 \ No newline at end of file From 7de067afdd1479016151ce4e0103c2a29f7dd2ac Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 29 Oct 2021 14:18:38 -0400 Subject: [PATCH 013/184] Fix for CMake version related bug --- fsw/crypto_util/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/crypto_util/CMakeLists.txt b/fsw/crypto_util/CMakeLists.txt index 6ff0d152..be1b77be 100644 --- a/fsw/crypto_util/CMakeLists.txt +++ b/fsw/crypto_util/CMakeLists.txt @@ -32,7 +32,7 @@ foreach(SOURCE_PATH ${SOURCE_FILES}) add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_BINARY_DIR}/bin/${EXECUTABLE_NAME} - COMMAND ${CMAKE_COMMAND} -E rm $ + COMMAND ${CMAKE_COMMAND} -E remove $ COMMENT "Created ${PROJECT_BINARY_DIR}/bin/${EXECUTABLE_NAME}" ) endforeach(SOURCE_PATH ${SOURCE_FILES}) From 38b3db199a22cde213aca3edf7d949fa0eb87651 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 29 Oct 2021 14:37:24 -0400 Subject: [PATCH 014/184] Ignore vscode files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index be4e9b05..f881e3a8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ core build venv *.dat +.vscode #CMake.gitignore CMakeLists.txt.user From 827b649e9e0c67d9fe6c4b72d275bc7790e7fc0a Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 29 Oct 2021 14:45:50 -0400 Subject: [PATCH 015/184] Plaintext working / adding SPI headers --- fsw/public_inc/crypto_structs.h | 2 +- fsw/src/crypto.c | 251 +++++++++++++++++++++++++++++--- 2 files changed, 228 insertions(+), 25 deletions(-) diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index 45696575..1f08ce79 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -231,7 +231,7 @@ typedef struct /* ** Telecommand (TC) Definitions */ -typedef struct +typedef struct __attribute__ ((packed)) { uint8 tfvn :2; // Transfer Frame Version Number uint8 bypass :1; // Bypass diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 87ecb1a8..b2743588 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -569,7 +569,8 @@ static int32 Crypto_SA_config(void) sa[1].sa_state = SA_OPERATIONAL; sa[1].est = 0; sa[1].ast = 0; - sa[1].arc_len = 1; + sa[1].shplf_len = 2; + sa[1].arc_len = 0; sa[1].arcw_len = 1; sa[1].arcw[0] = 5; sa[1].gvcid_tc_blk[0].tfvn = 0; @@ -2658,35 +2659,237 @@ int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest) OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); #endif - // TODO: This whole function! - //len_ingest = len_ingest; - //ingest[0] = ingest[0]; - - int security_header_bytes = 18; - int security_trailer_bytes = 16; - int tc_size = *len_ingest + security_header_bytes + security_trailer_bytes; + #ifdef DEBUG + OS_printf("TF Bytes received\n"); + OS_printf("DEBUG - "); + for(int i=0; i <*len_ingest; i++) + { + OS_printf("%02X", ((uint8 *)&*tc_ingest)[i]); + } + OS_printf("\nPrinted %d bytes\n", *len_ingest); + #endif - unsigned char * tempTC=NULL; - tempTC = (unsigned char *)malloc(tc_size * sizeof (unsigned char)); - CFE_PSP_MemSet(tempTC, 0, tc_size); - int count = 0; - //Create Security Header - for (;count < security_header_bytes;count++){ - tempTC[count]= 0x55; //put dummy filler bits in security header for now. + TC_FramePrimaryHeader_t temp_tc_header; + // Primary Header + temp_tc_header.tfvn = ((uint8)tc_ingest[0] & 0xC0) >> 6; + temp_tc_header.bypass = ((uint8)tc_ingest[0] & 0x20) >> 5; + temp_tc_header.cc = ((uint8)tc_ingest[0] & 0x10) >> 4; + temp_tc_header.spare = ((uint8)tc_ingest[0] & 0x0C) >> 2; + temp_tc_header.scid = ((uint8)tc_ingest[0] & 0x03) << 8; + temp_tc_header.scid = temp_tc_header.scid | (uint8)tc_ingest[1]; + temp_tc_header.vcid = ((uint8)tc_ingest[2] & 0xFC) >> 2; + temp_tc_header.fl = ((uint8)tc_ingest[2] & 0x03) << 8; + temp_tc_header.fl = temp_tc_header.fl | (uint8)tc_ingest[3]; + temp_tc_header.fsn = (uint8)tc_ingest[4]; + + // Check if command frame flag set + if (temp_tc_header.cc == 1) + { + /* + ** CCSDS 232.0-B-3 + ** Section 6.3.1 + ** "Type-C frames do not have the Security Header and Security Trailer." + */ + #ifdef TC_DEBUG + OS_printf(KYEL "DEBUG - Received Control/Command frame - nothing to do.\n" RESET); + #endif } - //Create Frame Body - CFE_PSP_MemCpy(&tempTC[security_header_bytes],&tc_ingest[0],*len_ingest); - count+=*len_ingest; + // TODO: If command frame flag not set, need to know SDLS parameters + // What is the best way to do this - copy in the entire SA for a channel? + // Expect these calls will return an error is the SA is not usable + // Will need to know lengths of various parameters from the SA DB + else + { + // Query SA DB for active SA / SDLS paremeters + // TODO: Likely API call + // TODO: Magic to make sure we're getting the correct SA.. + // currently SA DB allows for more than one + SecurityAssociation_t temp_SA; + int16_t spi = -1; + for (int i=0; i < NUM_SA;i++) + { + if (sa[i].sa_state == SA_OPERATIONAL) + { + spi = i; + //break; // Needs modified to ACTUALLY get the correct SA + // TODO: Likely API discussion + } + } - //Create Security Trailer - for(;count < tc_size;count++){ - tempTC[count]=0x55; //put dummy filler bits in security trailer for now. - } + // If no active SA found + if (spi == -1) + { + OS_printf(KRED "Error: No operational SA found! \n" RESET); + status = OS_ERROR; + } + // Found an active SA + else + { + CFE_PSP_MemCpy(&temp_SA, &(sa[spi]), SA_SIZE); + #ifdef TC_DEBUG + OS_printf("Operational SA found at index %d.\n", spi); + #endif + } + + #ifdef SA_DEBUG + OS_printf(KYEL "DEBUG - Received data frame.\n" RESET); + OS_printf("Using SA 0x%04X settings.\n", spi); + #endif + + // Verify SCID + if ((temp_tc_header.scid != temp_SA.gvcid_tc_blk[temp_tc_header.vcid].scid) \ + && (status == OS_SUCCESS)) + { + OS_printf(KRED "Error: SCID incorrect! \n" RESET); + status = OS_ERROR; + } + + #ifdef SA_DEBUG + OS_printf(KYEL "DEBUG - Printing local copy of SA Entry for current SPI.\n" RESET); + Crypto_saPrint(&temp_SA); + #endif + + // Verify SA SPI configurations + // Check if SA is operational + if ((temp_SA.sa_state != SA_OPERATIONAL) && (status == OS_SUCCESS)) + { + OS_printf(KRED "Error: SA is not operational! \n" RESET); + status = OS_ERROR; + } + // Check if this VCID exists / is mapped to TCs + if ((temp_SA.gvcid_tc_blk[temp_tc_header.vcid].mapid != TYPE_TC) && (status = OS_SUCCESS)) + { + OS_printf(KRED "Error: SA does not map this VCID to TC! \n" RESET); + status = OS_ERROR; + } + + // If a check is invalid so far, can return + if (status != OS_SUCCESS) + { + return status; + } + + // Determine mode + // Clear + if ((temp_SA.est == 0) && (temp_SA.ast == 0)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TC - CLEAR! \n" RESET); + #endif + + // Total length of buffer to be malloced + // Ingest length + segment header (1) + spi_index (2) + some variable length fields + // TODO + uint16 tc_buf_length = *len_ingest + 1 + 2 + temp_SA.shplf_len; + + #ifdef TC_DEBUG + OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, tc_buf_length); + OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, *len_ingest); + OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); + OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); + OS_printf(KYEL "\tsh pad len\t = %d\n" RESET, temp_SA.shplf_len); + #endif + + // Accio buffer + unsigned char * ptc_enc_buf; + ptc_enc_buf = (unsigned char *)malloc(tc_buf_length * sizeof (unsigned char)); + CFE_PSP_MemSet(ptc_enc_buf, 0, tc_buf_length); + + // Copy original TF header + CFE_PSP_MemCpy(ptc_enc_buf, &*tc_ingest, TC_FRAME_PRIMARYHEADER_SIZE); + // Set new TF Header length + // Recall: Length field is one minus total length per spec + *(ptc_enc_buf+2) = ((*(ptc_enc_buf+2) & 0xFC) | (((tc_buf_length - 1) & (0x0300)) >> 8)); + *(ptc_enc_buf+3) = ((tc_buf_length - 1) & (0x00FF)); + + #ifdef TC_DEBUG + OS_printf(KYEL "Printing updated TF Header:\n\t"); + for (int i=0; i> 8); + *(ptc_enc_buf + index + 1) = (spi & 0x00FF); + index += 2; + + // Set anti-replay sequence number value + /* + ** 4.1.1.4.4 If authentication or authenticated encryption is not selected + ** for an SA, the Sequence Number field shall be zero octets in length. + */ + + // Determine if padding is needed + // TODO: Likely SA API Call + for (int i=0; i < temp_SA.shplf_len; i++) + { + // Temp fill Pad + // TODO: What should pad be, set per channel/SA potentially? + *(ptc_enc_buf + index) = 0x00; + index++; + } + + // Copy in original TF data + // Copy original TF header + CFE_PSP_MemCpy(ptc_enc_buf + index, &*(tc_ingest + TC_FRAME_PRIMARYHEADER_SIZE), *len_ingest-TC_FRAME_PRIMARYHEADER_SIZE); - *ingest = tempTC; - *len_ingest = tc_size; + #ifdef TC_DEBUG + OS_printf(KYEL "Printing new TC Frame:\n\t"); + for(int i=0; i < tc_buf_length; i++) + { + OS_printf("%02X", *(ptc_enc_buf + i)); + } + OS_printf("\n" RESET); + #endif + } + + // Authentication + else if ((temp_SA.est == 0) && (temp_SA.ast == 1)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TC - AUTHENTICATED! \n" RESET); + #endif + // TODO + } + + // Encryption + else if ((temp_SA.est == 1) && (temp_SA.ast == 0)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TC - ENCRYPTED! \n" RESET); + #endif + // TODO + } + + // Authenticated Encryption + else if((temp_SA.est == 1) && (temp_SA.ast == 1)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION! \n" RESET); + #endif + // TODO + } + } #ifdef DEBUG OS_printf(KYEL "----- Crypto_TC_ApplySecurity END -----\n" RESET); From 6a7b43f437c05529ce89758e00fce417efe5f448 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Mon, 1 Nov 2021 17:27:21 -0400 Subject: [PATCH 016/184] TC_ApplySecurity plaintext w/ function sig changes --- fsw/crypto_util/app/apply_security.c | 23 +++++--- fsw/crypto_util/app/crypto_sequence.c | 8 ++- fsw/public_inc/crypto.h | 3 +- fsw/src/crypto.c | 78 ++++++++++++++------------- 4 files changed, 66 insertions(+), 46 deletions(-) diff --git a/fsw/crypto_util/app/apply_security.c b/fsw/crypto_util/app/apply_security.c index e41f5f7d..d5c45e4e 100644 --- a/fsw/crypto_util/app/apply_security.c +++ b/fsw/crypto_util/app/apply_security.c @@ -40,27 +40,38 @@ int main(int argc, char *argv[]) { } buffer = c_read_file(filename,&buffer_size); debug_printf("File buffer size:%lu\n",buffer_size); - int buffer_size_i = (int) buffer_size; + uint32 buffer_size_i = (uint32) buffer_size; debug_printf("File buffer size int:%d\n",buffer_size_i); debug_printf("File content: \n"); debug_hexprintf(buffer,buffer_size_i); - //Setup & Initialize CryptoLib Crypto_Init(); + uint8 * ptr_enc_frame = NULL; + uint32 enc_frame_len; + //Call ApplySecurity on buffer contents depending on type. if (strcmp(security_type,"tc")==0){ - Crypto_TC_ApplySecurity(&buffer, &buffer_size_i); + Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); } else if (strcmp(security_type,"tm")==0){ Crypto_TM_ApplySecurity(buffer, &buffer_size_i); } else if (strcmp(security_type,"aos")==0){ Crypto_AOS_ApplySecurity(buffer, &buffer_size_i); } - debug_printf("Applied Security buffer size int:%d\n",buffer_size_i); - debug_printf("File content: \n"); - debug_hexprintf(buffer,buffer_size_i); + #ifdef TC_DEBUG + OS_printf(KYEL "ApplySecurity Output:\n" RESET); + OS_printf(KYEL "\tBuffer size int:%d\n" RESET, enc_frame_len); + OS_printf(KYEL "\tEncrypted Frame Contents: \n\t" RESET); + + for(int i=0; i < enc_frame_len; i++) + { + OS_printf(KYEL "%02X" RESET, *(ptr_enc_frame+i)); + } + OS_printf("\n"); + #endif free(buffer); + free(ptr_enc_frame); } \ No newline at end of file diff --git a/fsw/crypto_util/app/crypto_sequence.c b/fsw/crypto_util/app/crypto_sequence.c index 8c55c563..fbf35cd3 100644 --- a/fsw/crypto_util/app/crypto_sequence.c +++ b/fsw/crypto_util/app/crypto_sequence.c @@ -42,6 +42,9 @@ int main(int argc, char *argv[]) { Crypto_Init(); int arg_index = 0; + uint8 * ptr_enc_frame = NULL; + uint32 enc_frame_len; + while(arg_index != argc-1){ security_type = argv[++arg_index]; debug_printf("Security Type: %s\n",security_type); @@ -54,10 +57,11 @@ int main(int argc, char *argv[]) { debug_printf("File content: \n"); debug_hexprintf(buffer,buffer_size_i); + //Call Apply/ProcessSecurity on buffer contents depending on type. if (strcmp(security_type,"tc_a")==0){ - Crypto_TC_ApplySecurity(&buffer, &buffer_size_i); - } else if (strcmp(security_type,"tm_a")==0){ + Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, enc_frame_len);} + else if (strcmp(security_type,"tm_a")==0){ Crypto_TM_ApplySecurity(buffer, &buffer_size_i); } else if (strcmp(security_type,"aos_a")==0){ Crypto_AOS_ApplySecurity(buffer, &buffer_size_i); diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index 4ac8a351..6b52b935 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -40,7 +40,8 @@ ivv-itc@lists.nasa.gov // Initialization extern int32 Crypto_Init(void); // Telecommand (TC) -extern int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest); +extern int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_length, \ + uint8 **enc_frame, uint32 *enc_frame_len); extern int32 Crypto_TC_ProcessSecurity(char* ingest, int* len_ingest, TC_t* tc_sdls_processed_frame); // Telemetry (TM) extern int32 Crypto_TM_ApplySecurity(char* ingest, int* len_ingest); diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index b2743588..81b30a9a 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2648,40 +2648,39 @@ static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) return status; } - -int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest) +int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_length, \ + uint8 **enc_frame_test, uint32 *enc_frame_len) { // Local Variables int32 status = OS_SUCCESS; - unsigned char* tc_ingest = *ingest; #ifdef DEBUG OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); #endif #ifdef DEBUG - OS_printf("TF Bytes received\n"); + OS_printf("%d TF Bytes received\n", in_frame_length); OS_printf("DEBUG - "); - for(int i=0; i <*len_ingest; i++) + for(int i=0; i < in_frame_length; i++) { - OS_printf("%02X", ((uint8 *)&*tc_ingest)[i]); + OS_printf("%02X", ((uint8 *)&*in_frame)[i]); } - OS_printf("\nPrinted %d bytes\n", *len_ingest); + OS_printf("\nPrinted %d bytes\n", in_frame_length); #endif TC_FramePrimaryHeader_t temp_tc_header; // Primary Header - temp_tc_header.tfvn = ((uint8)tc_ingest[0] & 0xC0) >> 6; - temp_tc_header.bypass = ((uint8)tc_ingest[0] & 0x20) >> 5; - temp_tc_header.cc = ((uint8)tc_ingest[0] & 0x10) >> 4; - temp_tc_header.spare = ((uint8)tc_ingest[0] & 0x0C) >> 2; - temp_tc_header.scid = ((uint8)tc_ingest[0] & 0x03) << 8; - temp_tc_header.scid = temp_tc_header.scid | (uint8)tc_ingest[1]; - temp_tc_header.vcid = ((uint8)tc_ingest[2] & 0xFC) >> 2; - temp_tc_header.fl = ((uint8)tc_ingest[2] & 0x03) << 8; - temp_tc_header.fl = temp_tc_header.fl | (uint8)tc_ingest[3]; - temp_tc_header.fsn = (uint8)tc_ingest[4]; + temp_tc_header.tfvn = ((uint8)in_frame[0] & 0xC0) >> 6; + temp_tc_header.bypass = ((uint8)in_frame[0] & 0x20) >> 5; + temp_tc_header.cc = ((uint8)in_frame[0] & 0x10) >> 4; + temp_tc_header.spare = ((uint8)in_frame[0] & 0x0C) >> 2; + temp_tc_header.scid = ((uint8)in_frame[0] & 0x03) << 8; + temp_tc_header.scid = temp_tc_header.scid | (uint8)in_frame[1]; + temp_tc_header.vcid = ((uint8)in_frame[2] & 0xFC) >> 2; + temp_tc_header.fl = ((uint8)in_frame[2] & 0x03) << 8; + temp_tc_header.fl = temp_tc_header.fl | (uint8)in_frame[3]; + temp_tc_header.fsn = (uint8)in_frame[4]; // Check if command frame flag set if (temp_tc_header.cc == 1) @@ -2782,36 +2781,35 @@ int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest) // Total length of buffer to be malloced // Ingest length + segment header (1) + spi_index (2) + some variable length fields // TODO - uint16 tc_buf_length = *len_ingest + 1 + 2 + temp_SA.shplf_len; + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shplf_len; #ifdef TC_DEBUG - OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, tc_buf_length); - OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, *len_ingest); + OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *enc_frame_len); + OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); OS_printf(KYEL "\tsh pad len\t = %d\n" RESET, temp_SA.shplf_len); #endif // Accio buffer - unsigned char * ptc_enc_buf; - ptc_enc_buf = (unsigned char *)malloc(tc_buf_length * sizeof (unsigned char)); - CFE_PSP_MemSet(ptc_enc_buf, 0, tc_buf_length); + uint8 *enc_frame = (const uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); + CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); // Copy original TF header - CFE_PSP_MemCpy(ptc_enc_buf, &*tc_ingest, TC_FRAME_PRIMARYHEADER_SIZE); + CFE_PSP_MemCpy(enc_frame, in_frame, TC_FRAME_PRIMARYHEADER_SIZE); // Set new TF Header length // Recall: Length field is one minus total length per spec - *(ptc_enc_buf+2) = ((*(ptc_enc_buf+2) & 0xFC) | (((tc_buf_length - 1) & (0x0300)) >> 8)); - *(ptc_enc_buf+3) = ((tc_buf_length - 1) & (0x00FF)); + *(enc_frame+2) = ((*(enc_frame+2) & 0xFC) | (((*enc_frame_len - 1) & (0x0300)) >> 8)); + *(enc_frame+3) = ((*enc_frame_len - 1) & (0x00FF)); #ifdef TC_DEBUG OS_printf(KYEL "Printing updated TF Header:\n\t"); for (int i=0; i> 8); - *(ptc_enc_buf + index + 1) = (spi & 0x00FF); + *(enc_frame + index) = ((spi & 0xFF00) >> 8); + *(enc_frame + index + 1) = (spi & 0x00FF); index += 2; // Set anti-replay sequence number value @@ -2845,22 +2843,28 @@ int32 Crypto_TC_ApplySecurity(char** ingest, int* len_ingest) { // Temp fill Pad // TODO: What should pad be, set per channel/SA potentially? - *(ptc_enc_buf + index) = 0x00; + *(enc_frame + index) = 0x00; index++; } // Copy in original TF data - // Copy original TF header - CFE_PSP_MemCpy(ptc_enc_buf + index, &*(tc_ingest + TC_FRAME_PRIMARYHEADER_SIZE), *len_ingest-TC_FRAME_PRIMARYHEADER_SIZE); + CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), (in_frame_length-TC_FRAME_PRIMARYHEADER_SIZE)); + // for (int i=TC_FRAME_PRIMARYHEADER_SIZE; i < in_frame_length; i++) + // { + // *(enc_frame + index) = *(in_frame + i); + // index++; + // } #ifdef TC_DEBUG OS_printf(KYEL "Printing new TC Frame:\n\t"); - for(int i=0; i < tc_buf_length; i++) + for(int i=0; i < *enc_frame_len; i++) { - OS_printf("%02X", *(ptc_enc_buf + i)); + OS_printf("%02X", *(enc_frame + i)); } - OS_printf("\n" RESET); + OS_printf("\n\tThe returned length is: %d\n" RESET, *enc_frame_len); #endif + + *enc_frame_test = enc_frame; } // Authentication From 5b432318ed5700c8e3553f1ac5f5eb26653b02c2 Mon Sep 17 00:00:00 2001 From: Robert Brown Date: Wed, 3 Nov 2021 15:43:34 -0400 Subject: [PATCH 017/184] Crypto_TC_Apply Unit Test Start --- fsw/crypto_tests/CMakeLists.txt | 4 + .../data/raw_tc_sdls_ping_bad_scid.dat | 0 .../data/raw_tc_sdls_ping_bad_scid.txt | 1 + .../data/raw_tc_sdls_ping_bad_vcid.dat | 0 .../data/raw_tc_sdls_ping_bad_vcid.txt | 1 + fsw/crypto_util/app/apply_security.c | 27 +- fsw/crypto_util/app/ut_tc_apply.c | 84 ++ fsw/crypto_util/include/ut_tc_apply.h | 34 + fsw/crypto_util/include/utest.h | 1156 +++++++++++++++++ fsw/public_inc/crypto_config.h | 4 +- 10 files changed, 1291 insertions(+), 20 deletions(-) create mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat create mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.txt create mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat create mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.txt create mode 100644 fsw/crypto_util/app/ut_tc_apply.c create mode 100644 fsw/crypto_util/include/ut_tc_apply.h create mode 100644 fsw/crypto_util/include/utest.h diff --git a/fsw/crypto_tests/CMakeLists.txt b/fsw/crypto_tests/CMakeLists.txt index d53b7cdc..a64cf4d9 100644 --- a/fsw/crypto_tests/CMakeLists.txt +++ b/fsw/crypto_tests/CMakeLists.txt @@ -17,4 +17,8 @@ set(PROJECT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) add_test(NAME Process_Security COMMAND ${PROJECT_BINARY_DIR}/bin/process_security tc ${PROJECT_TEST_DIR}/data/tc4.1.dat + WORKING_DIRECTORY ${PROJECT_TEST_DIR}) + +add_test(NAME UT_TC_APPLY + COMMAND ${PROJECT_BINARY_DIR}/bin/ut_tc_apply WORKING_DIRECTORY ${PROJECT_TEST_DIR}) \ No newline at end of file diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat new file mode 100644 index 00000000..e69de29b diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.txt b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.txt new file mode 100644 index 00000000..ba2549ba --- /dev/null +++ b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.txt @@ -0,0 +1 @@ +20010015001880d2c70008197f0b00310000b1fe3128 \ No newline at end of file diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat new file mode 100644 index 00000000..e69de29b diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.txt b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.txt new file mode 100644 index 00000000..64b27cb1 --- /dev/null +++ b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.txt @@ -0,0 +1 @@ +20032015001880d2c70008197f0b00310000b1fe3128 \ No newline at end of file diff --git a/fsw/crypto_util/app/apply_security.c b/fsw/crypto_util/app/apply_security.c index d5c45e4e..7d70fbbc 100644 --- a/fsw/crypto_util/app/apply_security.c +++ b/fsw/crypto_util/app/apply_security.c @@ -40,38 +40,27 @@ int main(int argc, char *argv[]) { } buffer = c_read_file(filename,&buffer_size); debug_printf("File buffer size:%lu\n",buffer_size); - uint32 buffer_size_i = (uint32) buffer_size; + int buffer_size_i = (int) buffer_size; debug_printf("File buffer size int:%d\n",buffer_size_i); debug_printf("File content: \n"); debug_hexprintf(buffer,buffer_size_i); + //Setup & Initialize CryptoLib Crypto_Init(); - uint8 * ptr_enc_frame = NULL; - uint32 enc_frame_len; - //Call ApplySecurity on buffer contents depending on type. if (strcmp(security_type,"tc")==0){ - Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); + //Crypto_TC_ApplySecurity(&buffer, &buffer_size_i); } else if (strcmp(security_type,"tm")==0){ - Crypto_TM_ApplySecurity(buffer, &buffer_size_i); + //Crypto_TM_ApplySecurity(buffer, &buffer_size_i); } else if (strcmp(security_type,"aos")==0){ - Crypto_AOS_ApplySecurity(buffer, &buffer_size_i); + //Crypto_AOS_ApplySecurity(buffer, &buffer_size_i); } - #ifdef TC_DEBUG - OS_printf(KYEL "ApplySecurity Output:\n" RESET); - OS_printf(KYEL "\tBuffer size int:%d\n" RESET, enc_frame_len); - OS_printf(KYEL "\tEncrypted Frame Contents: \n\t" RESET); - - for(int i=0; i < enc_frame_len; i++) - { - OS_printf(KYEL "%02X" RESET, *(ptr_enc_frame+i)); - } - OS_printf("\n"); - #endif + debug_printf("Applied Security buffer size int:%d\n",buffer_size_i); + debug_printf("File content: \n"); + debug_hexprintf(buffer,buffer_size_i); free(buffer); - free(ptr_enc_frame); } \ No newline at end of file diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c new file mode 100644 index 00000000..0d7c5ebb --- /dev/null +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -0,0 +1,84 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +/* + * Simple apply security program that reads a file into memory and calls the Crypto_TC_ApplySecurity function on the data. + */ +#include "ut_tc_apply.h" +#include "utest.h" + +// Initilization header? + +UTEST(HAPPY_PATH, TC_APPLY_SECURITY) +{ + //Setup & Initialize CryptoLib + Crypto_Init(); + long buffer_size; + char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping.dat", &buffer_size); + uint32 buffer_size_i = (uint32) buffer_size; + + uint8 *ptr_enc_frame = NULL; + uint32 enc_frame_len; + + ASSERT_TRUE(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len) == 0); +} + +UTEST(BAD_SPACE_CRAFT_ID, TC_APPLY_SECURITY) +{ + //Setup & Initialize CryptoLib + Crypto_Init(); + long buffer_size; + char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat", &buffer_size); + uint32 buffer_size_i = (uint32) buffer_size; + + uint8 *ptr_enc_frame = NULL; + uint32 enc_frame_len; + + ASSERT_FALSE(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len) == 0); +} + +UTEST(BAD_VIRTUAL_CHANNEL_ID, TC_APPLY_SECURITY) +{ + //Setup & Initialize CryptoLib + Crypto_Init(); + long buffer_size; + char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat", &buffer_size); + uint32 buffer_size_i = (uint32) buffer_size; + + uint8 *ptr_enc_frame = NULL; + uint32 enc_frame_len; + + ASSERT_FALSE(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len) == 0); +} + +UTEST(NULL_BUFFER, TC_APPLY_SECURITY) +{ + //Setup & Initialize CryptoLib + Crypto_Init(); + long buffer_size; + char *buffer = NULL; + uint32 buffer_size_i = (uint32) buffer_size; + + uint8 *ptr_enc_frame = NULL; + uint32 enc_frame_len; + + ASSERT_FALSE(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len) == 0); +} + + + +UTEST_MAIN(); \ No newline at end of file diff --git a/fsw/crypto_util/include/ut_tc_apply.h b/fsw/crypto_util/include/ut_tc_apply.h new file mode 100644 index 00000000..449d76df --- /dev/null +++ b/fsw/crypto_util/include/ut_tc_apply.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +#ifndef CRYPTOLIB_UT_TC_APPLY_H +#define CRYPTOLIB_UT_TC_APPLY_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "crypto.h" +#include "shared_util.h" +#include + +#ifdef __cplusplus +} /* Close scope of 'extern "C"' declaration which encloses file. */ +#endif + +#endif //CRYPTOLIB_UT_TC_APPLY_H \ No newline at end of file diff --git a/fsw/crypto_util/include/utest.h b/fsw/crypto_util/include/utest.h new file mode 100644 index 00000000..41ec2ce7 --- /dev/null +++ b/fsw/crypto_util/include/utest.h @@ -0,0 +1,1156 @@ +/* + The latest version of this library is available on GitHub; + https://github.com/sheredom/utest.h +*/ + +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + For more information, please refer to +*/ + +#ifndef SHEREDOM_UTEST_H_INCLUDED +#define SHEREDOM_UTEST_H_INCLUDED + +#ifdef _MSC_VER +/* + Disable warning about not inlining 'inline' functions. +*/ +#pragma warning(disable : 4710) + +/* + Disable warning about inlining functions that are not marked 'inline'. +*/ +#pragma warning(disable : 4711) + +#if _MSC_VER > 1900 +/* + Disable warning about preprocessor macros not being defined in MSVC headers. +*/ +#pragma warning(disable : 4668) + +/* + Disable warning about no function prototype given in MSVC headers. +*/ +#pragma warning(disable : 4255) + +/* + Disable warning about pointer or reference to potentially throwing function. +*/ +#pragma warning(disable : 5039) +#endif + +#pragma warning(push, 1) +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +typedef __int64 utest_int64_t; +typedef unsigned __int64 utest_uint64_t; +#else +#include +typedef int64_t utest_int64_t; +typedef uint64_t utest_uint64_t; +#endif + +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(__cplusplus) +#define UTEST_C_FUNC extern "C" +#else +#define UTEST_C_FUNC +#endif + +#if defined(_MSC_VER) \ + || defined(__MINGW64__) \ + || defined(__MINGW32__) + +#if defined(__MINGW64__) || defined(__MINGW32__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#endif + +// define UTEST_USE_OLD_QPC before #include "utest.h" to use old QueryPerformanceCounter +#ifndef UTEST_USE_OLD_QPC +#pragma warning(push, 0) +#include +#pragma warning(pop) + +typedef LARGE_INTEGER utest_large_integer; +#else +//use old QueryPerformanceCounter definitions (not sure is this needed in some edge cases or not) +//on Win7 with VS2015 these extern declaration cause "second C linkage of overloaded function not allowed" error +typedef union { + struct { + unsigned long LowPart; + long HighPart; + } DUMMYSTRUCTNAME; + struct { + unsigned long LowPart; + long HighPart; + } u; + utest_int64_t QuadPart; +} utest_large_integer; + +UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceCounter( + utest_large_integer *); +UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceFrequency( + utest_large_integer *); + +#if defined(__MINGW64__) || defined(__MINGW32__) +#pragma GCC diagnostic pop +#endif +#endif + +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +/* + slightly obscure include here - we need to include glibc's features.h, but + we don't want to just include a header that might not be defined for other + c libraries like musl. Instead we include limits.h, which we know on all + glibc distributions includes features.h +*/ +#include + +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +#include + +#if ((2 < __GLIBC__) || ((2 == __GLIBC__) && (17 <= __GLIBC_MINOR__))) +/* glibc is version 2.17 or above, so we can just use clock_gettime */ +#define UTEST_USE_CLOCKGETTIME +#else +#include +#include +#endif +#else // Other libc implementations +#include +#define UTEST_USE_CLOCKGETTIME +#endif + +#elif defined(__APPLE__) +#include +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#define UTEST_PRId64 "I64d" +#define UTEST_PRIu64 "I64u" +#else +#include + +#define UTEST_PRId64 PRId64 +#define UTEST_PRIu64 PRIu64 +#endif + +#if defined(__cplusplus) +#define UTEST_INLINE inline + +#if defined(__clang__) +#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") + +#define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") +#else +#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS +#define UTEST_INITIALIZER_END_DISABLE_WARNINGS +#endif + +#define UTEST_INITIALIZER(f) \ + struct f##_cpp_struct { f##_cpp_struct(); }; \ + UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS static f##_cpp_struct f##_cpp_global UTEST_INITIALIZER_END_DISABLE_WARNINGS; \ + f##_cpp_struct::f##_cpp_struct() +#elif defined(_MSC_VER) +#define UTEST_INLINE __forceinline + +#if defined(_WIN64) +#define UTEST_SYMBOL_PREFIX +#else +#define UTEST_SYMBOL_PREFIX "_" +#endif + +#if defined(__clang__) +#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wmissing-variable-declarations\"") + +#define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") +#else +#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS +#define UTEST_INITIALIZER_END_DISABLE_WARNINGS +#endif + +#pragma section(".CRT$XCU", read) +#define UTEST_INITIALIZER(f) \ + static void __cdecl f(void); \ + UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ + __pragma(comment(linker, "/include:" UTEST_SYMBOL_PREFIX #f "_")) \ + UTEST_C_FUNC __declspec(allocate(".CRT$XCU")) void(__cdecl * \ + f##_)(void) = f; \ + UTEST_INITIALIZER_END_DISABLE_WARNINGS \ + static void __cdecl f(void) +#else +#if defined(__linux__) +#if defined(__clang__) +#if __has_warning("-Wreserved-id-macro") +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#endif +#endif + +#define __STDC_FORMAT_MACROS 1 + +#if defined(__clang__) +#if __has_warning("-Wreserved-id-macro") +#pragma clang diagnostic pop +#endif +#endif +#endif + +#define UTEST_INLINE inline + +#define UTEST_INITIALIZER(f) \ + static void f(void) __attribute__((constructor)); \ + static void f(void) +#endif + +#if defined(__cplusplus) +#define UTEST_CAST(type, x) static_cast(x) +#define UTEST_PTR_CAST(type, x) reinterpret_cast(x) +#define UTEST_EXTERN extern "C" +#define UTEST_NULL NULL +#else +#define UTEST_CAST(type, x) ((type)x) +#define UTEST_PTR_CAST(type, x) ((type)x) +#define UTEST_EXTERN extern +#define UTEST_NULL 0 +#endif + +#ifdef _MSC_VER +/* + io.h contains definitions for some structures with natural padding. This is + uninteresting, but for some reason MSVC's behaviour is to warn about + including this system header. That *is* interesting +*/ +#pragma warning(disable : 4820) +#pragma warning(push, 1) +#include +#pragma warning(pop) +#define UTEST_COLOUR_OUTPUT() (_isatty(_fileno(stdout))) +#else +#if defined(__EMSCRIPTEN__) +#include +#define UTEST_COLOUR_OUTPUT() false +#else +#include +#define UTEST_COLOUR_OUTPUT() (isatty(STDOUT_FILENO)) +#endif +#endif + +static UTEST_INLINE void *utest_realloc(void *const pointer, size_t new_size) { + void *const new_pointer = realloc(pointer, new_size); + + if (UTEST_NULL == new_pointer) { + free(new_pointer); + } + + return new_pointer; +} + +static UTEST_INLINE utest_int64_t utest_ns(void) { +#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) + utest_large_integer counter; + utest_large_integer frequency; + QueryPerformanceCounter(&counter); + QueryPerformanceFrequency(&frequency); + return UTEST_CAST(utest_int64_t, + (counter.QuadPart * 1000000000) / frequency.QuadPart); +#elif defined(__linux__) && defined(__STRICT_ANSI__) + return UTEST_CAST(utest_int64_t, clock()) * 1000000000 / CLOCKS_PER_SEC; +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + struct timespec ts; +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) + timespec_get(&ts, TIME_UTC); +#else + const clockid_t cid = CLOCK_REALTIME; +#if defined(UTEST_USE_CLOCKGETTIME) + clock_gettime(cid, &ts); +#else + syscall(SYS_clock_gettime, cid, &ts); +#endif +#endif + return UTEST_CAST(utest_int64_t, ts.tv_sec) * 1000 * 1000 * 1000 + ts.tv_nsec; +#elif __APPLE__ + return UTEST_CAST(utest_int64_t, mach_absolute_time()); +#elif __EMSCRIPTEN__ + return emscripten_performance_now() * 1000000.0; +#else +#error Unsupported platform! +#endif +} + +typedef void (*utest_testcase_t)(int *, size_t); + +struct utest_test_state_s { + utest_testcase_t func; + size_t index; + char *name; +}; + +struct utest_state_s { + struct utest_test_state_s *tests; + size_t tests_length; + FILE *output; +}; + +/* extern to the global state utest needs to execute */ +UTEST_EXTERN struct utest_state_s utest_state; + +#if defined(_MSC_VER) +#define UTEST_WEAK __forceinline +#else +#define UTEST_WEAK __attribute__((weak)) +#endif + +#if defined(_MSC_VER) +#define UTEST_UNUSED +#else +#define UTEST_UNUSED __attribute__((unused)) +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#define UTEST_PRINTF(...) \ + if (utest_state.output) { \ + fprintf(utest_state.output, __VA_ARGS__); \ + } \ + printf(__VA_ARGS__) +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#ifdef _MSC_VER +#define UTEST_SNPRINTF(BUFFER, N, ...) _snprintf_s(BUFFER, N, N, __VA_ARGS__) +#else +#define UTEST_SNPRINTF(...) snprintf(__VA_ARGS__) +#endif + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#if defined(__cplusplus) +/* if we are using c++ we can use overloaded methods (its in the language) */ +#define UTEST_OVERLOADABLE +#elif defined(__clang__) +/* otherwise, if we are using clang with c - use the overloadable attribute */ +#define UTEST_OVERLOADABLE __attribute__((overloadable)) +#endif + +#if defined(UTEST_OVERLOADABLE) +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f) { + UTEST_PRINTF("%f", UTEST_CAST(double, f)); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d) { + UTEST_PRINTF("%f", d); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d) { + UTEST_PRINTF("%Lf", d); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i) { + UTEST_PRINTF("%d", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i) { + UTEST_PRINTF("%u", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i) { + UTEST_PRINTF("%ld", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i) { + UTEST_PRINTF("%lu", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p) { + UTEST_PRINTF("%p", p); +} + +/* + long long is a c++11 extension +*/ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || \ + defined(__cplusplus) && (__cplusplus >= 201103L) + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i) { + UTEST_PRINTF("%lld", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long unsigned int i); +UTEST_WEAK UTEST_OVERLOADABLE void +utest_type_printer(long long unsigned int i) { + UTEST_PRINTF("%llu", i); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +#define utest_type_printer(val) \ + UTEST_PRINTF(_Generic((val), signed char \ + : "%d", unsigned char \ + : "%u", short \ + : "%d", unsigned short \ + : "%u", int \ + : "%d", long \ + : "%ld", long long \ + : "%lld", unsigned \ + : "%u", unsigned long \ + : "%lu", unsigned long long \ + : "%llu", float \ + : "%f", double \ + : "%f", long double \ + : "%Lf", default \ + : _Generic((val - val), ptrdiff_t \ + : "%p", default \ + : "undef")), \ + (val)) +#else +/* + we don't have the ability to print the values we got, so we create a macro + to tell our users we can't do anything fancy +*/ +#define utest_type_printer(...) UTEST_PRINTF("undef") +#endif + +#ifdef _MSC_VER +#define UTEST_SURPRESS_WARNING_BEGIN \ + __pragma(warning(push)) __pragma(warning(disable : 4127)) +#define UTEST_SURPRESS_WARNING_END __pragma(warning(pop)) +#else +#define UTEST_SURPRESS_WARNING_BEGIN +#define UTEST_SURPRESS_WARNING_END +#endif + +#if defined(__cplusplus) && (__cplusplus >= 201103L) +#define UTEST_AUTO(x) auto +#elif !defined(__cplusplus) + +#if defined(__clang__) +/* clang-format off */ +/* had to disable clang-format here because it malforms the pragmas */ +#define UTEST_AUTO(x) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wgnu-auto-type\"") __auto_type \ + _Pragma("clang diagnostic pop") +/* clang-format on */ +#else +#define UTEST_AUTO(x) __typeof__(x + 0) +#endif + +#else +#define UTEST_AUTO(x) typeof(x + 0) +#endif + +#if defined(__clang__) +#define UTEST_STRNCMP(x, y, size) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") \ + strncmp(x, y, size) _Pragma("clang diagnostic pop") +#else +#define UTEST_STRNCMP(x, y, size) strncmp(x, y, size) +#endif + +#if defined(__clang__) +#define UTEST_EXPECT(x, y, cond) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wlanguage-extension-token\"") \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \ + _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \ + UTEST_AUTO(x) xEval = (x); \ + UTEST_AUTO(y) yEval = (y); \ + if (!((xEval)cond(yEval))) { \ + _Pragma("clang diagnostic pop") \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : "); \ + utest_type_printer(xEval); \ + UTEST_PRINTF("\n"); \ + UTEST_PRINTF(" Actual : "); \ + utest_type_printer(yEval); \ + UTEST_PRINTF("\n"); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#elif defined(__GNUC__) +#define UTEST_EXPECT(x, y, cond) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + UTEST_AUTO(x) xEval = (x); \ + UTEST_AUTO(y) yEval = (y); \ + if (!((xEval)cond(yEval))) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : "); \ + utest_type_printer(xEval); \ + UTEST_PRINTF("\n"); \ + UTEST_PRINTF(" Actual : "); \ + utest_type_printer(yEval); \ + UTEST_PRINTF("\n"); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#else +#define UTEST_EXPECT(x, y, cond) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (!((x)cond(y))) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#endif + +#define EXPECT_TRUE(x) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (!(x)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : true\n"); \ + UTEST_PRINTF(" Actual : %s\n", (x) ? "true" : "false"); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_FALSE(x) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (x) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : false\n"); \ + UTEST_PRINTF(" Actual : %s\n", (x) ? "true" : "false"); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_EQ(x, y) UTEST_EXPECT(x, y, ==) +#define EXPECT_NE(x, y) UTEST_EXPECT(x, y, !=) +#define EXPECT_LT(x, y) UTEST_EXPECT(x, y, <) +#define EXPECT_LE(x, y) UTEST_EXPECT(x, y, <=) +#define EXPECT_GT(x, y) UTEST_EXPECT(x, y, >) +#define EXPECT_GE(x, y) UTEST_EXPECT(x, y, >=) + +#define EXPECT_STREQ(x, y) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (0 != strcmp(x, y)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%s\"\n", x); \ + UTEST_PRINTF(" Actual : \"%s\"\n", y); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_STRNE(x, y) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (0 == strcmp(x, y)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%s\"\n", x); \ + UTEST_PRINTF(" Actual : \"%s\"\n", y); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_STRNEQ(x, y, n) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (0 != UTEST_STRNCMP(x, y, n)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, n), x); \ + UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, n), y); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_STRNNE(x, y, n) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (0 == UTEST_STRNCMP(x, y, n)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, n), x); \ + UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, n), y); \ + *utest_result = 1; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#if defined(__clang__) +#define UTEST_ASSERT(x, y, cond) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wlanguage-extension-token\"") \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \ + _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \ + UTEST_AUTO(x) xEval = (x); \ + UTEST_AUTO(y) yEval = (y); \ + if (!((xEval)cond(yEval))) { \ + _Pragma("clang diagnostic pop") \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : "); \ + utest_type_printer(xEval); \ + UTEST_PRINTF("\n"); \ + UTEST_PRINTF(" Actual : "); \ + utest_type_printer(yEval); \ + UTEST_PRINTF("\n"); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#elif defined(__GNUC__) +#define UTEST_ASSERT(x, y, cond) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + UTEST_AUTO(x) xEval = (x); \ + UTEST_AUTO(y) yEval = (y); \ + if (!((xEval)cond(yEval))) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : "); \ + utest_type_printer(xEval); \ + UTEST_PRINTF("\n"); \ + UTEST_PRINTF(" Actual : "); \ + utest_type_printer(yEval); \ + UTEST_PRINTF("\n"); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#else +#define UTEST_ASSERT(x, y, cond) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (!((x)cond(y))) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#endif + +#define ASSERT_TRUE(x) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (!(x)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : true\n"); \ + UTEST_PRINTF(" Actual : %s\n", (x) ? "true" : "false"); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define ASSERT_FALSE(x) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (x) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : false\n"); \ + UTEST_PRINTF(" Actual : %s\n", (x) ? "true" : "false"); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define ASSERT_EQ(x, y) UTEST_ASSERT(x, y, ==) +#define ASSERT_NE(x, y) UTEST_ASSERT(x, y, !=) +#define ASSERT_LT(x, y) UTEST_ASSERT(x, y, <) +#define ASSERT_LE(x, y) UTEST_ASSERT(x, y, <=) +#define ASSERT_GT(x, y) UTEST_ASSERT(x, y, >) +#define ASSERT_GE(x, y) UTEST_ASSERT(x, y, >=) + +#define ASSERT_STREQ(x, y) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (0 != strcmp(x, y)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%s\"\n", x); \ + UTEST_PRINTF(" Actual : \"%s\"\n", y); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define ASSERT_STRNE(x, y) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (0 == strcmp(x, y)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%s\"\n", x); \ + UTEST_PRINTF(" Actual : \"%s\"\n", y); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define ASSERT_STRNEQ(x, y, n) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (0 != UTEST_STRNCMP(x, y, n)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, n), x); \ + UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, n), y); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define ASSERT_STRNNE(x, y, n) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (0 == UTEST_STRNCMP(x, y, n)) { \ + UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, n), x); \ + UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, n), y); \ + *utest_result = 1; \ + return; \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define UTEST(SET, NAME) \ + UTEST_EXTERN struct utest_state_s utest_state; \ + static void utest_run_##SET##_##NAME(int *utest_result); \ + static void utest_##SET##_##NAME(int *utest_result, size_t utest_index) { \ + (void)utest_index; \ + utest_run_##SET##_##NAME(utest_result); \ + } \ + UTEST_INITIALIZER(utest_register_##SET##_##NAME) { \ + const size_t index = utest_state.tests_length++; \ + const char *name_part = #SET "." #NAME; \ + const size_t name_size = strlen(name_part) + 1; \ + char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ + utest_state.tests = UTEST_PTR_CAST( \ + struct utest_test_state_s *, \ + utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ + sizeof(struct utest_test_state_s) * \ + utest_state.tests_length)); \ + utest_state.tests[index].func = &utest_##SET##_##NAME; \ + utest_state.tests[index].name = name; \ + utest_state.tests[index].index = 0; \ + UTEST_SNPRINTF(name, name_size, "%s", name_part); \ + } \ + void utest_run_##SET##_##NAME(int *utest_result) + +#define UTEST_F_SETUP(FIXTURE) \ + static void utest_f_setup_##FIXTURE(int *utest_result, \ + struct FIXTURE *utest_fixture) + +#define UTEST_F_TEARDOWN(FIXTURE) \ + static void utest_f_teardown_##FIXTURE(int *utest_result, \ + struct FIXTURE *utest_fixture) + +#define UTEST_F(FIXTURE, NAME) \ + UTEST_EXTERN struct utest_state_s utest_state; \ + static void utest_f_setup_##FIXTURE(int *, struct FIXTURE *); \ + static void utest_f_teardown_##FIXTURE(int *, struct FIXTURE *); \ + static void utest_run_##FIXTURE##_##NAME(int *, struct FIXTURE *); \ + static void utest_f_##FIXTURE##_##NAME(int *utest_result, \ + size_t utest_index) { \ + struct FIXTURE fixture; \ + (void)utest_index; \ + memset(&fixture, 0, sizeof(fixture)); \ + utest_f_setup_##FIXTURE(utest_result, &fixture); \ + if (0 != *utest_result) { \ + return; \ + } \ + utest_run_##FIXTURE##_##NAME(utest_result, &fixture); \ + utest_f_teardown_##FIXTURE(utest_result, &fixture); \ + } \ + UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME) { \ + const size_t index = utest_state.tests_length++; \ + const char *name_part = #FIXTURE "." #NAME; \ + const size_t name_size = strlen(name_part) + 1; \ + char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ + utest_state.tests = UTEST_PTR_CAST( \ + struct utest_test_state_s *, \ + utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ + sizeof(struct utest_test_state_s) * \ + utest_state.tests_length)); \ + utest_state.tests[index].func = &utest_f_##FIXTURE##_##NAME; \ + utest_state.tests[index].name = name; \ + UTEST_SNPRINTF(name, name_size, "%s", name_part); \ + } \ + void utest_run_##FIXTURE##_##NAME(int *utest_result, \ + struct FIXTURE *utest_fixture) + +#define UTEST_I_SETUP(FIXTURE) \ + static void utest_i_setup_##FIXTURE( \ + int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) + +#define UTEST_I_TEARDOWN(FIXTURE) \ + static void utest_i_teardown_##FIXTURE( \ + int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) + +#define UTEST_I(FIXTURE, NAME, INDEX) \ + UTEST_EXTERN struct utest_state_s utest_state; \ + static void utest_run_##FIXTURE##_##NAME##_##INDEX(int *, struct FIXTURE *); \ + static void utest_i_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ + size_t index) { \ + struct FIXTURE fixture; \ + memset(&fixture, 0, sizeof(fixture)); \ + utest_i_setup_##FIXTURE(utest_result, &fixture, index); \ + if (0 != *utest_result) { \ + return; \ + } \ + utest_run_##FIXTURE##_##NAME##_##INDEX(utest_result, &fixture); \ + utest_i_teardown_##FIXTURE(utest_result, &fixture, index); \ + } \ + UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME##_##INDEX) { \ + size_t i; \ + utest_uint64_t iUp; \ + for (i = 0; i < (INDEX); i++) { \ + const size_t index = utest_state.tests_length++; \ + const char *name_part = #FIXTURE "." #NAME; \ + const size_t name_size = strlen(name_part) + 32; \ + char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ + utest_state.tests = UTEST_PTR_CAST( \ + struct utest_test_state_s *, \ + utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ + sizeof(struct utest_test_state_s) * \ + utest_state.tests_length)); \ + utest_state.tests[index].func = &utest_i_##FIXTURE##_##NAME##_##INDEX; \ + utest_state.tests[index].index = i; \ + utest_state.tests[index].name = name; \ + iUp = UTEST_CAST(utest_uint64_t, i); \ + UTEST_SNPRINTF(name, name_size, "%s/%" UTEST_PRIu64, name_part, iUp); \ + } \ + } \ + void utest_run_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ + struct FIXTURE *utest_fixture) + +UTEST_WEAK +int utest_should_filter_test(const char *filter, const char *testcase); +UTEST_WEAK int utest_should_filter_test(const char *filter, + const char *testcase) { + if (filter) { + const char *filter_cur = filter; + const char *testcase_cur = testcase; + const char *filter_wildcard = UTEST_NULL; + + while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { + if ('*' == *filter_cur) { + /* store the position of the wildcard */ + filter_wildcard = filter_cur; + + /* skip the wildcard character */ + filter_cur++; + + while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { + if ('*' == *filter_cur) { + /* + we found another wildcard (filter is something like *foo*) so we + exit the current loop, and return to the parent loop to handle + the wildcard case + */ + break; + } else if (*filter_cur != *testcase_cur) { + /* otherwise our filter didn't match, so U_RESET it */ + filter_cur = filter_wildcard; + } + + /* move testcase along */ + testcase_cur++; + + /* move filter along */ + filter_cur++; + } + + if (('\0' == *filter_cur) && ('\0' == *testcase_cur)) { + return 0; + } + + /* if the testcase has been exhausted, we don't have a match! */ + if ('\0' == *testcase_cur) { + return 1; + } + } else { + if (*testcase_cur != *filter_cur) { + /* test case doesn't match filter */ + return 1; + } else { + /* move our filter and testcase forward */ + testcase_cur++; + filter_cur++; + } + } + } + + if (('\0' != *filter_cur) || + (('\0' != *testcase_cur) && + ((filter == filter_cur) || ('*' != filter_cur[-1])))) { + /* we have a mismatch! */ + return 1; + } + } + + return 0; +} + +static UTEST_INLINE FILE *utest_fopen(const char *filename, const char *mode) { +#ifdef _MSC_VER + FILE *file; + if (0 == fopen_s(&file, filename, mode)) { + return file; + } else { + return UTEST_NULL; + } +#else + return fopen(filename, mode); +#endif +} + +static UTEST_INLINE int utest_main(int argc, const char *const argv[]); +int utest_main(int argc, const char *const argv[]) { + utest_uint64_t failed = 0; + size_t index = 0; + size_t *failed_testcases = UTEST_NULL; + size_t failed_testcases_length = 0; + const char *filter = UTEST_NULL; + utest_uint64_t ran_tests = 0; + + enum colours { U_RESET, GREEN, RED }; + + const int use_colours = UTEST_COLOUR_OUTPUT(); + const char *colours[] = {"\033[0m", "\033[32m", "\033[31m"}; + + if (!use_colours) { + for (index = 0; index < sizeof colours / sizeof colours[0]; index++) { + colours[index] = ""; + } + } + /* loop through all arguments looking for our options */ + for (index = 1; index < UTEST_CAST(size_t, argc); index++) { + /* Informational switches */ + const char help_str[] = "--help"; + const char list_str[] = "--list-tests"; + /* Test config switches */ + const char filter_str[] = "--filter="; + const char output_str[] = "--output="; + + if (0 == UTEST_STRNCMP(argv[index], help_str, strlen(help_str))) { + printf("utest.h - the single file unit testing solution for C/C++!\n" + "Command line Options:\n" + " --help Show this message and exit.\n" + " --filter= Filter the test cases to run (EG. MyTest*.a " + "would run MyTestCase.a but not MyTestCase.b).\n" + " --list-tests List testnames, one per line. Output names " + "can be passed to --filter.\n" + " --output= Output an xunit XML file to the file " + "specified in .\n"); + goto cleanup; + } else if (0 == + UTEST_STRNCMP(argv[index], filter_str, strlen(filter_str))) { + /* user wants to filter what test cases run! */ + filter = argv[index] + strlen(filter_str); + } else if (0 == + UTEST_STRNCMP(argv[index], output_str, strlen(output_str))) { + utest_state.output = utest_fopen(argv[index] + strlen(output_str), "w+"); + } else if (0 == UTEST_STRNCMP(argv[index], list_str, strlen(list_str))) { + for (index = 0; index < utest_state.tests_length; index++) { + UTEST_PRINTF("%s\n", utest_state.tests[index].name); + } + /* when printing the test list, don't actually run the tests */ + return 0; + } + } + + for (index = 0; index < utest_state.tests_length; index++) { + if (utest_should_filter_test(filter, utest_state.tests[index].name)) { + continue; + } + + ran_tests++; + } + printf("%s[==========]%s Running %" UTEST_PRIu64 " test cases.\n", + colours[GREEN], colours[U_RESET], UTEST_CAST(utest_uint64_t, ran_tests)); + + if (utest_state.output) { + fprintf(utest_state.output, "\n"); + fprintf(utest_state.output, + "\n", + UTEST_CAST(utest_uint64_t, ran_tests)); + fprintf(utest_state.output, + "\n", + UTEST_CAST(utest_uint64_t, ran_tests)); + } + + for (index = 0; index < utest_state.tests_length; index++) { + int result = 0; + utest_int64_t ns = 0; + + if (utest_should_filter_test(filter, utest_state.tests[index].name)) { + continue; + } + + printf("%s[ RUN ]%s %s\n", colours[GREEN], colours[U_RESET], + utest_state.tests[index].name); + + if (utest_state.output) { + fprintf(utest_state.output, "", + utest_state.tests[index].name); + } + + ns = utest_ns(); + errno = 0; + utest_state.tests[index].func(&result, utest_state.tests[index].index); + ns = utest_ns() - ns; + + if (utest_state.output) { + fprintf(utest_state.output, "\n"); + } + + if (0 != result) { + const size_t failed_testcase_index = failed_testcases_length++; + failed_testcases = UTEST_PTR_CAST( + size_t *, utest_realloc(UTEST_PTR_CAST(void *, failed_testcases), + sizeof(size_t) * failed_testcases_length)); + if (UTEST_NULL != failed_testcases) { + failed_testcases[failed_testcase_index] = index; + } + failed++; + printf("%s[ FAILED ]%s %s (%" UTEST_PRId64 "ns)\n", colours[RED], + colours[U_RESET], utest_state.tests[index].name, ns); + } else { + printf("%s[ OK ]%s %s (%" UTEST_PRId64 "ns)\n", colours[GREEN], + colours[U_RESET], utest_state.tests[index].name, ns); + } + } + + printf("%s[==========]%s %" UTEST_PRIu64 " test cases ran.\n", colours[GREEN], + colours[U_RESET], ran_tests); + printf("%s[ PASSED ]%s %" UTEST_PRIu64 " tests.\n", colours[GREEN], + colours[U_RESET], ran_tests - failed); + + if (0 != failed) { + printf("%s[ FAILED ]%s %" UTEST_PRIu64 " tests, listed below:\n", + colours[RED], colours[U_RESET], failed); + for (index = 0; index < failed_testcases_length; index++) { + printf("%s[ FAILED ]%s %s\n", colours[RED], colours[U_RESET], + utest_state.tests[failed_testcases[index]].name); + } + } + + if (utest_state.output) { + fprintf(utest_state.output, "\n\n"); + } + +cleanup: + for (index = 0; index < utest_state.tests_length; index++) { + free(UTEST_PTR_CAST(void *, utest_state.tests[index].name)); + } + + free(UTEST_PTR_CAST(void *, failed_testcases)); + free(UTEST_PTR_CAST(void *, utest_state.tests)); + + if (utest_state.output) { + fclose(utest_state.output); + } + + return UTEST_CAST(int, failed); +} + +/* + we need, in exactly one source file, define the global struct that will hold + the data we need to run utest. This macro allows the user to declare the + data without having to use the UTEST_MAIN macro, thus allowing them to write + their own main() function. +*/ +#define UTEST_STATE() struct utest_state_s utest_state = {0, 0, 0} + +/* + define a main() function to call into utest.h and start executing tests! A + user can optionally not use this macro, and instead define their own main() + function and manually call utest_main. The user must, in exactly one source + file, use the UTEST_STATE macro to declare a global struct variable that + utest requires. +*/ +#define UTEST_MAIN() \ + UTEST_STATE(); \ + int main(int argc, const char *const argv[]) { \ + return utest_main(argc, argv); \ + } + +#endif /* SHEREDOM_UTEST_H_INCLUDED */ \ No newline at end of file diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index caf8e124..81745d36 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -43,7 +43,9 @@ ivv-itc@lists.nasa.gov #define RESET "\033[0m" #else #define KRED - #define KGRN + #define RED + #define KGRN + #define GREEN #define KYEL #define KBLU #define KMAG From 72ee0dbaf825fc2ec4b5126916c76b2b60295ff6 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 3 Nov 2021 13:57:17 -0700 Subject: [PATCH 018/184] AKMC-113: Add more MySQL modularity and configuration --- CMakeLists.txt | 4 +- fsw/CMakeLists.txt | 15 +++++ .../create_sadb_user_grant_permissions.sql | 2 +- fsw/public_inc/crypto_config.h | 6 ++ fsw/public_inc/crypto_error.h | 3 + fsw/public_inc/sadb_mariadb_error.h | 10 ++++ fsw/public_inc/sadb_routine.h | 3 +- fsw/src/crypto.c | 5 +- fsw/src/sadb_routine_inmemory.template.c | 12 +++- .../sadb_routine_mariadb.template.c | 56 +++++++++++++++---- 10 files changed, 97 insertions(+), 19 deletions(-) create mode 100644 fsw/public_inc/sadb_mariadb_error.h rename fsw/{src => src_mysql}/sadb_routine_mariadb.template.c (59%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8eda60d2..33723c59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,9 @@ project(CRYPTO C) set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") -OPTION(DEBUG "Debug" OFF) # Disabled by default +OPTION(DEBUG "Debug" OFF) # Disabled by default, enable with: -DDEBUG=ON +OPTION(MYSQL "Mysql" OFF) # Disabled by default, enable with: -DMYSQL=ON + IF(DEBUG) ADD_DEFINITIONS(-DDEBUG -DOCF_DEBUG -DFECF_DEBUG -DSA_DEBUG -DPDU_DEBUG -DCCSDS_DEBUG -DTC_DEBUG -DMAC_DEBUG -DTM_DEBUG) add_compile_options(-ggdb) diff --git a/fsw/CMakeLists.txt b/fsw/CMakeLists.txt index 3bc71820..f684cc64 100644 --- a/fsw/CMakeLists.txt +++ b/fsw/CMakeLists.txt @@ -17,6 +17,11 @@ include_directories(public_inc) aux_source_directory(src LIB_SRC_FILES) +if(MYSQL) + aux_source_directory(src_mysql LIB_SRC_MYSQL_FILES) + list(APPEND LIB_SRC_FILES ${LIB_SRC_MYSQL_FILES}) +endif() + if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) include(CTest) @@ -30,6 +35,16 @@ else() #standalone build add_library(Crypto SHARED ${LIB_SRC_FILES}) endif() +if(MYSQL) + execute_process(COMMAND mysql_config --cflags + OUTPUT_VARIABLE MYSQL_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND mysql_config --libs + OUTPUT_VARIABLE MYSQL_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE) + + target_compile_options(Crypto PUBLIC ${MYSQL_CFLAGS}) + target_link_libraries(Crypto ${MYSQL_LIBS}) +endif() + # Add libgcrypt target_link_libraries(Crypto gcrypt) diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql index e4d959c9..10d3a746 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql @@ -1,3 +1,3 @@ -Create User IF NOT EXISTS sadb_user; +Create User IF NOT EXISTS sadb_user IDENTIFIED BY 'sadb_password'; GRANT ALL PRIVILEGES ON sadb.* TO 'sadb_user' @ '%'; \ No newline at end of file diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index caf8e124..c08bb943 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -170,4 +170,10 @@ ivv-itc@lists.nasa.gov #define SEGMENTATION_HDR 1 //(1=true,0=false) #define HAS_FECF 1 //(1=true,0=false) +// MySQL - MariaDB Defines (will be dynamically loaded properties in the future) + #define MYSQL_USER "sadb_user" + #define MYSQL_PASS "sadb_password" + #define MYSQL_HOST "localhost" + #define MYSQL_DB "sadb" + #define MYSQL_PORT 0 #endif \ No newline at end of file diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h index d69e7316..3cbdb59f 100644 --- a/fsw/public_inc/crypto_error.h +++ b/fsw/public_inc/crypto_error.h @@ -17,4 +17,7 @@ ivv-itc@lists.nasa.gov #ifndef _crypto_error_h_ #define _crypto_error_h_ +#include "sadb_mariadb_error.h" + + #endif //_crypto_error_h_ diff --git a/fsw/public_inc/sadb_mariadb_error.h b/fsw/public_inc/sadb_mariadb_error.h new file mode 100644 index 00000000..f57374af --- /dev/null +++ b/fsw/public_inc/sadb_mariadb_error.h @@ -0,0 +1,10 @@ +// +// Created by isaleh on 11/3/2021. +// + +#ifndef _sadb_mariadb_error_h_ +#define _sadb_mariadb_error_h_ + +#define SADB_MARIADB_CONNECTION_FAILED 300 + +#endif //_sadb_mariadb_error_h_ diff --git a/fsw/public_inc/sadb_routine.h b/fsw/public_inc/sadb_routine.h index ad8b44a5..dfc937bb 100644 --- a/fsw/public_inc/sadb_routine.h +++ b/fsw/public_inc/sadb_routine.h @@ -26,9 +26,10 @@ #include "crypto_structs.h" typedef struct { - // Security Association Initialization Functions + // Security Association Initialization & Management Functions int32 (*sadb_config)(void); int32 (*sadb_init)(void); + int32 (*sadb_close)(void); // Security Association Interaction Functions int32 (*sadb_get_sa_from_spi)(uint16,SecurityAssociation_t**); // Security Association Utility Functions diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index f87c9218..721ab991 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -120,7 +120,8 @@ int32 Crypto_Init(void) { int32 status = OS_SUCCESS; - sadb_routine = get_sadb_routine_inmemory(); + //TODO -- Make the routine that gets called variable based on configuration! + sadb_routine = get_sadb_routine_mariadb(); // Initialize libgcrypt if (!gcry_check_version(GCRYPT_VERSION)) @@ -2175,7 +2176,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro // TODO: I don't think this is needed. //if (status == OS_SUCCESS) //{ - // if (sa_ptr->.gvcid_tc_blk[tc_sdls_processed_frame->tc_header.vcid].vcid != tc_sdls_processed_frame->tc_header.vcid) + // if (sa_ptr->gvcid_tc_blk[tc_sdls_processed_frame->tc_header.vcid].vcid != tc_sdls_processed_frame->tc_header.vcid) // { // OS_printf(KRED "Error: VCID not mapped to provided SPI! \n" RESET); // status = OS_ERROR; diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c index e8ef6e28..7e461222 100644 --- a/fsw/src/sadb_routine_inmemory.template.c +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -20,6 +20,7 @@ // Security Association Initialization Functions static int32 sadb_config(void); static int32 sadb_init(void); +static int32 sadb_close(void); // Security Association Interaction Functions static int32 sadb_get_sa_from_spi(uint16,SecurityAssociation_t**); // Security Association Utility Functions @@ -44,6 +45,7 @@ SadbRoutine get_sadb_routine_inmemory(void) { sadb_routine.sadb_config = sadb_config; sadb_routine.sadb_init = sadb_init; + sadb_routine.sadb_close = sadb_close; sadb_routine.sadb_get_sa_from_spi = sadb_get_sa_from_spi; sadb_routine.sadb_sa_start = sadb_sa_start; sadb_routine.sadb_sa_expire = sadb_sa_expire; @@ -56,7 +58,7 @@ SadbRoutine get_sadb_routine_inmemory(void) return &sadb_routine; } -int32 sadb_config(void) +static int32 sadb_config(void) { int32 status = OS_SUCCESS; @@ -168,7 +170,7 @@ int32 sadb_config(void) return status; } -int32 sadb_init(void) +static int32 sadb_init(void) { int32 status = OS_SUCCESS; @@ -191,6 +193,12 @@ int32 sadb_init(void) return status; } +static int32 sadb_close(void) +{ + //closing not necessary for inmemory DB. + return OS_SUCCESS; +} + /* ** Security Association Interaction Functions diff --git a/fsw/src/sadb_routine_mariadb.template.c b/fsw/src_mysql/sadb_routine_mariadb.template.c similarity index 59% rename from fsw/src/sadb_routine_mariadb.template.c rename to fsw/src_mysql/sadb_routine_mariadb.template.c index a93fac11..1cf6d52c 100644 --- a/fsw/src/sadb_routine_mariadb.template.c +++ b/fsw/src_mysql/sadb_routine_mariadb.template.c @@ -14,10 +14,15 @@ #include "sadb_routine.h" #include "crypto_structs.h" +#include "crypto_config.h" +#include "crypto_error.h" + +#include // Security Association Initialization Functions static int32 sadb_config(void); static int32 sadb_init(void); +static int32 sadb_close(void); // Security Association Interaction Functions static int32 sadb_get_sa_from_spi(uint16,SecurityAssociation_t**); // Security Association Utility Functions @@ -29,7 +34,8 @@ static int32 sadb_sa_create(void); static int32 sadb_sa_setARSN(void); static int32 sadb_sa_setARSNW(void); static int32 sadb_sa_delete(void); - +//MySQL local functions +static int32 finish_with_error(MYSQL *con,int err); /* ** Global Variables @@ -37,6 +43,7 @@ static int32 sadb_sa_delete(void); // Security static SadbRoutineStruct sadb_routine; static SecurityAssociation_t sa[NUM_SA]; +static MYSQL* con; SadbRoutine get_sadb_routine_mariadb(void) { @@ -54,19 +61,44 @@ SadbRoutine get_sadb_routine_mariadb(void) return &sadb_routine; } -int32 sadb_config(void) +static int32 sadb_config(void) { return OS_SUCCESS; } -int32 sadb_init(void){return OS_SUCCESS;} + +static int32 sadb_init(void) +{ + int32 status = OS_SUCCESS; + con = mysql_init(NULL); + + //TODO - add mysql_options/mysql_get_ssl_cipher logic for mTLS connections. + + if (mysql_real_connect(con, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, MYSQL_PORT, NULL, 0) == NULL) + { //0,NULL,0 are port number, unix socket, client flag + status = finish_with_error(con,SADB_MARIADB_CONNECTION_FAILED); + } + + return status; +} + +static int32 sadb_close(void){return OS_SUCCESS;}; + // Security Association Interaction Functions -int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_association){return OS_SUCCESS;} +static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_association){return OS_SUCCESS;} // Security Association Utility Functions -int32 sadb_sa_start(TC_t* tc_frame){return OS_SUCCESS;} -int32 sadb_sa_expire(void){return OS_SUCCESS;} -int32 sadb_sa_rekey(void){return OS_SUCCESS;} -int32 sadb_sa_status(char* ingest){return OS_SUCCESS;} -int32 sadb_sa_create(void){return OS_SUCCESS;} -int32 sadb_sa_setARSN(void){return OS_SUCCESS;} -int32 sadb_sa_setARSNW(void){return OS_SUCCESS;} -int32 sadb_sa_delete(void){return OS_SUCCESS;} +static int32 sadb_sa_start(TC_t* tc_frame){return OS_SUCCESS;} +static int32 sadb_sa_expire(void){return OS_SUCCESS;} +static int32 sadb_sa_rekey(void){return OS_SUCCESS;} +static int32 sadb_sa_status(char* ingest){return OS_SUCCESS;} +static int32 sadb_sa_create(void){return OS_SUCCESS;} +static int32 sadb_sa_setARSN(void){return OS_SUCCESS;} +static int32 sadb_sa_setARSNW(void){return OS_SUCCESS;} +static int32 sadb_sa_delete(void){return OS_SUCCESS;} + + +static int32 finish_with_error(MYSQL *con, int err) +{ + fprintf(stderr, "%s\n", mysql_error(con)); + mysql_close(con); + return err; +} \ No newline at end of file From a786df7650a75e31381c1d7feaf5bf62a980f6d2 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 3 Nov 2021 16:08:09 -0700 Subject: [PATCH 019/184] AKMC-113: Remove multiple gvcid per SA functionality, add mysql unit test SA creations cripts --- .../create_sadb.sql | 25 +++--- ...e_sadb_unit_test_security_associations.sql | 33 +++++++ .../create_sadb_user_grant_permissions.sql | 5 +- .../delete_sadb.sql | 1 + fsw/public_inc/crypto_structs.h | 2 +- fsw/src/crypto.c | 8 +- fsw/src/sadb_routine_inmemory.template.c | 90 ++++++++++++------- 7 files changed, 116 insertions(+), 48 deletions(-) create mode 100644 fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql create mode 100644 fsw/crypto_sadb/sadb_mariadb_admin_scripts/delete_sadb.sql diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql index 0a817c9a..ac781c71 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql @@ -2,13 +2,18 @@ CREATE DATABASE IF NOT EXISTS sadb; USE sadb; +-- IV_LEN should probably not have that default -- to be reviewed. + CREATE TABLE security_associations ( sa_id INT NOT NULL - ,ekid MEDIUMINT NOT NULL - ,akid mediumint NOT NULL - ,sa_state SMALLINT NOT NULL - ,gvcid INT + ,ekid MEDIUMINT NOT NULL DEFAULT sa_id + ,akid MEDIUMINT NOT NULL DEFAULT sa_id + ,sa_state SMALLINT NOT NULL DEFAULT 0 + ,tfvn TINYINT + ,scid SMALLINT + ,vcid TINYINT + ,mapid TINYINT ,lpid SMALLINT ,est SMALLINT ,ast SMALLINT @@ -17,15 +22,15 @@ CREATE TABLE security_associations ,shplf_len SMALLINT ,stmacf_len SMALLINT ,ecs_len SMALLINT - ,ecs SMALLINT - ,iv_len SMALLINT + ,ecs SMALLINT NOT NULL DEFAULT 0 + ,iv_len SMALLINT NOT NULL DEFAULT 12 ,iv SMALLINT - ,acs_len SMALLINT - ,acs SMALLINT + ,acs_len SMALLINT NOT NULL DEFAULT 0 + ,acs SMALLINT NOT NULL DEFAULT 0 ,abm_len MEDIUMINT ,abm SMALLINT - ,arc_len SMALLINT - ,arc SMALLINT + ,arc_len SMALLINT NOT NULL DEFAULT 0 + ,arc SMALLINT NOT NULL DEFAULT 5 ,arcw_len SMALLINT ,arcw SMALLINT ); \ No newline at end of file diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql new file mode 100644 index 00000000..61d106c3 --- /dev/null +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql @@ -0,0 +1,33 @@ +USE sadb; + +-- SA 1 - CLEAR MODE +INSERT INTO security_associations (sa_id,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) +VALUES (1,3,0,0,1,0,1,5,0,3,0,0); + +-- SA 2 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 128 +INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) +VALUES (2,128,2,1,1,12,12,0,20,0,1,5,11); + +-- SA 3 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 129 +INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) +VALUES (3,129,2,1,1,12,12,0,20,0,1,5,11); + +-- SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 +INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +VALUES (4,130,2,1,1,12,12,0,20,0,1,5,11,0,3,0,0); + +-- SA 5 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 131 +INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) +VALUES (5,131,2,1,1,12,12,0,20,0,1,5,11); + +-- SA 6 - UNKEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: - +INSERT INTO security_associations (sa_id,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) +VALUES (6,1,1,1,12,12,0,20,0,1,5,11); + +-- SA 7 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 +INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +VALUES (7,130,2,1,1,12,12,0,20,0,1,5,11,0,3,1,0); + +-- SA 8 - CLEAR MODE +INSERT INTO security_associations (sa_id,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) +VALUES (1,3,0,0,1,0,1,5,0,3,1,0); diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql index 10d3a746..353884bf 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_user_grant_permissions.sql @@ -1,3 +1,4 @@ -Create User IF NOT EXISTS sadb_user IDENTIFIED BY 'sadb_password'; +DROP USER IF EXISTS 'sadb_user'; +CREATE USER IF NOT EXISTS sadb_user IDENTIFIED BY 'sadb_password'; -GRANT ALL PRIVILEGES ON sadb.* TO 'sadb_user' @ '%'; \ No newline at end of file +GRANT ALL PRIVILEGES ON sadb.* TO 'sadb_user'@'%'; \ No newline at end of file diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/delete_sadb.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/delete_sadb.sql new file mode 100644 index 00000000..4ecde304 --- /dev/null +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/delete_sadb.sql @@ -0,0 +1 @@ +DROP DATABASE IF EXISTS sadb; diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index 45696575..c2952d92 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -53,7 +53,7 @@ typedef struct uint16 ekid; // Encryption Key ID uint16 akid; // Authentication Key ID uint8 sa_state:2; - crypto_gvcid_t gvcid_tc_blk[NUM_GVCID]; + crypto_gvcid_t gvcid_tc_blk; crypto_gvcid_t gvcid_tm_blk[NUM_GVCID]; uint8 lpid; diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 721ab991..4f6545d0 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -121,7 +121,9 @@ int32 Crypto_Init(void) int32 status = OS_SUCCESS; //TODO -- Make the routine that gets called variable based on configuration! - sadb_routine = get_sadb_routine_mariadb(); + sadb_routine = get_sadb_routine_inmemory(); + //sadb_routine = get_sadb_routine_mariadb(); + // Initialize libgcrypt if (!gcry_check_version(GCRYPT_VERSION)) @@ -2167,7 +2169,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } if (status == OS_SUCCESS) { - if (sa_ptr->gvcid_tc_blk[tc_sdls_processed_frame->tc_header.vcid].mapid != TYPE_TC) + if (sa_ptr->gvcid_tc_blk.mapid != TYPE_TC) { OS_printf(KRED "Error: SA invalid type! \n" RESET); status = OS_ERROR; @@ -2176,7 +2178,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro // TODO: I don't think this is needed. //if (status == OS_SUCCESS) //{ - // if (sa_ptr->gvcid_tc_blk[tc_sdls_processed_frame->tc_header.vcid].vcid != tc_sdls_processed_frame->tc_header.vcid) + // if (sa_ptr->gvcid_tc_blk.vcid != tc_sdls_processed_frame->tc_header.vcid) // { // OS_printf(KRED "Error: VCID not mapped to provided SPI! \n" RESET); // status = OS_ERROR; diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c index 7e461222..e7f15d55 100644 --- a/fsw/src/sadb_routine_inmemory.template.c +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -64,20 +64,17 @@ static int32 sadb_config(void) // Security Associations // SA 1 - CLEAR MODE + // SA 1 VC0/1 is now SA 1-VC0, SA 8-VC1 sa[1].sa_state = SA_OPERATIONAL; sa[1].est = 0; sa[1].ast = 0; sa[1].arc_len = 1; sa[1].arcw_len = 1; sa[1].arcw[0] = 5; - sa[1].gvcid_tc_blk[0].tfvn = 0; - sa[1].gvcid_tc_blk[0].scid = SCID & 0x3FF; - sa[1].gvcid_tc_blk[0].vcid = 0; - sa[1].gvcid_tc_blk[0].mapid = TYPE_TC; - sa[1].gvcid_tc_blk[1].tfvn = 0; - sa[1].gvcid_tc_blk[1].scid = SCID & 0x3FF; - sa[1].gvcid_tc_blk[1].vcid = 1; - sa[1].gvcid_tc_blk[1].mapid = TYPE_TC; + sa[1].gvcid_tc_blk.tfvn = 0; + sa[1].gvcid_tc_blk.scid = SCID & 0x3FF; + sa[1].gvcid_tc_blk.vcid = 0; + sa[1].gvcid_tc_blk.mapid = TYPE_TC; // SA 2 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 128 sa[2].ekid = 128; sa[2].sa_state = SA_KEYED; @@ -111,6 +108,7 @@ static int32 sadb_config(void) sa[3].arcw[0] = 5; sa[3].arc_len = (sa[3].arcw[0] * 2) + 1; // SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 + // SA 4 VC0/1 is now 4-VC0, 7-VC1 sa[4].ekid = 130; sa[4].sa_state = SA_KEYED; sa[4].est = 1; @@ -126,14 +124,11 @@ static int32 sadb_config(void) sa[4].arcw_len = 1; sa[4].arcw[0] = 5; sa[4].arc_len = (sa[4].arcw[0] * 2) + 1; - sa[4].gvcid_tc_blk[0].tfvn = 0; - sa[4].gvcid_tc_blk[0].scid = SCID & 0x3FF; - sa[4].gvcid_tc_blk[0].vcid = 0; - sa[4].gvcid_tc_blk[0].mapid = TYPE_TC; - sa[4].gvcid_tc_blk[1].tfvn = 0; - sa[4].gvcid_tc_blk[1].scid = SCID & 0x3FF; - sa[4].gvcid_tc_blk[1].vcid = 1; - sa[4].gvcid_tc_blk[1].mapid = TYPE_TC; + sa[4].gvcid_tc_blk.tfvn = 0; + sa[4].gvcid_tc_blk.scid = SCID & 0x3FF; + sa[4].gvcid_tc_blk.vcid = 0; + sa[4].gvcid_tc_blk.mapid = TYPE_TC; + // SA 5 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 131 sa[5].ekid = 131; sa[5].sa_state = SA_KEYED; @@ -167,7 +162,40 @@ static int32 sadb_config(void) sa[6].arc_len = (sa[6].arcw[0] * 2) + 1; //itc_gcm128_init(&(sa[6].gcm_ctx), (unsigned char *)&(ek_ring[sa[6].ekid])); + // SA 7 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 + sa[7].ekid = 130; + sa[7].sa_state = SA_KEYED; + sa[7].est = 1; + sa[7].ast = 1; + sa[7].shivf_len = 12; + sa[7].iv_len = IV_SIZE; + sa[7].iv[IV_SIZE-1] = 0; + sa[7].abm_len = 0x14; // 20 + for (int i = 0; i < sa[4].abm_len; i++) + { // Zero AAD bit mask + sa[4].abm[i] = 0x00; + } + sa[7].arcw_len = 1; + sa[7].arcw[0] = 5; + sa[7].arc_len = (sa[4].arcw[0] * 2) + 1; + sa[7].gvcid_tc_blk.tfvn = 0; + sa[7].gvcid_tc_blk.scid = SCID & 0x3FF; + sa[7].gvcid_tc_blk.vcid = 1; + sa[7].gvcid_tc_blk.mapid = TYPE_TC; return status; + + // SA 8 - CLEAR MODE + sa[8].sa_state = SA_OPERATIONAL; + sa[8].est = 0; + sa[8].ast = 0; + sa[8].arc_len = 1; + sa[8].arcw_len = 1; + sa[8].arcw[0] = 5; + sa[8].gvcid_tc_blk.tfvn = 0; + sa[8].gvcid_tc_blk.scid = SCID & 0x3FF; + sa[8].gvcid_tc_blk.vcid = 1; + sa[8].gvcid_tc_blk.mapid = TYPE_TC; + } static int32 sadb_init(void) @@ -241,27 +269,25 @@ static int32 sadb_sa_start(TC_t* tc_frame) (sdls_frame.pdu.data[count + 2] >> 4); gvcid.vcid = (sdls_frame.pdu.data[count + 2] << 4) | (sdls_frame.pdu.data[count + 3] && 0x3F); - gvcid.mapid = (sdls_frame.pdu.data[count + 3]); + if(SEGMENTATION_HDR){gvcid.mapid = (sdls_frame.pdu.data[count + 3]);} + else {gvcid.mapid=0;} // TC if (gvcid.vcid != tc_frame->tc_header.vcid) { // Clear all GVCIDs for provided SPI if (gvcid.mapid == TYPE_TC) { - for (int i = 0; i < NUM_GVCID; i++) - { // TC - sa[spi].gvcid_tc_blk[x].tfvn = 0; - sa[spi].gvcid_tc_blk[x].scid = 0; - sa[spi].gvcid_tc_blk[x].vcid = 0; - sa[spi].gvcid_tc_blk[x].mapid = 0; - } + sa[spi].gvcid_tc_blk.tfvn = 0; + sa[spi].gvcid_tc_blk.scid = 0; + sa[spi].gvcid_tc_blk.vcid = 0; + sa[spi].gvcid_tc_blk.mapid = 0; } // Write channel to SA if (gvcid.mapid != TYPE_MAP) { // TC - sa[spi].gvcid_tc_blk[gvcid.vcid].tfvn = gvcid.tfvn; - sa[spi].gvcid_tc_blk[gvcid.vcid].scid = gvcid.scid; - sa[spi].gvcid_tc_blk[gvcid.vcid].mapid = gvcid.mapid; + sa[spi].gvcid_tc_blk.tfvn = gvcid.tfvn; + sa[spi].gvcid_tc_blk.scid = gvcid.scid; + sa[spi].gvcid_tc_blk.mapid = gvcid.mapid; } else { @@ -353,12 +379,12 @@ static int32 sadb_sa_stop(void) if (sa[spi].sa_state == SA_OPERATIONAL) { // Remove all GVC/GMAP IDs + sa[spi].gvcid_tc_blk.tfvn = 0; + sa[spi].gvcid_tc_blk.scid = 0; + sa[spi].gvcid_tc_blk.vcid = 0; + sa[spi].gvcid_tc_blk.mapid = 0; for (int x = 0; x < NUM_GVCID; x++) - { // TC - sa[spi].gvcid_tc_blk[x].tfvn = 0; - sa[spi].gvcid_tc_blk[x].scid = 0; - sa[spi].gvcid_tc_blk[x].vcid = 0; - sa[spi].gvcid_tc_blk[x].mapid = 0; + { // TM sa[spi].gvcid_tm_blk[x].tfvn = 0; sa[spi].gvcid_tm_blk[x].scid = 0; From 3fe6c7e4974825b5f6ab16942d7e0203ce235fe6 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Wed, 3 Nov 2021 21:35:51 -0400 Subject: [PATCH 020/184] WIP on authentication bug - tracking down GPG_ERR_INV_STATE cause. Version? --- fsw/src/crypto.c | 313 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 297 insertions(+), 16 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 81b30a9a..c2ddf63a 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -566,7 +566,8 @@ static int32 Crypto_SA_config(void) // Security Associations // SA 1 - CLEAR MODE - sa[1].sa_state = SA_OPERATIONAL; + // sa[1].sa_state = SA_OPERATIONAL; + sa[1].sa_state = SA_NONE; sa[1].est = 0; sa[1].ast = 0; sa[1].shplf_len = 2; @@ -600,6 +601,7 @@ static int32 Crypto_SA_config(void) // SA 3 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 129 sa[3].ekid = 129; sa[3].sa_state = SA_KEYED; + // sa[3].sa_state = SA_OPERATIONAL; sa[3].est = 1; sa[3].ast = 1; sa[3].shivf_len = 12; @@ -615,10 +617,12 @@ static int32 Crypto_SA_config(void) sa[3].arc_len = (sa[3].arcw[0] * 2) + 1; // SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 sa[4].ekid = 130; - sa[4].sa_state = SA_KEYED; + // sa[4].sa_state = SA_KEYED; + sa[4].sa_state = SA_OPERATIONAL; sa[4].est = 1; sa[4].ast = 1; sa[4].shivf_len = 12; + sa[4].stmacf_len = 16; sa[4].iv_len = IV_SIZE; sa[4].iv[IV_SIZE-1] = 0; sa[4].abm_len = 0x14; // 20 @@ -628,7 +632,7 @@ static int32 Crypto_SA_config(void) } sa[4].arcw_len = 1; sa[4].arcw[0] = 5; - sa[4].arc_len = (sa[4].arcw[0] * 2) + 1; + //sa[4].arc_len = (sa[4].arcw[0] * 2) + 1; // TEST sa[4].gvcid_tc_blk[0].tfvn = 0; sa[4].gvcid_tc_blk[0].scid = SCID & 0x3FF; sa[4].gvcid_tc_blk[0].vcid = 0; @@ -958,6 +962,7 @@ static void Crypto_TM_updateOCF(void) } } +//TODO - Review this. Not sure it quite works how we think static int32 Crypto_increment(uint8 *num, int length) { int i; @@ -1129,7 +1134,7 @@ static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest) OS_printf(KCYN "0x" RESET); for (int x = 0; x < len_ingest; x++) { - OS_printf(KCYN "%02x" RESET, ingest[x]); + OS_printf(KCYN "%02x" RESET, (uint8)*(ingest+x)); } OS_printf(KCYN "\n" RESET); OS_printf(KCYN "In Crypto_Calc_FECF! fecf = 0x%04x\n" RESET, fecf); @@ -2640,7 +2645,7 @@ static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) OS_printf(KMAG "CCSDS message put on software bus: 0x" RESET); for (int x = 0; x < status; x++) { - OS_printf(KMAG "%02x" RESET, x, (uint8) ingest[x]); + OS_printf(KMAG "%02x" RESET, (uint8) ingest[x]); } OS_printf("\n"); } @@ -2653,6 +2658,15 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt { // Local Variables int32 status = OS_SUCCESS; + TC_FramePrimaryHeader_t temp_tc_header; + SecurityAssociation_t temp_SA; + int16_t spi = -1; + uint16 mac_loc = 0; + uint16 tf_payload_len = 0x0000; + uint16 new_fecf = 0x0000; + uint8 aad[20]; + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; #ifdef DEBUG OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); @@ -2668,8 +2682,6 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt OS_printf("\nPrinted %d bytes\n", in_frame_length); #endif - - TC_FramePrimaryHeader_t temp_tc_header; // Primary Header temp_tc_header.tfvn = ((uint8)in_frame[0] & 0xC0) >> 6; temp_tc_header.bypass = ((uint8)in_frame[0] & 0x20) >> 5; @@ -2705,8 +2717,6 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt // TODO: Likely API call // TODO: Magic to make sure we're getting the correct SA.. // currently SA DB allows for more than one - SecurityAssociation_t temp_SA; - int16_t spi = -1; for (int i=0; i < NUM_SA;i++) { if (sa[i].sa_state == SA_OPERATIONAL) @@ -2792,7 +2802,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt #endif // Accio buffer - uint8 *enc_frame = (const uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); + uint8 *enc_frame = (uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); // Copy original TF header @@ -2849,11 +2859,20 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt // Copy in original TF data CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), (in_frame_length-TC_FRAME_PRIMARYHEADER_SIZE)); - // for (int i=TC_FRAME_PRIMARYHEADER_SIZE; i < in_frame_length; i++) - // { - // *(enc_frame + index) = *(in_frame + i); - // index++; - // } + index += in_frame_length-TC_FRAME_PRIMARYHEADER_SIZE; + + // MAC may be present and unused in plaintext SA + // Reference CCSDS 3550b1 4.1.2.3 + // TODO: Likely API call + for (int i=0; i < temp_SA.stmacf_len; i++) + { + // Temp fill Pad + // TODO: What should pad be, set per channel/SA potentially? + *(enc_frame + index) = 0x00; + index++; + } + + // TODO: Calc FECF if exists for channel #ifdef TC_DEBUG OS_printf(KYEL "Printing new TC Frame:\n\t"); @@ -2891,7 +2910,269 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt #ifdef DEBUG OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION! \n" RESET); #endif - // TODO + + // Total length of buffer to be malloced + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len _ arc_len + pad_size + stmacf_len + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len; + + #ifdef TC_DEBUG + OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *enc_frame_len); + OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); + OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); + OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); + OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, temp_SA.shivf_len); + OS_printf(KYEL "\tshsnf_len\t = %d\n" RESET, temp_SA.shsnf_len); + OS_printf(KYEL "\tshplf len\t = %d\n" RESET, temp_SA.shplf_len); + OS_printf(KYEL "\tarc_len\t\t = %d\n" RESET, temp_SA.arc_len); + OS_printf(KYEL "\tpad_size\t = %d\n" RESET, TC_PAD_SIZE); + OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, temp_SA.stmacf_len); + #endif + + // Accio buffer + uint8 *enc_frame = (uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); + CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); + + // Copy original TF header + CFE_PSP_MemCpy(enc_frame, in_frame, TC_FRAME_PRIMARYHEADER_SIZE); + // Set new TF Header length + // Recall: Length field is one minus total length per spec + *(enc_frame+2) = ((*(enc_frame+2) & 0xFC) | (((*enc_frame_len - 1) & (0x0300)) >> 8)); + *(enc_frame+3) = ((*enc_frame_len - 1) & (0x00FF)); + + #ifdef TC_DEBUG + OS_printf(KYEL "Printing updated TF Header:\n\t"); + for (int i=0; i> 8); + *(enc_frame + index + 1) = (spi & 0x00FF); + index += 2; + + // Set initialization value + #ifdef SA_DEBUG + OS_printf("Old IV value was:\n\t"); + for(int i=0; i SA or TC channel setup + //for (int i=0; i < TC_PAD_SIZE; i++) + for (int i=0; i < temp_SA.shplf_len; i++) + { + // Temp fill Pad + // TODO: What should pad be, set per channel/SA potentially? + *(enc_frame + index) = 0x88; + index++; + } + + // Copy in original TF data - except FECF + // TODO: Need to know presence / absence of FECF + //if FECF + tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - FECF_SIZE; + //if no FECF + //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; + + CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); + index += tf_payload_len; + + // Set MAC Field + for (int i=0; i < temp_SA.stmacf_len; i++) + { + // Temp fill MAC + *(enc_frame + index) = 0x99; + index++; + } + + // Set FECF Field + // TODO: Determine is FECF is even present + // on this particular channel + // TODO: Determine if needs recalculated + // TODO: Needs recalculated due to change in length bytes + // for (int i=0; i < FECF_SIZE; i++) + // { + // // Copy over old FECF + // *(enc_frame + index) = in_frame[in_frame_length - (FECF_SIZE - i)]; + // index++; + // } + // Calc new fecf, don't include old fecf in length + // Need a cleaner way of doing this: + // uint * temp_old_frame = malloc() + #ifdef FECF_DEBUG + OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + sa[spi].shivf_len + sa[spi].shsnf_len + sa[spi].shsnf_len + tf_payload_len); + #endif + new_fecf = Crypto_Calc_FECF(enc_frame, TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + sa[spi].shivf_len + sa[spi].shsnf_len + sa[spi].shsnf_len + tf_payload_len); + *(enc_frame + index) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(enc_frame + index + 1) = (uint8) (new_fecf & 0x00FF); + index += 2; + + //TODO AAD / ABM? + #ifdef MAC_DEBUG + OS_printf("Preparing AAD:\n"); + OS_printf("\tUsing ABM Length of %d\n\t", sa[spi].abm_len); + #endif + // Prepare additional authenticated data + for (int y = 0; y < sa[spi].abm_len; y++) + { + aad[y] = in_frame[y] & sa[spi].abm[y]; + #ifdef MAC_DEBUG + OS_printf("%02x", aad[y]); + #endif + } + #ifdef MAC_DEBUG + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[sa[spi].ekid].value[0]), + KEY_SIZE //TODO: look into this + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(sa[spi].iv[0]), + sa[spi].iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + uint16 output_loc = TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; + OS_printf("Encrypted bytes output_loc is %d\n", output_loc); + OS_printf("tf_payload_len is %d\n", tf_payload_len); + #ifdef TC_DEBUG + OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); + for(int i=0; i < output_loc; i++) + { + OS_printf("%02X", *(enc_frame + i)); + } + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_encrypt( + tmp_hd, + &enc_frame[output_loc],// ciphertext output + tf_payload_len, // length of data + (in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now + tf_payload_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + gcry_error = gcry_cipher_authenticate( + tmp_hd, + &(aad[0]), // additional authenticated data + 1 //sa[spi].abm_len // length of AAD + ); + + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + status = OS_ERROR; + return status; + } + + // TODO - Know if FECF exists + // TODO - Could start working in if/else here wrt ast/est flags + mac_loc = *enc_frame_len - sa[spi].stmacf_len - FECF_SIZE; + #ifdef DEBUG + OS_printf("MAC location is: %d\n", mac_loc); + OS_printf("MAC size is: %d\n", MAC_SIZE); + #endif + gcry_error = gcry_cipher_gettag( + tmp_hd, + &enc_frame[mac_loc], // tag output + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + #ifdef TC_DEBUG + OS_printf(KYEL "Printing new TC Frame:\n\t"); + for(int i=0; i < *enc_frame_len; i++) + { + OS_printf("%02x", *(enc_frame + i)); + } + OS_printf("\n\tThe returned length is: %d\n" RESET, *enc_frame_len); + #endif + + + *enc_frame_test = enc_frame; } } From d5da11c56bab10e9c82169a0946a3b808c962c24 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Wed, 3 Nov 2021 23:04:36 -0400 Subject: [PATCH 021/184] Fix function call in crypto_seq --- fsw/crypto_util/app/crypto_sequence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/crypto_util/app/crypto_sequence.c b/fsw/crypto_util/app/crypto_sequence.c index fbf35cd3..b300aa11 100644 --- a/fsw/crypto_util/app/crypto_sequence.c +++ b/fsw/crypto_util/app/crypto_sequence.c @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) { //Call Apply/ProcessSecurity on buffer contents depending on type. if (strcmp(security_type,"tc_a")==0){ - Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, enc_frame_len);} + Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len);} else if (strcmp(security_type,"tm_a")==0){ Crypto_TM_ApplySecurity(buffer, &buffer_size_i); } else if (strcmp(security_type,"aos_a")==0){ From 576514ee35005bfe9a9f5a3a81789404e96d5f22 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 3 Nov 2021 20:13:44 -0700 Subject: [PATCH 022/184] AKMC-113: Implement MySQL sadb_get_sa_from_spi function --- ...e_sadb_unit_test_security_associations.sql | 2 +- fsw/public_inc/sadb_mariadb_error.h | 2 + fsw/src/crypto.c | 4 +- fsw/src_mysql/sadb_routine_mariadb.template.c | 88 ++++++++++++++++++- 4 files changed, 91 insertions(+), 5 deletions(-) diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql index 61d106c3..b87fe125 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql @@ -30,4 +30,4 @@ VALUES (7,130,2,1,1,12,12,0,20,0,1,5,11,0,3,1,0); -- SA 8 - CLEAR MODE INSERT INTO security_associations (sa_id,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) -VALUES (1,3,0,0,1,0,1,5,0,3,1,0); +VALUES (8,3,0,0,1,0,1,5,0,3,1,0); diff --git a/fsw/public_inc/sadb_mariadb_error.h b/fsw/public_inc/sadb_mariadb_error.h index f57374af..2badf05e 100644 --- a/fsw/public_inc/sadb_mariadb_error.h +++ b/fsw/public_inc/sadb_mariadb_error.h @@ -6,5 +6,7 @@ #define _sadb_mariadb_error_h_ #define SADB_MARIADB_CONNECTION_FAILED 300 +#define SADB_QUERY_BY_SPI_FAILED 301 +#define SADB_QUERY_BY_SPI_EMPTY_RESULTS 302 #endif //_sadb_mariadb_error_h_ diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 4f6545d0..31a37a98 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -121,8 +121,8 @@ int32 Crypto_Init(void) int32 status = OS_SUCCESS; //TODO -- Make the routine that gets called variable based on configuration! - sadb_routine = get_sadb_routine_inmemory(); - //sadb_routine = get_sadb_routine_mariadb(); + //sadb_routine = get_sadb_routine_inmemory(); + sadb_routine = get_sadb_routine_mariadb(); // Initialize libgcrypt diff --git a/fsw/src_mysql/sadb_routine_mariadb.template.c b/fsw/src_mysql/sadb_routine_mariadb.template.c index 1cf6d52c..9b5277b7 100644 --- a/fsw/src_mysql/sadb_routine_mariadb.template.c +++ b/fsw/src_mysql/sadb_routine_mariadb.template.c @@ -18,6 +18,9 @@ #include "crypto_error.h" #include +#include +#include +#include // Security Association Initialization Functions static int32 sadb_config(void); @@ -36,6 +39,9 @@ static int32 sadb_sa_setARSNW(void); static int32 sadb_sa_delete(void); //MySQL local functions static int32 finish_with_error(MYSQL *con,int err); +//MySQL Queries +const static char* SQL_SADB_GET_SA_BY_SPI = "SELECT * FROM security_associations WHERE sa_id='%d'"; + /* ** Global Variables @@ -81,10 +87,88 @@ static int32 sadb_init(void) return status; } -static int32 sadb_close(void){return OS_SUCCESS;}; +static int32 sadb_close(void) +{ + mysql_close(con); + return OS_SUCCESS; +} // Security Association Interaction Functions -static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_association){return OS_SUCCESS;} +static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_association) +{ + int32 status = OS_SUCCESS; + + SecurityAssociation_t* sa = malloc(sizeof(SecurityAssociation_t)); + + char spi_query[2048]; + snprintf(spi_query, sizeof(spi_query),SQL_SADB_GET_SA_BY_SPI,spi); + if(mysql_query(con,spi_query)) { status = finish_with_error(con,SADB_QUERY_BY_SPI_FAILED); } + + MYSQL_RES *result = mysql_store_result(con); + if(result == NULL) { status = finish_with_error(con,SADB_QUERY_BY_SPI_EMPTY_RESULTS); } + + int num_fields = mysql_num_fields(result); + + MYSQL_ROW row; + MYSQL_FIELD *field; + + char *field_names[num_fields]; //[64]; 64 == max length of column name in MySQL + + + while((row = mysql_fetch_row(result))){ + for(int i=0; i < num_fields; i++) + { + //Parse out all the field names. + if(i == 0){ + int field_idx = 0; + while(field = mysql_fetch_field(result)){ + field_names[field_idx] = field->name; + field_idx++; + } + } + //Handle query results + int sa_id; + uint8 tmp_uint8; + if(row[i]==NULL){continue;} //Don't do anything with NULL fields from MySQL query. + if(strcmp(field_names[i],"sa_id")==0){sa_id = atoi(row[i]);continue;} + if(strcmp(field_names[i],"ekid")==0){sa->ekid=atoi(row[i]);continue;} + if(strcmp(field_names[i],"akid")==0){sa->akid=atoi(row[i]);continue;} + if(strcmp(field_names[i],"sa_state")==0){sa->sa_state=atoi(row[i]);continue;} + if(strcmp(field_names[i],"tfvn")==0){sa->gvcid_tc_blk.tfvn=atoi(row[i]);continue;} + if(strcmp(field_names[i],"scid")==0){sa->gvcid_tc_blk.scid=atoi(row[i]);continue;} + if(strcmp(field_names[i],"vcid")==0){sa->gvcid_tc_blk.vcid=atoi(row[i]);continue;} + if(strcmp(field_names[i],"mapid")==0){sa->gvcid_tc_blk.mapid=atoi(row[i]);continue;} + if(strcmp(field_names[i],"lpid")==0){sa->lpid=atoi(row[i]);continue;} + if(strcmp(field_names[i],"est")==0){sa->est=atoi(row[i]);continue;} + if(strcmp(field_names[i],"ast")==0){sa->ast=atoi(row[i]);continue;} + if(strcmp(field_names[i],"shivf_len")==0){sa->shivf_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"shsnf_len")==0){sa->shsnf_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"shplf_len")==0){sa->shplf_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"stmacf_len")==0){sa->stmacf_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"ecs_len")==0){sa->ecs_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"ecs")==0){tmp_uint8 = (uint8)atoi(row[i]); memcpy(&(sa->ecs),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"iv_len")==0){sa->iv_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"iv")==0){tmp_uint8 =(uint8) atoi(row[i]); memcpy(&(sa->iv),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"acs_len")==0){sa->acs_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"acs")==0){sa->acs=atoi(row[i]);continue;} + if(strcmp(field_names[i],"abm_len")==0){sa->abm_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"abm")==0){tmp_uint8 = (uint8)atoi(row[i]);memcpy(&(sa->abm),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"arc_len")==0){sa->arc_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"arc")==0){tmp_uint8 = (uint8)atoi(row[i]);memcpy(&(sa->arc),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"arcw_len")==0){sa->arcw_len=atoi(row[i]);continue;} + if(strcmp(field_names[i],"arcw")==0){tmp_uint8 = (uint8)atoi(row[i]);memcpy(&(sa->arcw),&tmp_uint8,sizeof(tmp_uint8));continue;} + //printf("%s:%s ",field_names[i], row[i] ? row[i] : "NULL"); + } + printf("\n"); + } + + *security_association = sa; + mysql_free_result(result); + //set all the SA fields from the query results. + //*security_association.vcid = + + return status; +} // Security Association Utility Functions static int32 sadb_sa_start(TC_t* tc_frame){return OS_SUCCESS;} static int32 sadb_sa_expire(void){return OS_SUCCESS;} From e9423c74112cc2b332b03da1f2efd36b65493aa3 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 3 Nov 2021 20:16:01 -0700 Subject: [PATCH 023/184] AKMC-113: Change default instantiation back to inmemory instead of mysql --- fsw/src/crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 31a37a98..4f6545d0 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -121,8 +121,8 @@ int32 Crypto_Init(void) int32 status = OS_SUCCESS; //TODO -- Make the routine that gets called variable based on configuration! - //sadb_routine = get_sadb_routine_inmemory(); - sadb_routine = get_sadb_routine_mariadb(); + sadb_routine = get_sadb_routine_inmemory(); + //sadb_routine = get_sadb_routine_mariadb(); // Initialize libgcrypt From 3b91d843b7ab7314bf55b464674387e531c02a07 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Thu, 4 Nov 2021 14:23:47 -0400 Subject: [PATCH 024/184] Minor cleanup --- fsw/src/crypto.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index c2ddf63a..7bdd1b1a 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -3032,17 +3032,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt // Set FECF Field // TODO: Determine is FECF is even present // on this particular channel - // TODO: Determine if needs recalculated - // TODO: Needs recalculated due to change in length bytes - // for (int i=0; i < FECF_SIZE; i++) - // { - // // Copy over old FECF - // *(enc_frame + index) = in_frame[in_frame_length - (FECF_SIZE - i)]; - // index++; - // } // Calc new fecf, don't include old fecf in length - // Need a cleaner way of doing this: - // uint * temp_old_frame = malloc() #ifdef FECF_DEBUG OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + sa[spi].shivf_len + sa[spi].shsnf_len + sa[spi].shsnf_len + tf_payload_len); #endif @@ -3051,20 +3041,19 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt *(enc_frame + index + 1) = (uint8) (new_fecf & 0x00FF); index += 2; - //TODO AAD / ABM? - #ifdef MAC_DEBUG - OS_printf("Preparing AAD:\n"); - OS_printf("\tUsing ABM Length of %d\n\t", sa[spi].abm_len); - #endif // Prepare additional authenticated data for (int y = 0; y < sa[spi].abm_len; y++) { aad[y] = in_frame[y] & sa[spi].abm[y]; - #ifdef MAC_DEBUG - OS_printf("%02x", aad[y]); - #endif } + //TODO AAD / ABM? #ifdef MAC_DEBUG + OS_printf("Preparing AAD:\n"); + OS_printf("\tUsing ABM Length of %d\n\t", sa[spi].abm_len); + for (int y = 0; y < sa[spi].abm_len; y++) + { + OS_printf("%02x", aad[y]); + } OS_printf("\n"); #endif @@ -3132,7 +3121,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt gcry_error = gcry_cipher_authenticate( tmp_hd, &(aad[0]), // additional authenticated data - 1 //sa[spi].abm_len // length of AAD + sa[spi].abm_len // length of AAD ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -3153,7 +3142,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt gcry_error = gcry_cipher_gettag( tmp_hd, &enc_frame[mac_loc], // tag output - MAC_SIZE // tag size + MAC_SIZE // tag size ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { From b79b9acf316408f41441a0d8cb66fed254adbf8e Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Thu, 4 Nov 2021 23:26:18 -0400 Subject: [PATCH 025/184] WIP - working Authenticated Encryption - checkpoint before refactor TC_ApplySec --- fsw/src/crypto.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 7bdd1b1a..919a6914 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -707,7 +707,7 @@ int32 Crypto_Init(void) if (!gcry_check_version(GCRYPT_VERSION)) { fprintf(stderr, "Gcrypt Version: %s",GCRYPT_VERSION); - OS_printf(KRED "ERROR: gcrypt version mismatch! \n" RESET); + OS_printf(KRED "\tERROR: gcrypt version mismatch! \n" RESET); } if (gcry_control(GCRYCTL_SELFTEST) != GPG_ERR_NO_ERROR) { @@ -3097,37 +3097,36 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt OS_printf("tf_payload_len is %d\n", tf_payload_len); #ifdef TC_DEBUG OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); - for(int i=0; i < output_loc; i++) + for(int i=0; i < *enc_frame_len; i++) { OS_printf("%02X", *(enc_frame + i)); } OS_printf("\n"); #endif - gcry_error = gcry_cipher_encrypt( + gcry_error = gcry_cipher_authenticate( tmp_hd, - &enc_frame[output_loc],// ciphertext output - tf_payload_len, // length of data - (in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now - tf_payload_len // in data length + &(aad[0]), // additional authenticated data + sa[spi].abm_len // length of AAD ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { - OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); status = OS_ERROR; return status; } - gcry_error = gcry_cipher_authenticate( + gcry_error = gcry_cipher_encrypt( tmp_hd, - &(aad[0]), // additional authenticated data - sa[spi].abm_len // length of AAD + &enc_frame[output_loc],// ciphertext output + tf_payload_len, // length of data + (in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now + tf_payload_len // in data length ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { - OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); status = OS_ERROR; return status; } @@ -3160,7 +3159,6 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt OS_printf("\n\tThe returned length is: %d\n" RESET, *enc_frame_len); #endif - *enc_frame_test = enc_frame; } } From 55879d5bff8ad82c2f9dc50d09b47594a35b5e33 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Thu, 4 Nov 2021 23:43:58 -0400 Subject: [PATCH 026/184] Define SA Service Types --- fsw/public_inc/crypto_config.h | 6 ++++++ fsw/src/crypto.c | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index caf8e124..d9964098 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -91,6 +91,12 @@ ivv-itc@lists.nasa.gov #define KEY_DESTROYED 3 #define KEY_CORRUPTED 4 +// SA Service Types + #define SA_PLAINTEXT 0 + #define SA_AUTHENTICATION 1 + #define SA_ENCRYPTION 2 + #define SA_AUTHENTICATED_ENCRYPTION 3 + // Generic Defines #define NUM_SA 64 #define KEY_SIZE 32 diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 919a6914..1340509b 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2661,6 +2661,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt TC_FramePrimaryHeader_t temp_tc_header; SecurityAssociation_t temp_SA; int16_t spi = -1; + uint8 sa_service_type = -1; uint16 mac_loc = 0; uint16 tf_payload_len = 0x0000; uint16 new_fecf = 0x0000; @@ -2780,6 +2781,32 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt return status; } + // Determine SA Service Type + if ((temp_SA.est == 0) && (temp_SA.ast == 0)) + { + sa_service_type = SA_PLAINTEXT; + } + else if ((temp_SA.est == 0) && (temp_SA.ast == 1)) + { + sa_service_type = SA_AUTHENTICATION; + } + else if ((temp_SA.est == 1) && (temp_SA.ast == 0)) + { + sa_service_type = SA_ENCRYPTION; + } + else if ((temp_SA.est == 1) && (temp_SA.ast == 1)) + { + sa_service_type = SA_AUTHENTICATED_ENCRYPTION; + } + else + { + // Probably unnecessary check + // Leaving for now as it would be cleaner in SA to have an association enum returned I believe + OS_printf(KRED "Error: SA Service Type is not defined! \n" RESET); + status = OS_ERROR; + return status; + } + // Determine mode // Clear if ((temp_SA.est == 0) && (temp_SA.ast == 0)) From 6711c4a849e963f1eeacdb7c5ef225db0ccb28b1 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Thu, 4 Nov 2021 23:51:26 -0400 Subject: [PATCH 027/184] Rearrange debugs.. commit early and often ;) --- fsw/src/crypto.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 1340509b..00cb4b0d 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2807,14 +2807,24 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt return status; } + #ifdef TC_DEBUG + switch(sa_service_type) + { + case SA_PLAINTEXT: + OS_printf(KBLU "Creating a TC - CLEAR!\n" RESET); + case SA_AUTHENTICATION: + OS_printf(KBLU "Creating a TC - AUTHENTICATED!\n" RESET); + case SA_ENCRYPTION: + OS_printf(KBLU "Creating a TC - ENCRYPTED!\n" RESET); + case SA_AUTHENTICATED_ENCRYPTION: + OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION!\n" RESET); + } + #endif + // Determine mode // Clear if ((temp_SA.est == 0) && (temp_SA.ast == 0)) { - #ifdef DEBUG - OS_printf(KBLU "Creating a TC - CLEAR! \n" RESET); - #endif - // Total length of buffer to be malloced // Ingest length + segment header (1) + spi_index (2) + some variable length fields // TODO @@ -2916,28 +2926,18 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt // Authentication else if ((temp_SA.est == 0) && (temp_SA.ast == 1)) { - #ifdef DEBUG - OS_printf(KBLU "Creating a TC - AUTHENTICATED! \n" RESET); - #endif // TODO } // Encryption else if ((temp_SA.est == 1) && (temp_SA.ast == 0)) { - #ifdef DEBUG - OS_printf(KBLU "Creating a TC - ENCRYPTED! \n" RESET); - #endif // TODO } // Authenticated Encryption else if((temp_SA.est == 1) && (temp_SA.ast == 1)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION! \n" RESET); - #endif - + { // Total length of buffer to be malloced // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len _ arc_len + pad_size + stmacf_len From 86269ad9c034acb9ec3f668beea33b09556c859b Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 00:09:03 -0400 Subject: [PATCH 028/184] WIP - Output buf malloc and debug statements --- fsw/src/crypto.c | 70 ++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 00cb4b0d..2e7e7861 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2821,23 +2821,48 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt } #endif + // Determine length of buffer to be malloced + // TODO: Determine presence of FECF & TC_PAD_SIZE + // TODO: Note: Currently assumes ciphertext output length is same as ciphertext input length + switch(sa_service_type) + { + case SA_PLAINTEXT: + // Ingest length + segment header (1) + spi_index (2) + some variable length fields + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shplf_len; + case SA_AUTHENTICATION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + stmacf_len + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len;; + case SA_ENCRYPTION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE; + case SA_AUTHENTICATED_ENCRYPTION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + stmacf_len + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len; + } + + #ifdef TC_DEBUG + OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *enc_frame_len); + OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); + OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded + OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); + OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, temp_SA.shivf_len); + OS_printf(KYEL "\tshsnf_len\t = %d\n" RESET, temp_SA.shsnf_len); + OS_printf(KYEL "\tshplf len\t = %d\n" RESET, temp_SA.shplf_len); + OS_printf(KYEL "\tarc_len\t\t = %d\n" RESET, temp_SA.arc_len); + OS_printf(KYEL "\tpad_size\t = %d\n" RESET, TC_PAD_SIZE); + OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, temp_SA.stmacf_len); + #endif + // Determine mode // Clear if ((temp_SA.est == 0) && (temp_SA.ast == 0)) { - // Total length of buffer to be malloced - // Ingest length + segment header (1) + spi_index (2) + some variable length fields - // TODO - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shplf_len; - - #ifdef TC_DEBUG - OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *enc_frame_len); - OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); - OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); - OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); - OS_printf(KYEL "\tsh pad len\t = %d\n" RESET, temp_SA.shplf_len); - #endif - // Accio buffer uint8 *enc_frame = (uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); @@ -2938,25 +2963,6 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt // Authenticated Encryption else if((temp_SA.est == 1) && (temp_SA.ast == 1)) { - // Total length of buffer to be malloced - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len _ arc_len + pad_size + stmacf_len - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ - temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len; - - #ifdef TC_DEBUG - OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *enc_frame_len); - OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); - OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); - OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); - OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, temp_SA.shivf_len); - OS_printf(KYEL "\tshsnf_len\t = %d\n" RESET, temp_SA.shsnf_len); - OS_printf(KYEL "\tshplf len\t = %d\n" RESET, temp_SA.shplf_len); - OS_printf(KYEL "\tarc_len\t\t = %d\n" RESET, temp_SA.arc_len); - OS_printf(KYEL "\tpad_size\t = %d\n" RESET, TC_PAD_SIZE); - OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, temp_SA.stmacf_len); - #endif - // Accio buffer uint8 *enc_frame = (uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); From 3b774287c6321cc7d72f570032ce18a9839df9dc Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 01:18:29 -0400 Subject: [PATCH 029/184] Malloc enc_frame buffer and check return code --- fsw/src/crypto.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 2e7e7861..befcbf1c 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2859,14 +2859,20 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, temp_SA.stmacf_len); #endif + // Accio buffer + uint8 *enc_frame = (uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); + if(!enc_frame) + { + OS_printf(KRED "Error: Malloc for encrypted output buffer failed! \n" RESET); + status = OS_ERROR; + return status; + } + CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); + // Determine mode // Clear if ((temp_SA.est == 0) && (temp_SA.ast == 0)) { - // Accio buffer - uint8 *enc_frame = (uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); - CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); - // Copy original TF header CFE_PSP_MemCpy(enc_frame, in_frame, TC_FRAME_PRIMARYHEADER_SIZE); // Set new TF Header length @@ -2963,10 +2969,6 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt // Authenticated Encryption else if((temp_SA.est == 1) && (temp_SA.ast == 1)) { - // Accio buffer - uint8 *enc_frame = (uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); - CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); - // Copy original TF header CFE_PSP_MemCpy(enc_frame, in_frame, TC_FRAME_PRIMARYHEADER_SIZE); // Set new TF Header length From 16b795d7e37687ed8b675cd40d7ec82e0ecbd7ce Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 02:27:18 -0400 Subject: [PATCH 030/184] Rework SPI headers --- fsw/src/crypto.c | 252 ++++++++++++++++++++++------------------------- 1 file changed, 120 insertions(+), 132 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index befcbf1c..5e3c9850 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2825,26 +2825,26 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt // TODO: Determine presence of FECF & TC_PAD_SIZE // TODO: Note: Currently assumes ciphertext output length is same as ciphertext input length switch(sa_service_type) - { - case SA_PLAINTEXT: - // Ingest length + segment header (1) + spi_index (2) + some variable length fields - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shplf_len; - case SA_AUTHENTICATION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size + stmacf_len - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ - temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len;; - case SA_ENCRYPTION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ - temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE; - case SA_AUTHENTICATED_ENCRYPTION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size + stmacf_len - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ - temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len; - } + { + case SA_PLAINTEXT: + // Ingest length + segment header (1) + spi_index (2) + some variable length fields + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shplf_len; + case SA_AUTHENTICATION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + stmacf_len + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len;; + case SA_ENCRYPTION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE; + case SA_AUTHENTICATED_ENCRYPTION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + stmacf_len + *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len; + } #ifdef TC_DEBUG OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *enc_frame_len); @@ -2869,62 +2869,114 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt } CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); - // Determine mode - // Clear - if ((temp_SA.est == 0) && (temp_SA.ast == 0)) - { - // Copy original TF header - CFE_PSP_MemCpy(enc_frame, in_frame, TC_FRAME_PRIMARYHEADER_SIZE); - // Set new TF Header length - // Recall: Length field is one minus total length per spec - *(enc_frame+2) = ((*(enc_frame+2) & 0xFC) | (((*enc_frame_len - 1) & (0x0300)) >> 8)); - *(enc_frame+3) = ((*enc_frame_len - 1) & (0x00FF)); + // Copy original TF header + CFE_PSP_MemCpy(enc_frame, in_frame, TC_FRAME_PRIMARYHEADER_SIZE); - #ifdef TC_DEBUG - OS_printf(KYEL "Printing updated TF Header:\n\t"); - for (int i=0; i> 8)); + *(enc_frame+3) = ((*enc_frame_len - 1) & (0x00FF)); - uint16_t index = TC_FRAME_PRIMARYHEADER_SIZE; - // Set Secondary Header flags - *(enc_frame + index) = 0xFF; - index++; + #ifdef TC_DEBUG + OS_printf(KYEL "Printing updated TF Header:\n\t"); + for (int i=0; i> 8); - *(enc_frame + index + 1) = (spi & 0x00FF); - index += 2; + /* + ** Start variable length fields + */ + uint16_t index = TC_FRAME_PRIMARYHEADER_SIZE; + + // Set Segment Header flags + // TODO: Determine segment header exists + *(enc_frame + index) = 0xFF; + index++; - // Set anti-replay sequence number value - /* - ** 4.1.1.4.4 If authentication or authenticated encryption is not selected - ** for an SA, the Sequence Number field shall be zero octets in length. - */ + /* + ** Begin Security Header Fields + ** Reference CCSDS SDLP 3550b1 4.1.1.1.3 + */ + // Set SPI + *(enc_frame + index) = ((spi & 0xFF00) >> 8); + *(enc_frame + index + 1) = (spi & 0x00FF); + index += 2; + + // Set initialization vector if specified + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + #ifdef SA_DEBUG + OS_printf(KYEL "Old IV value was:\n\t"); + for(int i=0; i 0) + { + // If using anti-replay counter, increment it + // TODO: API call instead? + // TODO: Check return code + Crypto_increment(sa[spi].arc, sa[spi].shsnf_len); + for (int i=0; i < temp_SA.shsnf_len; i++) { - // Temp fill Pad - // TODO: What should pad be, set per channel/SA potentially? - *(enc_frame + index) = 0x00; + *(enc_frame + index) = sa[spi].arc[i]; index++; } + } + + // Set security header padding if specified + /* + ** 4.2.3.4 h) if the algorithm and mode selected for the SA require the use of + ** fill padding, place the number of fill bytes used into the Pad Length field + ** of the Security Header - Reference CCSDS 3550b1 + */ + // TODO: Revisit this + // TODO: Likely SA API Call + for (int i=0; i < temp_SA.shplf_len; i++) + { + /* 4.1.1.5.2 The Pad Length field shall contain the count of fill bytes used in the + ** cryptographic process, consisting of an integral number of octets. - CCSDS 3550b1 + */ + // TODO: Set this depending on crypto cipher used + *(enc_frame + index) = 0x00; + index++; + } + // Determine mode + // Clear + if ((temp_SA.est == 0) && (temp_SA.ast == 0)) + { // Copy in original TF data CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), (in_frame_length-TC_FRAME_PRIMARYHEADER_SIZE)); index += in_frame_length-TC_FRAME_PRIMARYHEADER_SIZE; @@ -2968,71 +3020,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt // Authenticated Encryption else if((temp_SA.est == 1) && (temp_SA.ast == 1)) - { - // Copy original TF header - CFE_PSP_MemCpy(enc_frame, in_frame, TC_FRAME_PRIMARYHEADER_SIZE); - // Set new TF Header length - // Recall: Length field is one minus total length per spec - *(enc_frame+2) = ((*(enc_frame+2) & 0xFC) | (((*enc_frame_len - 1) & (0x0300)) >> 8)); - *(enc_frame+3) = ((*enc_frame_len - 1) & (0x00FF)); - - #ifdef TC_DEBUG - OS_printf(KYEL "Printing updated TF Header:\n\t"); - for (int i=0; i> 8); - *(enc_frame + index + 1) = (spi & 0x00FF); - index += 2; - - // Set initialization value - #ifdef SA_DEBUG - OS_printf("Old IV value was:\n\t"); - for(int i=0; i Date: Fri, 5 Nov 2021 02:58:45 -0400 Subject: [PATCH 031/184] WIP - Copy in payload and mac --- fsw/src/crypto.c | 75 ++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 44 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 5e3c9850..90eb7b16 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2973,24 +2973,41 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt index++; } + /* + ** End Security Header Fields + */ + + // Copy in original TF data - except FECF + // Will be over-written if using encryption later + // TODO: This will change depending on how we handle segment header and FECF above, + // and if it was present in the original TCTF + //if FECF + tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - FECF_SIZE; + //if no FECF + //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; + CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); + index += tf_payload_len; + + /* + ** Begin Security Trailer Fields + */ + + // Set MAC Field if present + /* + ** May be present and unused if switching between clear and authenticated + ** CCSDS 3550b1 4.1.2.3 + */ + for (int i=0; i < temp_SA.stmacf_len; i++) + { + // Temp fill MAC + *(enc_frame + index) = 0x00; + index++; + } + // Determine mode // Clear if ((temp_SA.est == 0) && (temp_SA.ast == 0)) { - // Copy in original TF data - CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), (in_frame_length-TC_FRAME_PRIMARYHEADER_SIZE)); - index += in_frame_length-TC_FRAME_PRIMARYHEADER_SIZE; - - // MAC may be present and unused in plaintext SA - // Reference CCSDS 3550b1 4.1.2.3 - // TODO: Likely API call - for (int i=0; i < temp_SA.stmacf_len; i++) - { - // Temp fill Pad - // TODO: What should pad be, set per channel/SA potentially? - *(enc_frame + index) = 0x00; - index++; - } // TODO: Calc FECF if exists for channel @@ -3022,36 +3039,6 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt else if((temp_SA.est == 1) && (temp_SA.ast == 1)) { - // Determine if padding is needed - // TODO: Likely SA API Call - // TODO: Resolve location of TC_PAD_LENGTH -> SA or TC channel setup - //for (int i=0; i < TC_PAD_SIZE; i++) - for (int i=0; i < temp_SA.shplf_len; i++) - { - // Temp fill Pad - // TODO: What should pad be, set per channel/SA potentially? - *(enc_frame + index) = 0x88; - index++; - } - - // Copy in original TF data - except FECF - // TODO: Need to know presence / absence of FECF - //if FECF - tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - FECF_SIZE; - //if no FECF - //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; - - CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); - index += tf_payload_len; - - // Set MAC Field - for (int i=0; i < temp_SA.stmacf_len; i++) - { - // Temp fill MAC - *(enc_frame + index) = 0x99; - index++; - } - // Set FECF Field // TODO: Determine is FECF is even present // on this particular channel From d29446444f0cb9ead52cfa7f3397123b459e56c0 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 03:06:46 -0400 Subject: [PATCH 032/184] Fix FECF length used in calc --- fsw/src/crypto.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 90eb7b16..eb76e332 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -3004,6 +3004,18 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt index++; } + // Set FECF Field if present + // TODO: Determine is FECF is even present + // on this particular channel + // Calc new fecf, don't include old fecf in length + #ifdef FECF_DEBUG + OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *enc_frame_len - 2); + #endif + new_fecf = Crypto_Calc_FECF(enc_frame, *enc_frame_len - 2); + *(enc_frame + index) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(enc_frame + index + 1) = (uint8) (new_fecf & 0x00FF); + index += 2; + // Determine mode // Clear if ((temp_SA.est == 0) && (temp_SA.ast == 0)) @@ -3039,17 +3051,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt else if((temp_SA.est == 1) && (temp_SA.ast == 1)) { - // Set FECF Field - // TODO: Determine is FECF is even present - // on this particular channel - // Calc new fecf, don't include old fecf in length - #ifdef FECF_DEBUG - OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + sa[spi].shivf_len + sa[spi].shsnf_len + sa[spi].shsnf_len + tf_payload_len); - #endif - new_fecf = Crypto_Calc_FECF(enc_frame, TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + sa[spi].shivf_len + sa[spi].shsnf_len + sa[spi].shsnf_len + tf_payload_len); - *(enc_frame + index) = (uint8) ((new_fecf & 0xFF00) >> 8); - *(enc_frame + index + 1) = (uint8) (new_fecf & 0x00FF); - index += 2; + // Prepare additional authenticated data for (int y = 0; y < sa[spi].abm_len; y++) From 5aa68609139b4892bd85d3da0cba7979618481be Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 03:52:00 -0400 Subject: [PATCH 033/184] Major TC_ApplySecurity refactor work --- fsw/src/crypto.c | 244 ++++++++++++++++++++++------------------------- 1 file changed, 116 insertions(+), 128 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index eb76e332..5ac4de96 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2986,7 +2986,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt //if no FECF //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); - index += tf_payload_len; + //index += tf_payload_len; /* ** Begin Security Trailer Fields @@ -2997,84 +2997,30 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt ** May be present and unused if switching between clear and authenticated ** CCSDS 3550b1 4.1.2.3 */ - for (int i=0; i < temp_SA.stmacf_len; i++) - { - // Temp fill MAC - *(enc_frame + index) = 0x00; - index++; - } - - // Set FECF Field if present - // TODO: Determine is FECF is even present - // on this particular channel - // Calc new fecf, don't include old fecf in length - #ifdef FECF_DEBUG - OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *enc_frame_len - 2); - #endif - new_fecf = Crypto_Calc_FECF(enc_frame, *enc_frame_len - 2); - *(enc_frame + index) = (uint8) ((new_fecf & 0xFF00) >> 8); - *(enc_frame + index + 1) = (uint8) (new_fecf & 0x00FF); - index += 2; - - // Determine mode - // Clear - if ((temp_SA.est == 0) && (temp_SA.ast == 0)) - { - - // TODO: Calc FECF if exists for channel - - #ifdef TC_DEBUG - OS_printf(KYEL "Printing new TC Frame:\n\t"); - for(int i=0; i < *enc_frame_len; i++) - { - OS_printf("%02X", *(enc_frame + i)); - } - OS_printf("\n\tThe returned length is: %d\n" RESET, *enc_frame_len); - #endif + // By leaving MAC as zeros, can use index for encryption output + // for (int i=0; i < temp_SA.stmacf_len; i++) + // { + // // Temp fill MAC + // *(enc_frame + index) = 0x00; + // index++; + // } - *enc_frame_test = enc_frame; - } - - // Authentication - else if ((temp_SA.est == 0) && (temp_SA.ast == 1)) - { - // TODO - } + /* + ** End Security Trailer Fields + */ - // Encryption - else if ((temp_SA.est == 1) && (temp_SA.ast == 0)) - { - // TODO - } + /* + ** Begin Authentication / Encryption + */ - // Authenticated Encryption - else if((temp_SA.est == 1) && (temp_SA.ast == 1)) + if (sa_service_type != SA_PLAINTEXT) { - - - - // Prepare additional authenticated data - for (int y = 0; y < sa[spi].abm_len; y++) - { - aad[y] = in_frame[y] & sa[spi].abm[y]; - } - //TODO AAD / ABM? - #ifdef MAC_DEBUG - OS_printf("Preparing AAD:\n"); - OS_printf("\tUsing ABM Length of %d\n\t", sa[spi].abm_len); - for (int y = 0; y < sa[spi].abm_len; y++) - { - OS_printf("%02x", aad[y]); - } - OS_printf("\n"); - #endif - gcry_error = gcry_cipher_open( &(tmp_hd), GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, GCRY_CIPHER_CBC_MAC - ); + ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); @@ -3104,75 +3050,117 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_lengt return status; } - uint16 output_loc = TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; - OS_printf("Encrypted bytes output_loc is %d\n", output_loc); - OS_printf("tf_payload_len is %d\n", tf_payload_len); - #ifdef TC_DEBUG - OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); - for(int i=0; i < *enc_frame_len; i++) + // Prepare additional authenticated data, if needed + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + for (int y = 0; y < sa[spi].abm_len; y++) { - OS_printf("%02X", *(enc_frame + i)); + aad[y] = in_frame[y] & sa[spi].abm[y]; } - OS_printf("\n"); - #endif + #ifdef MAC_DEBUG + OS_printf(KYEL "Preparing AAD:\n"); + OS_printf("\tUsing ABM Length of %d\n\t", sa[spi].abm_len); + for (int y = 0; y < sa[spi].abm_len; y++) + { + OS_printf("%02x", aad[y]); + } + OS_printf("\n" RESET); + #endif - gcry_error = gcry_cipher_authenticate( - tmp_hd, - &(aad[0]), // additional authenticated data - sa[spi].abm_len // length of AAD - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); - status = OS_ERROR; - return status; + gcry_error = gcry_cipher_authenticate( + tmp_hd, + &(aad[0]), // additional authenticated data + sa[spi].abm_len // length of AAD + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + status = OS_ERROR; + return status; + } } - gcry_error = gcry_cipher_encrypt( - tmp_hd, - &enc_frame[output_loc],// ciphertext output - tf_payload_len, // length of data - (in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now - tf_payload_len // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + if ((sa_service_type == SA_ENCRYPTION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) { - OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - - // TODO - Know if FECF exists - // TODO - Could start working in if/else here wrt ast/est flags - mac_loc = *enc_frame_len - sa[spi].stmacf_len - FECF_SIZE; - #ifdef DEBUG - OS_printf("MAC location is: %d\n", mac_loc); - OS_printf("MAC size is: %d\n", MAC_SIZE); - #endif - gcry_error = gcry_cipher_gettag( - tmp_hd, - &enc_frame[mac_loc], // tag output - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } + // TODO: More robust calculation of this location + // uint16 output_loc = TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; + #ifdef TC_DEBUG + OS_printf("Encrypted bytes output_loc is %d\n", index); + OS_printf("tf_payload_len is %d\n", tf_payload_len); + OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); + for(int i=0; i < *enc_frame_len; i++) + { + OS_printf("%02X", *(enc_frame + i)); + } + OS_printf("\n"); + #endif - #ifdef TC_DEBUG - OS_printf(KYEL "Printing new TC Frame:\n\t"); - for(int i=0; i < *enc_frame_len; i++) + gcry_error = gcry_cipher_encrypt( + tmp_hd, + &enc_frame[index], // ciphertext output + tf_payload_len, // length of data + (in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now + tf_payload_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { - OS_printf("%02x", *(enc_frame + i)); + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; } - OS_printf("\n\tThe returned length is: %d\n" RESET, *enc_frame_len); - #endif + } - *enc_frame_test = enc_frame; + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + // TODO - Know if FECF exists + mac_loc = *enc_frame_len - sa[spi].stmacf_len - FECF_SIZE; + #ifdef MAC_DEBUG + OS_printf(KYEL "MAC location is: %d\n" RESET, mac_loc); + OS_printf(KYEL "MAC size is: %d\n" RESET, MAC_SIZE); + #endif + gcry_error = gcry_cipher_gettag( + tmp_hd, + &enc_frame[mac_loc], // tag output + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + } } + /* + ** End Authentication / Encryption + */ + + // Set FECF Field if present + // TODO: Determine is FECF is even present + // on this particular channel + // Calc new fecf, don't include old fecf in length + #ifdef FECF_DEBUG + OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *enc_frame_len - 2); + #endif + new_fecf = Crypto_Calc_FECF(enc_frame, *enc_frame_len - 2); + *(enc_frame + *enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(enc_frame + *enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); + index += 2; + + #ifdef TC_DEBUG + OS_printf(KYEL "Printing new TC Frame:\n\t"); + for(int i=0; i < *enc_frame_len; i++) + { + OS_printf("%02X", *(enc_frame + i)); + } + OS_printf("\n\tThe returned length is: %d\n" RESET, *enc_frame_len); + #endif + + *enc_frame_test = enc_frame; } #ifdef DEBUG From e422f851cdf85b2642bd866561d882b9a04b1b18 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 11:49:45 -0400 Subject: [PATCH 034/184] Modifying enc_frame_len to * uint16 --- fsw/crypto_util/app/apply_security.c | 2 +- fsw/crypto_util/app/crypto_sequence.c | 2 +- fsw/public_inc/crypto.h | 4 ++-- fsw/src/crypto.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fsw/crypto_util/app/apply_security.c b/fsw/crypto_util/app/apply_security.c index d5c45e4e..304fa095 100644 --- a/fsw/crypto_util/app/apply_security.c +++ b/fsw/crypto_util/app/apply_security.c @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) { Crypto_Init(); uint8 * ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len; //Call ApplySecurity on buffer contents depending on type. if (strcmp(security_type,"tc")==0){ diff --git a/fsw/crypto_util/app/crypto_sequence.c b/fsw/crypto_util/app/crypto_sequence.c index b300aa11..fd8f5dc3 100644 --- a/fsw/crypto_util/app/crypto_sequence.c +++ b/fsw/crypto_util/app/crypto_sequence.c @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { int arg_index = 0; uint8 * ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len; while(arg_index != argc-1){ security_type = argv[++arg_index]; diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index 6b52b935..c1ec197f 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -40,8 +40,8 @@ ivv-itc@lists.nasa.gov // Initialization extern int32 Crypto_Init(void); // Telecommand (TC) -extern int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_length, \ - uint8 **enc_frame, uint32 *enc_frame_len); +extern int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_length, \ + uint8 **enc_frame, uint16 *enc_frame_len); extern int32 Crypto_TC_ProcessSecurity(char* ingest, int* len_ingest, TC_t* tc_sdls_processed_frame); // Telemetry (TM) extern int32 Crypto_TM_ApplySecurity(char* ingest, int* len_ingest); diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 5ac4de96..1c832d7b 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2653,8 +2653,8 @@ static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) return status; } -int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint32 in_frame_length, \ - uint8 **enc_frame_test, uint32 *enc_frame_len) +int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_length, \ + uint8 **enc_frame_test, uint16 *enc_frame_len) { // Local Variables int32 status = OS_SUCCESS; From f9535fe9ac6b6a405b5f0261ef7725df9930ed18 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 12:05:33 -0400 Subject: [PATCH 035/184] Updated function sig var names for clarity within code --- fsw/public_inc/crypto.h | 4 +- fsw/src/crypto.c | 99 +++++++++++++++++++++-------------------- 2 files changed, 52 insertions(+), 51 deletions(-) diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index c1ec197f..06984599 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -40,8 +40,8 @@ ivv-itc@lists.nasa.gov // Initialization extern int32 Crypto_Init(void); // Telecommand (TC) -extern int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_length, \ - uint8 **enc_frame, uint16 *enc_frame_len); +extern int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ + uint8 **pp_enc_frame, uint16 *p_enc_frame_len); extern int32 Crypto_TC_ProcessSecurity(char* ingest, int* len_ingest, TC_t* tc_sdls_processed_frame); // Telemetry (TM) extern int32 Crypto_TM_ApplySecurity(char* ingest, int* len_ingest); diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 1c832d7b..86791836 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2653,13 +2653,14 @@ static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) return status; } -int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_length, \ - uint8 **enc_frame_test, uint16 *enc_frame_len) +int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ + uint8 **pp_in_frame, uint16 *p_enc_frame_len) { // Local Variables int32 status = OS_SUCCESS; TC_FramePrimaryHeader_t temp_tc_header; SecurityAssociation_t temp_SA; + uint8 *p_new_enc_frame = NULL; int16_t spi = -1; uint8 sa_service_type = -1; uint16 mac_loc = 0; @@ -2678,22 +2679,22 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt OS_printf("DEBUG - "); for(int i=0; i < in_frame_length; i++) { - OS_printf("%02X", ((uint8 *)&*in_frame)[i]); + OS_printf("%02X", ((uint8 *)&*p_in_frame)[i]); } OS_printf("\nPrinted %d bytes\n", in_frame_length); #endif // Primary Header - temp_tc_header.tfvn = ((uint8)in_frame[0] & 0xC0) >> 6; - temp_tc_header.bypass = ((uint8)in_frame[0] & 0x20) >> 5; - temp_tc_header.cc = ((uint8)in_frame[0] & 0x10) >> 4; - temp_tc_header.spare = ((uint8)in_frame[0] & 0x0C) >> 2; - temp_tc_header.scid = ((uint8)in_frame[0] & 0x03) << 8; - temp_tc_header.scid = temp_tc_header.scid | (uint8)in_frame[1]; - temp_tc_header.vcid = ((uint8)in_frame[2] & 0xFC) >> 2; - temp_tc_header.fl = ((uint8)in_frame[2] & 0x03) << 8; - temp_tc_header.fl = temp_tc_header.fl | (uint8)in_frame[3]; - temp_tc_header.fsn = (uint8)in_frame[4]; + temp_tc_header.tfvn = ((uint8)p_in_frame[0] & 0xC0) >> 6; + temp_tc_header.bypass = ((uint8)p_in_frame[0] & 0x20) >> 5; + temp_tc_header.cc = ((uint8)p_in_frame[0] & 0x10) >> 4; + temp_tc_header.spare = ((uint8)p_in_frame[0] & 0x0C) >> 2; + temp_tc_header.scid = ((uint8)p_in_frame[0] & 0x03) << 8; + temp_tc_header.scid = temp_tc_header.scid | (uint8)p_in_frame[1]; + temp_tc_header.vcid = ((uint8)p_in_frame[2] & 0xFC) >> 2; + temp_tc_header.fl = ((uint8)p_in_frame[2] & 0x03) << 8; + temp_tc_header.fl = temp_tc_header.fl | (uint8)p_in_frame[3]; + temp_tc_header.fsn = (uint8)p_in_frame[4]; // Check if command frame flag set if (temp_tc_header.cc == 1) @@ -2828,26 +2829,26 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt { case SA_PLAINTEXT: // Ingest length + segment header (1) + spi_index (2) + some variable length fields - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shplf_len; + *p_enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shplf_len; case SA_AUTHENTICATION: // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size + stmacf_len - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + *p_enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len;; case SA_ENCRYPTION: // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + *p_enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE; case SA_AUTHENTICATED_ENCRYPTION: // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size + stmacf_len - *enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ + *p_enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len; } #ifdef TC_DEBUG - OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *enc_frame_len); + OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *p_enc_frame_len); OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); @@ -2860,31 +2861,31 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt #endif // Accio buffer - uint8 *enc_frame = (uint8 *)malloc(*enc_frame_len * sizeof (unsigned char)); - if(!enc_frame) + p_new_enc_frame = (uint8 *)malloc(*p_enc_frame_len * sizeof (unsigned char)); + if(!p_new_enc_frame) { OS_printf(KRED "Error: Malloc for encrypted output buffer failed! \n" RESET); status = OS_ERROR; return status; } - CFE_PSP_MemSet(enc_frame, 0, *enc_frame_len); + CFE_PSP_MemSet(p_new_enc_frame, 0, *p_enc_frame_len); // Copy original TF header - CFE_PSP_MemCpy(enc_frame, in_frame, TC_FRAME_PRIMARYHEADER_SIZE); + CFE_PSP_MemCpy(p_new_enc_frame, p_in_frame, TC_FRAME_PRIMARYHEADER_SIZE); // Set new TF Header length // Recall: Length field is one minus total length per spec - *(enc_frame+2) = ((*(enc_frame+2) & 0xFC) | (((*enc_frame_len - 1) & (0x0300)) >> 8)); - *(enc_frame+3) = ((*enc_frame_len - 1) & (0x00FF)); + *(p_new_enc_frame+2) = ((*(p_new_enc_frame+2) & 0xFC) | (((*p_enc_frame_len - 1) & (0x0300)) >> 8)); + *(p_new_enc_frame+3) = ((*p_enc_frame_len - 1) & (0x00FF)); #ifdef TC_DEBUG OS_printf(KYEL "Printing updated TF Header:\n\t"); for (int i=0; i> 8); - *(enc_frame + index + 1) = (spi & 0x00FF); + *(p_new_enc_frame + index) = ((spi & 0xFF00) >> 8); + *(p_new_enc_frame + index + 1) = (spi & 0x00FF); index += 2; // Set initialization vector if specified @@ -2928,7 +2929,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt { // TODO: Likely API call // Copy in IV from SA - *(enc_frame + index) = sa[spi].iv[i]; + *(p_new_enc_frame + index) = sa[spi].iv[i]; index++; } } @@ -2950,7 +2951,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt Crypto_increment(sa[spi].arc, sa[spi].shsnf_len); for (int i=0; i < temp_SA.shsnf_len; i++) { - *(enc_frame + index) = sa[spi].arc[i]; + *(p_new_enc_frame + index) = sa[spi].arc[i]; index++; } } @@ -2969,7 +2970,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt ** cryptographic process, consisting of an integral number of octets. - CCSDS 3550b1 */ // TODO: Set this depending on crypto cipher used - *(enc_frame + index) = 0x00; + *(p_new_enc_frame + index) = 0x00; index++; } @@ -2985,7 +2986,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - FECF_SIZE; //if no FECF //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; - CFE_PSP_MemCpy((enc_frame+index), (in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); + CFE_PSP_MemCpy((p_new_enc_frame+index), (p_in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); //index += tf_payload_len; /* @@ -3001,7 +3002,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt // for (int i=0; i < temp_SA.stmacf_len; i++) // { // // Temp fill MAC - // *(enc_frame + index) = 0x00; + // *(p_new_enc_frame + index) = 0x00; // index++; // } @@ -3056,7 +3057,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt { for (int y = 0; y < sa[spi].abm_len; y++) { - aad[y] = in_frame[y] & sa[spi].abm[y]; + aad[y] = p_in_frame[y] & sa[spi].abm[y]; } #ifdef MAC_DEBUG OS_printf(KYEL "Preparing AAD:\n"); @@ -3091,18 +3092,18 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt OS_printf("Encrypted bytes output_loc is %d\n", index); OS_printf("tf_payload_len is %d\n", tf_payload_len); OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); - for(int i=0; i < *enc_frame_len; i++) + for(int i=0; i < *p_enc_frame_len; i++) { - OS_printf("%02X", *(enc_frame + i)); + OS_printf("%02X", *(p_new_enc_frame + i)); } OS_printf("\n"); #endif gcry_error = gcry_cipher_encrypt( tmp_hd, - &enc_frame[index], // ciphertext output + &p_new_enc_frame[index], // ciphertext output tf_payload_len, // length of data - (in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now + (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now tf_payload_len // in data length ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -3117,14 +3118,14 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) { // TODO - Know if FECF exists - mac_loc = *enc_frame_len - sa[spi].stmacf_len - FECF_SIZE; + mac_loc = *p_enc_frame_len - sa[spi].stmacf_len - FECF_SIZE; #ifdef MAC_DEBUG OS_printf(KYEL "MAC location is: %d\n" RESET, mac_loc); OS_printf(KYEL "MAC size is: %d\n" RESET, MAC_SIZE); #endif gcry_error = gcry_cipher_gettag( tmp_hd, - &enc_frame[mac_loc], // tag output + &p_new_enc_frame[mac_loc], // tag output MAC_SIZE // tag size ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -3144,23 +3145,23 @@ int32 Crypto_TC_ApplySecurity(const uint8* in_frame, const uint16 in_frame_lengt // on this particular channel // Calc new fecf, don't include old fecf in length #ifdef FECF_DEBUG - OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *enc_frame_len - 2); + OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *p_enc_frame_len - 2); #endif - new_fecf = Crypto_Calc_FECF(enc_frame, *enc_frame_len - 2); - *(enc_frame + *enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); - *(enc_frame + *enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); + new_fecf = Crypto_Calc_FECF(p_new_enc_frame, *p_enc_frame_len - 2); + *(p_new_enc_frame + *p_enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(p_new_enc_frame + *p_enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); index += 2; #ifdef TC_DEBUG OS_printf(KYEL "Printing new TC Frame:\n\t"); - for(int i=0; i < *enc_frame_len; i++) + for(int i=0; i < *p_enc_frame_len; i++) { - OS_printf("%02X", *(enc_frame + i)); + OS_printf("%02X", *(p_new_enc_frame + i)); } - OS_printf("\n\tThe returned length is: %d\n" RESET, *enc_frame_len); + OS_printf("\n\tThe returned length is: %d\n" RESET, *p_enc_frame_len); #endif - *enc_frame_test = enc_frame; + *pp_in_frame = p_new_enc_frame; } #ifdef DEBUG From 501fffdf899154b05b7708d6d5f0371cf4564335 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 12:10:13 -0400 Subject: [PATCH 036/184] Return Error if c/c flag set --- fsw/src/crypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 86791836..3fb9fd4e 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2707,13 +2707,14 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len #ifdef TC_DEBUG OS_printf(KYEL "DEBUG - Received Control/Command frame - nothing to do.\n" RESET); #endif + status = OS_ERROR; } // TODO: If command frame flag not set, need to know SDLS parameters // What is the best way to do this - copy in the entire SA for a channel? // Expect these calls will return an error is the SA is not usable // Will need to know lengths of various parameters from the SA DB - else + if (status == OS_SUCCESS) { // Query SA DB for active SA / SDLS paremeters // TODO: Likely API call From d21e15e20ac37ebd4c2bfa3aa5a9a58e831f5778 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Fri, 5 Nov 2021 12:28:03 -0400 Subject: [PATCH 037/184] Restore initial SA, add case breaks --- fsw/src/crypto.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 3fb9fd4e..5edf0965 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -566,8 +566,7 @@ static int32 Crypto_SA_config(void) // Security Associations // SA 1 - CLEAR MODE - // sa[1].sa_state = SA_OPERATIONAL; - sa[1].sa_state = SA_NONE; + sa[1].sa_state = SA_OPERATIONAL; sa[1].est = 0; sa[1].ast = 0; sa[1].shplf_len = 2; @@ -617,8 +616,7 @@ static int32 Crypto_SA_config(void) sa[3].arc_len = (sa[3].arcw[0] * 2) + 1; // SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 sa[4].ekid = 130; - // sa[4].sa_state = SA_KEYED; - sa[4].sa_state = SA_OPERATIONAL; + sa[4].sa_state = SA_KEYED; sa[4].est = 1; sa[4].ast = 1; sa[4].shivf_len = 12; @@ -2814,12 +2812,16 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len { case SA_PLAINTEXT: OS_printf(KBLU "Creating a TC - CLEAR!\n" RESET); + break; case SA_AUTHENTICATION: OS_printf(KBLU "Creating a TC - AUTHENTICATED!\n" RESET); + break; case SA_ENCRYPTION: OS_printf(KBLU "Creating a TC - ENCRYPTED!\n" RESET); + break; case SA_AUTHENTICATED_ENCRYPTION: OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION!\n" RESET); + break; } #endif From 8ca55886dc91666d26edd3644c2a6358d9fbfd78 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Mon, 8 Nov 2021 05:38:26 -0500 Subject: [PATCH 038/184] Add cipher_close call --- fsw/crypto_util/app/apply_security.c | 2 +- fsw/src/crypto.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/fsw/crypto_util/app/apply_security.c b/fsw/crypto_util/app/apply_security.c index 304fa095..ca34e508 100644 --- a/fsw/crypto_util/app/apply_security.c +++ b/fsw/crypto_util/app/apply_security.c @@ -17,7 +17,7 @@ /* * Simple apply security program that reads a file into memory and calls the Crypto_TC_ApplySecurity function on the data. - */ + */ #include "apply_security.h" diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 5edf0965..ff0182f6 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -3138,6 +3138,11 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len return status; } } + // Zeroise any sensitive information + if (sa_service_type != SA_PLAINTEXT) + { + gcry_cipher_close(tmp_hd); + } } /* ** End Authentication / Encryption From 43bf3fb0ed8a0796a108c396cc33c73139004396 Mon Sep 17 00:00:00 2001 From: Robert Brown Date: Mon, 8 Nov 2021 12:43:45 -0500 Subject: [PATCH 039/184] Cleanup and Comments for UTs --- fsw/crypto_util/app/ut_tc_apply.c | 60 ++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c index 0d7c5ebb..c133b3a8 100644 --- a/fsw/crypto_util/app/ut_tc_apply.c +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -21,9 +21,25 @@ #include "ut_tc_apply.h" #include "utest.h" -// Initilization header? +// TODO: Should this be set up with a set of tests, or continue to Crypto_Init() each time. For now I think the current setup is the best path. -UTEST(HAPPY_PATH, TC_APPLY_SECURITY) +// Inactive SA Database +// TODO: Should this return or continue to function as currently written when SA is not initalized? +UTEST(TC_APPLY_SECURITY, NO_CRYPTO_INIT) +{ + // No Crypto_Init(); + long buffer_size; + char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping.dat", &buffer_size); + uint32 buffer_size_i = (uint32) buffer_size; + + uint8 *ptr_enc_frame = NULL; + uint32 enc_frame_len; + + ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), 0); +} + +// Nominal Test. This should read a raw_tc_sdls_ping.dat file, continue down the "happy path", and return OS_SUCCESS +UTEST(TC_APPLY_SECURITY, HAPPY_PATH) { //Setup & Initialize CryptoLib Crypto_Init(); @@ -34,10 +50,11 @@ UTEST(HAPPY_PATH, TC_APPLY_SECURITY) uint8 *ptr_enc_frame = NULL; uint32 enc_frame_len; - ASSERT_TRUE(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len) == 0); + ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), 0); } -UTEST(BAD_SPACE_CRAFT_ID, TC_APPLY_SECURITY) +// Bad Space Craft ID. This should pass the flawed .dat file, and return OS_ERROR +UTEST(TC_APPLY_SECURITY, BAD_SPACE_CRAFT_ID) { //Setup & Initialize CryptoLib Crypto_Init(); @@ -48,10 +65,12 @@ UTEST(BAD_SPACE_CRAFT_ID, TC_APPLY_SECURITY) uint8 *ptr_enc_frame = NULL; uint32 enc_frame_len; - ASSERT_FALSE(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len) == 0); + ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), -1); } -UTEST(BAD_VIRTUAL_CHANNEL_ID, TC_APPLY_SECURITY) +// TODO: This does not report the correct error. It returns the correctly, but complains of an incorrect SCID +// This should return OS_ERROR +UTEST(TC_APPLY_SECURITY, BAD_VIRTUAL_CHANNEL_ID) { //Setup & Initialize CryptoLib Crypto_Init(); @@ -62,10 +81,14 @@ UTEST(BAD_VIRTUAL_CHANNEL_ID, TC_APPLY_SECURITY) uint8 *ptr_enc_frame = NULL; uint32 enc_frame_len; - ASSERT_FALSE(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len) == 0); + ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), -1); } -UTEST(NULL_BUFFER, TC_APPLY_SECURITY) +// This test should test how to handle a null buffer being passed into the ApplySecurity Function. +// Currently this functionality isn't handled properly, and casues a seg-fault. +// TODO: We need to determine how this would return, as it will help in other test cases. +// Should this return the original buffer, a null pointer, OS_ERROR, etc? +UTEST(TC_APPLY_SECURITY, NULL_BUFFER) { //Setup & Initialize CryptoLib Crypto_Init(); @@ -76,9 +99,28 @@ UTEST(NULL_BUFFER, TC_APPLY_SECURITY) uint8 *ptr_enc_frame = NULL; uint32 enc_frame_len; - ASSERT_FALSE(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len) == 0); + ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), -1); } +//TODO: +/* What should be returned if something goes wrong with Control Command Flag? + Should a NULL pointer be returned....THe original pointer? + We need to decide on this functionality and write a test for this + + We should probably have more error codes than OS_SUCCESS and OS_ERROR + + Some way to modify and test the SA? + + Authentication Tests + When Ready / Complete? + + Encryption Tests + When Ready / Complete? + + Authenticated Encryption Tests + When Ready / Complete +*/ + UTEST_MAIN(); \ No newline at end of file From f1ae841806cfdaa5802e6a6e00365e91dc9b36ba Mon Sep 17 00:00:00 2001 From: Robert Brown Date: Mon, 8 Nov 2021 12:59:35 -0500 Subject: [PATCH 040/184] Fixing Macro Variable issues in UTests --- fsw/crypto_util/app/ut_tc_apply.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c index c133b3a8..4b8320b6 100644 --- a/fsw/crypto_util/app/ut_tc_apply.c +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -34,8 +34,10 @@ UTEST(TC_APPLY_SECURITY, NO_CRYPTO_INIT) uint8 *ptr_enc_frame = NULL; uint32 enc_frame_len; + int return_val = -1; - ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), 0); + return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(return_val, 0); } // Nominal Test. This should read a raw_tc_sdls_ping.dat file, continue down the "happy path", and return OS_SUCCESS @@ -50,11 +52,14 @@ UTEST(TC_APPLY_SECURITY, HAPPY_PATH) uint8 *ptr_enc_frame = NULL; uint32 enc_frame_len; - ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), 0); + int return_val = -1; + + return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(return_val, 0); } // Bad Space Craft ID. This should pass the flawed .dat file, and return OS_ERROR -UTEST(TC_APPLY_SECURITY, BAD_SPACE_CRAFT_ID) +UTEST(TC_APPLY_SECURITY1, BAD_SPACE_CRAFT_ID) { //Setup & Initialize CryptoLib Crypto_Init(); @@ -64,8 +69,10 @@ UTEST(TC_APPLY_SECURITY, BAD_SPACE_CRAFT_ID) uint8 *ptr_enc_frame = NULL; uint32 enc_frame_len; + int return_val = -1; - ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), -1); + return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(return_val, -1); } // TODO: This does not report the correct error. It returns the correctly, but complains of an incorrect SCID @@ -80,8 +87,9 @@ UTEST(TC_APPLY_SECURITY, BAD_VIRTUAL_CHANNEL_ID) uint8 *ptr_enc_frame = NULL; uint32 enc_frame_len; - - ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), -1); + int return_val = -1; + return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(return_val, return_val); } // This test should test how to handle a null buffer being passed into the ApplySecurity Function. From df9d07d4bb00b31a61a11acd519e7373bd909c4a Mon Sep 17 00:00:00 2001 From: Robert Brown Date: Tue, 9 Nov 2021 17:36:41 -0500 Subject: [PATCH 041/184] Fixed Unit Tests Warnings due to signature change after commit, Fixed Non-Debug issues with UTest framework, Fixed Null Buffer issue in Crypt.c, fixed bug found in crypto.c via no init utest --- fsw/crypto_util/app/ut_tc_apply.c | 79 ++++++++++++++++++++----------- fsw/crypto_util/include/utest.h | 18 +++---- fsw/src/crypto.c | 29 ++++++++---- 3 files changed, 81 insertions(+), 45 deletions(-) diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c index 4b8320b6..77befc20 100644 --- a/fsw/crypto_util/app/ut_tc_apply.c +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -16,7 +16,7 @@ */ /* - * Simple apply security program that reads a file into memory and calls the Crypto_TC_ApplySecurity function on the data. + * Unit Tests that macke use of TC_ApplySecurity function on the data. */ #include "ut_tc_apply.h" #include "utest.h" @@ -25,19 +25,25 @@ // Inactive SA Database // TODO: Should this return or continue to function as currently written when SA is not initalized? +// TODO: I don't believe Crypto Init is cleaned up between each test. I am fairly certain that the init persists between tests. + +// TODO: Need to cherry-pick Crypto_reInit functionality to use between each of these tests UTEST(TC_APPLY_SECURITY, NO_CRYPTO_INIT) { // No Crypto_Init(); - long buffer_size; + long buffer_size = 0; char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping.dat", &buffer_size); - uint32 buffer_size_i = (uint32) buffer_size; + uint16 buffer_size_i = (uint16) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; - int return_val = -1; + uint16 enc_frame_len = 0; + int32 return_val = -1; return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(return_val, 0); + + ASSERT_EQ(-1, return_val); + free(buffer); + free(ptr_enc_frame); } // Nominal Test. This should read a raw_tc_sdls_ping.dat file, continue down the "happy path", and return OS_SUCCESS @@ -45,34 +51,40 @@ UTEST(TC_APPLY_SECURITY, HAPPY_PATH) { //Setup & Initialize CryptoLib Crypto_Init(); - long buffer_size; + long buffer_size =0; char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping.dat", &buffer_size); - uint32 buffer_size_i = (uint32) buffer_size; + uint16 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len = 0; - int return_val = -1; + int32 return_val = -1; return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(return_val, 0); + ASSERT_EQ(0, return_val); + free(buffer); + free(ptr_enc_frame); + //Need Crypto_ReInit()?; } // Bad Space Craft ID. This should pass the flawed .dat file, and return OS_ERROR -UTEST(TC_APPLY_SECURITY1, BAD_SPACE_CRAFT_ID) +UTEST(TC_APPLY_SECURITY, BAD_SPACE_CRAFT_ID) { //Setup & Initialize CryptoLib Crypto_Init(); - long buffer_size; + long buffer_size = 0; char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat", &buffer_size); - uint32 buffer_size_i = (uint32) buffer_size; + uint16 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; - int return_val = -1; + uint16 enc_frame_len = 0; + int32 return_val = -1; return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(return_val, -1); + ASSERT_EQ(-1, return_val); + free(buffer); + free(ptr_enc_frame); + //Need Crypto_ReInit(); } // TODO: This does not report the correct error. It returns the correctly, but complains of an incorrect SCID @@ -81,17 +93,24 @@ UTEST(TC_APPLY_SECURITY, BAD_VIRTUAL_CHANNEL_ID) { //Setup & Initialize CryptoLib Crypto_Init(); - long buffer_size; + long buffer_size = 0; char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat", &buffer_size); - uint32 buffer_size_i = (uint32) buffer_size; + uint16 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; - int return_val = -1; + uint16 enc_frame_len = 0; + int32 return_val = -1; + return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(return_val, return_val); + ASSERT_EQ(0, return_val); //TODO: Having this fail until it is fixed in code. + free(buffer); + free(ptr_enc_frame); + //Need Crypto_ReInit(); } +// Encryption Test HERE + + // This test should test how to handle a null buffer being passed into the ApplySecurity Function. // Currently this functionality isn't handled properly, and casues a seg-fault. // TODO: We need to determine how this would return, as it will help in other test cases. @@ -100,19 +119,25 @@ UTEST(TC_APPLY_SECURITY, NULL_BUFFER) { //Setup & Initialize CryptoLib Crypto_Init(); - long buffer_size; + long buffer_size = 0; char *buffer = NULL; - uint32 buffer_size_i = (uint32) buffer_size; + uint16 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len = 0; + int32 return_val = -1; + + return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), -1); + ASSERT_EQ(-1, return_val); + free(buffer); + free(ptr_enc_frame); + //Need Crypto_ReInit(); } //TODO: /* What should be returned if something goes wrong with Control Command Flag? - Should a NULL pointer be returned....THe original pointer? + Should a NULL pointer be returned....The original pointer? We need to decide on this functionality and write a test for this We should probably have more error codes than OS_SUCCESS and OS_ERROR diff --git a/fsw/crypto_util/include/utest.h b/fsw/crypto_util/include/utest.h index 41ec2ce7..08cef51a 100644 --- a/fsw/crypto_util/include/utest.h +++ b/fsw/crypto_util/include/utest.h @@ -991,7 +991,7 @@ int utest_main(int argc, const char *const argv[]) { const char *filter = UTEST_NULL; utest_uint64_t ran_tests = 0; - enum colours { U_RESET, GREEN, RED }; + enum colours { U_RESET, U_GREEN, U_RED }; const int use_colours = UTEST_COLOUR_OUTPUT(); const char *colours[] = {"\033[0m", "\033[32m", "\033[31m"}; @@ -1045,7 +1045,7 @@ int utest_main(int argc, const char *const argv[]) { ran_tests++; } printf("%s[==========]%s Running %" UTEST_PRIu64 " test cases.\n", - colours[GREEN], colours[U_RESET], UTEST_CAST(utest_uint64_t, ran_tests)); + colours[U_GREEN], colours[U_RESET], UTEST_CAST(utest_uint64_t, ran_tests)); if (utest_state.output) { fprintf(utest_state.output, "\n"); @@ -1065,7 +1065,7 @@ int utest_main(int argc, const char *const argv[]) { continue; } - printf("%s[ RUN ]%s %s\n", colours[GREEN], colours[U_RESET], + printf("%s[ RUN ]%s %s\n", colours[U_GREEN], colours[U_RESET], utest_state.tests[index].name); if (utest_state.output) { @@ -1091,24 +1091,24 @@ int utest_main(int argc, const char *const argv[]) { failed_testcases[failed_testcase_index] = index; } failed++; - printf("%s[ FAILED ]%s %s (%" UTEST_PRId64 "ns)\n", colours[RED], + printf("%s[ FAILED ]%s %s (%" UTEST_PRId64 "ns)\n", colours[U_RED], colours[U_RESET], utest_state.tests[index].name, ns); } else { - printf("%s[ OK ]%s %s (%" UTEST_PRId64 "ns)\n", colours[GREEN], + printf("%s[ OK ]%s %s (%" UTEST_PRId64 "ns)\n", colours[U_GREEN], colours[U_RESET], utest_state.tests[index].name, ns); } } - printf("%s[==========]%s %" UTEST_PRIu64 " test cases ran.\n", colours[GREEN], + printf("%s[==========]%s %" UTEST_PRIu64 " test cases ran.\n", colours[U_GREEN], colours[U_RESET], ran_tests); - printf("%s[ PASSED ]%s %" UTEST_PRIu64 " tests.\n", colours[GREEN], + printf("%s[ PASSED ]%s %" UTEST_PRIu64 " tests.\n", colours[U_GREEN], colours[U_RESET], ran_tests - failed); if (0 != failed) { printf("%s[ FAILED ]%s %" UTEST_PRIu64 " tests, listed below:\n", - colours[RED], colours[U_RESET], failed); + colours[U_RED], colours[U_RESET], failed); for (index = 0; index < failed_testcases_length; index++) { - printf("%s[ FAILED ]%s %s\n", colours[RED], colours[U_RESET], + printf("%s[ FAILED ]%s %s\n", colours[U_RED], colours[U_RESET], utest_state.tests[failed_testcases[index]].name); } } diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index ff0182f6..ec9c22ea 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -101,8 +101,8 @@ static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); ** Global Variables */ // Security -static SecurityAssociation_t sa[NUM_SA]; -static crypto_key_t ek_ring[NUM_KEYS]; +static SecurityAssociation_t sa[NUM_SA] = {0}; +static crypto_key_t ek_ring[NUM_KEYS] = {0}; //static crypto_key_t ak_ring[NUM_KEYS]; // Local Frames static CCSDS_t sdls_frame; @@ -2657,9 +2657,9 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len // Local Variables int32 status = OS_SUCCESS; TC_FramePrimaryHeader_t temp_tc_header; - SecurityAssociation_t temp_SA; + SecurityAssociation_t temp_SA = {0}; uint8 *p_new_enc_frame = NULL; - int16_t spi = -1; + int spi = -1; uint8 sa_service_type = -1; uint16 mac_loc = 0; uint16 tf_payload_len = 0x0000; @@ -2672,6 +2672,13 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); #endif + if (p_in_frame == NULL) + { + status = OS_ERROR; + OS_printf(KRED "Error: Input Buffer NULL! \n" RESET); + return status; //Just return here, nothing can be done. + } + #ifdef DEBUG OS_printf("%d TF Bytes received\n", in_frame_length); OS_printf("DEBUG - "); @@ -2695,7 +2702,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len temp_tc_header.fsn = (uint8)p_in_frame[4]; // Check if command frame flag set - if (temp_tc_header.cc == 1) + if ((temp_tc_header.cc == 1) && (status == OS_SUCCESS)) { /* ** CCSDS 232.0-B-3 @@ -2718,7 +2725,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len // TODO: Likely API call // TODO: Magic to make sure we're getting the correct SA.. // currently SA DB allows for more than one - for (int i=0; i < NUM_SA;i++) + for (int i=0; i < NUM_SA; i++) { if (sa[i].sa_state == SA_OPERATIONAL) { @@ -2741,11 +2748,15 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len #ifdef TC_DEBUG OS_printf("Operational SA found at index %d.\n", spi); #endif - } + #ifdef SA_DEBUG + OS_printf(KYEL "DEBUG - Printing local copy of SA Entry for current SPI.\n" RESET); + Crypto_saPrint(&temp_SA); + #endif + } #ifdef SA_DEBUG OS_printf(KYEL "DEBUG - Received data frame.\n" RESET); - OS_printf("Using SA 0x%04X settings.\n", spi); + OS_printf("Using SA %d settings.\n", spi); #endif // Verify SCID @@ -2769,7 +2780,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len status = OS_ERROR; } // Check if this VCID exists / is mapped to TCs - if ((temp_SA.gvcid_tc_blk[temp_tc_header.vcid].mapid != TYPE_TC) && (status = OS_SUCCESS)) + if ((status == OS_SUCCESS) && (temp_SA.gvcid_tc_blk[temp_tc_header.vcid].mapid != TYPE_TC)) { OS_printf(KRED "Error: SA does not map this VCID to TC! \n" RESET); status = OS_ERROR; From 168abd9c4ab97df4dcb106e243dc9319953ed3ab Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Tue, 16 Nov 2021 12:00:47 -0800 Subject: [PATCH 042/184] AKMC-113: Update Crypto_TC_ApplySecurity function with sadb interface calls, more mysql sadb implementation --- .../create_sadb.sql | 10 +- ...e_sadb_unit_test_security_associations.sql | 16 +- fsw/crypto_util/app/ut_tc_apply.c | 10 +- fsw/public_inc/crypto_error.h | 46 +- fsw/public_inc/crypto_print.h | 3 +- fsw/public_inc/crypto_structs.h | 1 + fsw/public_inc/itc_common_types_minimum.h | 82 +- fsw/public_inc/sadb_mariadb_error.h | 38 +- fsw/public_inc/sadb_routine.h | 2 + fsw/src/crypto.c | 6917 ++++++++--------- fsw/src/crypto_print.c | 29 + fsw/src/sadb_routine_inmemory.template.c | 45 + fsw/src_mysql/sadb_routine_mariadb.template.c | 96 +- 13 files changed, 3696 insertions(+), 3599 deletions(-) diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql index ac781c71..7f93b27a 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql @@ -6,9 +6,9 @@ USE sadb; CREATE TABLE security_associations ( - sa_id INT NOT NULL - ,ekid MEDIUMINT NOT NULL DEFAULT sa_id - ,akid MEDIUMINT NOT NULL DEFAULT sa_id + spi INT NOT NULL + ,ekid MEDIUMINT NOT NULL DEFAULT spi + ,akid MEDIUMINT NOT NULL DEFAULT spi ,sa_state SMALLINT NOT NULL DEFAULT 0 ,tfvn TINYINT ,scid SMALLINT @@ -24,13 +24,13 @@ CREATE TABLE security_associations ,ecs_len SMALLINT ,ecs SMALLINT NOT NULL DEFAULT 0 ,iv_len SMALLINT NOT NULL DEFAULT 12 - ,iv SMALLINT + ,iv BINARY(12) NOT NULL DEFAULT 0 -- IV_SIZE=12 ,acs_len SMALLINT NOT NULL DEFAULT 0 ,acs SMALLINT NOT NULL DEFAULT 0 ,abm_len MEDIUMINT ,abm SMALLINT ,arc_len SMALLINT NOT NULL DEFAULT 0 - ,arc SMALLINT NOT NULL DEFAULT 5 + ,arc BINARY(20) NOT NULL DEFAULT 0 -- ARC_LEN=20 , TBD why so large... ,arcw_len SMALLINT ,arcw SMALLINT ); \ No newline at end of file diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql index 2029f12f..024bf989 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql @@ -1,33 +1,33 @@ USE sadb; -- SA 1 - CLEAR MODE -INSERT INTO security_associations (sa_id,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) +INSERT INTO security_associations (spi,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) VALUES (1,3,0,0,1,0,1,5,0,3,0,0); -- SA 2 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 128 -INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) VALUES (2,128,2,1,1,12,12,0,20,0,1,5,11); -- SA 3 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 129 -INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,stmacf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,stmacf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) VALUES (3,129,2,1,1,12,16,12,0,20,0,1,5,11); -- SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 -INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) VALUES (4,130,2,1,1,12,12,0,20,0,1,5,11,0,3,0,0); -- SA 5 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 131 -INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) VALUES (5,131,2,1,1,12,12,0,20,0,1,5,11); -- SA 6 - UNKEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: - -INSERT INTO security_associations (sa_id,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) +INSERT INTO security_associations (spi,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) VALUES (6,1,1,1,12,12,0,20,0,1,5,11); -- SA 7 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 -INSERT INTO security_associations (sa_id,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) VALUES (7,130,2,1,1,12,12,0,20,0,1,5,11,0,3,1,0); -- SA 8 - CLEAR MODE -INSERT INTO security_associations (sa_id,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) +INSERT INTO security_associations (spi,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) VALUES (8,3,0,0,1,0,1,5,0,3,1,0); diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c index 4b8320b6..cea75dbd 100644 --- a/fsw/crypto_util/app/ut_tc_apply.c +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -33,7 +33,7 @@ UTEST(TC_APPLY_SECURITY, NO_CRYPTO_INIT) uint32 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len; int return_val = -1; return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); @@ -50,7 +50,7 @@ UTEST(TC_APPLY_SECURITY, HAPPY_PATH) uint32 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len; int return_val = -1; @@ -68,7 +68,7 @@ UTEST(TC_APPLY_SECURITY1, BAD_SPACE_CRAFT_ID) uint32 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len; int return_val = -1; return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); @@ -86,7 +86,7 @@ UTEST(TC_APPLY_SECURITY, BAD_VIRTUAL_CHANNEL_ID) uint32 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len; int return_val = -1; return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); ASSERT_EQ(return_val, return_val); @@ -105,7 +105,7 @@ UTEST(TC_APPLY_SECURITY, NULL_BUFFER) uint32 buffer_size_i = (uint32) buffer_size; uint8 *ptr_enc_frame = NULL; - uint32 enc_frame_len; + uint16 enc_frame_len; ASSERT_EQ(Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len), -1); } diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h index 3cbdb59f..08f9a89c 100644 --- a/fsw/public_inc/crypto_error.h +++ b/fsw/public_inc/crypto_error.h @@ -1,23 +1,23 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. - -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder - -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov -*/ -#ifndef _crypto_error_h_ -#define _crypto_error_h_ - -#include "sadb_mariadb_error.h" - - -#endif //_crypto_error_h_ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + +This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not +limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +any warranty that the software will be error free. + +In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +documentation or services provided hereunder + +ITC Team +NASA IV&V +ivv-itc@lists.nasa.gov +*/ +#ifndef _crypto_error_h_ +#define _crypto_error_h_ + +#include "sadb_mariadb_error.h" + + +#endif //_crypto_error_h_ diff --git a/fsw/public_inc/crypto_print.h b/fsw/public_inc/crypto_print.h index 41a5d858..13daaeb2 100644 --- a/fsw/public_inc/crypto_print.h +++ b/fsw/public_inc/crypto_print.h @@ -34,5 +34,6 @@ void Crypto_clcwPrint(TM_FrameCLCW_t* clcw); void Crypto_fsrPrint(SDLS_FSR_t* report); void Crypto_ccsdsPrint(CCSDS_t* sdls_frame); void Crypto_saPrint(SecurityAssociation_t* sa); - +void Crypto_hexprint(void *c, size_t n); +void Crypto_binprint(void *c, size_t n); #endif diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index 01f981f9..59021a06 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -50,6 +50,7 @@ typedef struct typedef struct { // Status + uint16 spi; //Security Parameter Index uint16 ekid; // Encryption Key ID uint16 akid; // Authentication Key ID uint8 sa_state:2; diff --git a/fsw/public_inc/itc_common_types_minimum.h b/fsw/public_inc/itc_common_types_minimum.h index 10408298..77793147 100644 --- a/fsw/public_inc/itc_common_types_minimum.h +++ b/fsw/public_inc/itc_common_types_minimum.h @@ -1,41 +1,41 @@ -/* - * Minimal port of https://github.com/nasa-itc/osal/blob/master/src/os/inc/common_types.h - * needed to build standalone crypto library. - * - * Copyright (c) 2019 United States Government as represented by - * the Administrator of the National Aeronautics and Space Administration. - * All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _itc_common_types_minimum_ -#define _itc_common_types_minimum_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -typedef uintptr_t cpuaddr; -typedef size_t cpusize; -typedef ptrdiff_t cpudiff; - -#ifdef __cplusplus -} -#endif - - -#endif //itc_common_types_minimum_.h +/* + * Minimal port of https://github.com/nasa-itc/osal/blob/master/src/os/inc/common_types.h + * needed to build standalone crypto library. + * + * Copyright (c) 2019 United States Government as represented by + * the Administrator of the National Aeronautics and Space Administration. + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _itc_common_types_minimum_ +#define _itc_common_types_minimum_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +typedef uintptr_t cpuaddr; +typedef size_t cpusize; +typedef ptrdiff_t cpudiff; + +#ifdef __cplusplus +} +#endif + + +#endif //itc_common_types_minimum_.h diff --git a/fsw/public_inc/sadb_mariadb_error.h b/fsw/public_inc/sadb_mariadb_error.h index 2badf05e..eb2b4686 100644 --- a/fsw/public_inc/sadb_mariadb_error.h +++ b/fsw/public_inc/sadb_mariadb_error.h @@ -1,12 +1,26 @@ -// -// Created by isaleh on 11/3/2021. -// - -#ifndef _sadb_mariadb_error_h_ -#define _sadb_mariadb_error_h_ - -#define SADB_MARIADB_CONNECTION_FAILED 300 -#define SADB_QUERY_BY_SPI_FAILED 301 -#define SADB_QUERY_BY_SPI_EMPTY_RESULTS 302 - -#endif //_sadb_mariadb_error_h_ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + +This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not +limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +any warranty that the software will be error free. + +In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +documentation or services provided hereunder + +ITC Team +NASA IV&V +ivv-itc@lists.nasa.gov +*/ + +#ifndef _sadb_mariadb_error_h_ +#define _sadb_mariadb_error_h_ + +#define SADB_MARIADB_CONNECTION_FAILED 300 +#define SADB_QUERY_FAILED 301 +#define SADB_QUERY_EMPTY_RESULTS 302 +#define SADB_INSERT_FAILED 303 + +#endif //_sadb_mariadb_error_h_ diff --git a/fsw/public_inc/sadb_routine.h b/fsw/public_inc/sadb_routine.h index dfc937bb..838ecb04 100644 --- a/fsw/public_inc/sadb_routine.h +++ b/fsw/public_inc/sadb_routine.h @@ -32,6 +32,8 @@ typedef struct { int32 (*sadb_close)(void); // Security Association Interaction Functions int32 (*sadb_get_sa_from_spi)(uint16,SecurityAssociation_t**); + int32 (*sadb_get_operational_sa_from_gvcid)(uint8,uint16,uint16,uint8,SecurityAssociation_t**); + int32 (*sadb_save_sa)(SecurityAssociation_t*); // Security Association Utility Functions int32 (*sadb_sa_stop)(void); int32 (*sadb_sa_start)(TC_t* tc_frame); diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 90194012..5a370ed9 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -1,3483 +1,3436 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. - -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any0 way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder - -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov -*/ -#ifndef _crypto_c_ -#define _crypto_c_ - -/* -** Includes -*/ -#include "crypto.h" -#include "sadb_routine.h" - -#include "itc_aes128.h" -#include "itc_gcm128.h" - -#include "crypto_structs.h" -#include "crypto_print.h" -#include "crypto_config.h" -#include "crypto_events.h" - - - -#include - - -/* -** Static Library Declaration -*/ -#ifdef BUILD_STATIC - CFS_MODULE_DECLARE_LIB(crypto); -#endif - -static SadbRoutine sadb_routine = NULL; - -/* -** Static Prototypes -*/ -// Assisting Functions -static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame); -static int32 Crypto_Get_tmLength(int len); -static void Crypto_TM_updatePDU(char* ingest, int len_ingest); -static void Crypto_TM_updateOCF(void); -static void Crypto_Local_Config(void); -static void Crypto_Local_Init(void); -//static int32 Crypto_gcm_err(int gcm_err); -static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window); -static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length); -static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame); -static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest); -static void Crypto_Calc_CRC_Init_Table(void); -static uint16 Crypto_Calc_CRC16(char* data, int size); -// Key Management Functions -static int32 Crypto_Key_OTAR(void); -static int32 Crypto_Key_update(uint8 state); -static int32 Crypto_Key_inventory(char*); -static int32 Crypto_Key_verify(char*,TC_t* tc_frame); -// Security Monitoring & Control Procedure -static int32 Crypto_MC_ping(char* ingest); -static int32 Crypto_MC_status(char* ingest); -static int32 Crypto_MC_dump(char* ingest); -static int32 Crypto_MC_erase(char* ingest); -static int32 Crypto_MC_selftest(char* ingest); -static int32 Crypto_SA_readARSN(char* ingest); -static int32 Crypto_MC_resetalarm(void); -// User Functions -static int32 Crypto_User_IdleTrigger(char* ingest); -static int32 Crypto_User_BadSPI(void); -static int32 Crypto_User_BadIV(void); -static int32 Crypto_User_BadMAC(void); -static int32 Crypto_User_BadFECF(void); -static int32 Crypto_User_ModifyKey(void); -static int32 Crypto_User_ModifyActiveTM(void); -static int32 Crypto_User_ModifyVCID(void); -// Determine Payload Data Unit -static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); - -/* -** Global Variables -*/ -// Security -crypto_key_t ek_ring[NUM_KEYS]; -//static crypto_key_t ak_ring[NUM_KEYS]; -CCSDS_t sdls_frame; -TM_t tm_frame; -// OCF -static uint8 ocf = 0; -static SDLS_FSR_t report; -static TM_FrameCLCW_t clcw; -// Flags -static SDLS_MC_LOG_RPLY_t log_summary; -static SDLS_MC_DUMP_BLK_RPLY_t log; -static uint8 log_count = 0; -static uint16 tm_offset = 0; -// ESA Testing - 0 = disabled, 1 = enabled -static uint8 badSPI = 0; -static uint8 badIV = 0; -static uint8 badMAC = 0; -static uint8 badFECF = 0; -// CRC -static uint32 crc32Table[256]; -static uint16 crc16Table[256]; - -/* -** Initialization Functions -*/ -int32 Crypto_Init(void) -{ - int32 status = OS_SUCCESS; - - //TODO -- Make the routine that gets called variable based on configuration! - sadb_routine = get_sadb_routine_inmemory(); - //sadb_routine = get_sadb_routine_mariadb(); - - - // Initialize libgcrypt - if (!gcry_check_version(GCRYPT_VERSION)) - { - fprintf(stderr, "Gcrypt Version: %s",GCRYPT_VERSION); - OS_printf(KRED "\tERROR: gcrypt version mismatch! \n" RESET); - } - if (gcry_control(GCRYCTL_SELFTEST) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcrypt self test failed\n" RESET); - } - gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); - - // Init Security Associations - status = sadb_routine->sadb_init(); - status = sadb_routine->sadb_config(); - - Crypto_Local_Init(); - Crypto_Local_Config(); - - // TODO - Add error checking - - // Init table for CRC calculations - Crypto_Calc_CRC_Init_Table(); - - // cFS Standard Initialized Message - OS_printf (KBLU "Crypto Lib Intialized. Version %d.%d.%d.%d\n" RESET, - CRYPTO_LIB_MAJOR_VERSION, - CRYPTO_LIB_MINOR_VERSION, - CRYPTO_LIB_REVISION, - CRYPTO_LIB_MISSION_REV); - - return status; -} - -static void Crypto_Local_Config(void) -{ - // Initial TM configuration - tm_frame.tm_sec_header.spi = 1; - - // Initialize Log - log_summary.num_se = 2; - log_summary.rs = LOG_SIZE; - // Add a two messages to the log - log_summary.rs--; - log.blk[log_count].emt = STARTUP; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - log_summary.rs--; - log.blk[log_count].emt = STARTUP; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - - // Master Keys - // 0 - 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F -> ACTIVE - ek_ring[0].value[0] = 0x00; - ek_ring[0].value[1] = 0x01; - ek_ring[0].value[2] = 0x02; - ek_ring[0].value[3] = 0x03; - ek_ring[0].value[4] = 0x04; - ek_ring[0].value[5] = 0x05; - ek_ring[0].value[6] = 0x06; - ek_ring[0].value[7] = 0x07; - ek_ring[0].value[8] = 0x08; - ek_ring[0].value[9] = 0x09; - ek_ring[0].value[10] = 0x0A; - ek_ring[0].value[11] = 0x0B; - ek_ring[0].value[12] = 0x0C; - ek_ring[0].value[13] = 0x0D; - ek_ring[0].value[14] = 0x0E; - ek_ring[0].value[15] = 0x0F; - ek_ring[0].value[16] = 0x00; - ek_ring[0].value[17] = 0x01; - ek_ring[0].value[18] = 0x02; - ek_ring[0].value[19] = 0x03; - ek_ring[0].value[20] = 0x04; - ek_ring[0].value[21] = 0x05; - ek_ring[0].value[22] = 0x06; - ek_ring[0].value[23] = 0x07; - ek_ring[0].value[24] = 0x08; - ek_ring[0].value[25] = 0x09; - ek_ring[0].value[26] = 0x0A; - ek_ring[0].value[27] = 0x0B; - ek_ring[0].value[28] = 0x0C; - ek_ring[0].value[29] = 0x0D; - ek_ring[0].value[30] = 0x0E; - ek_ring[0].value[31] = 0x0F; - ek_ring[0].key_state = KEY_ACTIVE; - // 1 - 101112131415161718191A1B1C1D1E1F101112131415161718191A1B1C1D1E1F -> ACTIVE - ek_ring[1].value[0] = 0x10; - ek_ring[1].value[1] = 0x11; - ek_ring[1].value[2] = 0x12; - ek_ring[1].value[3] = 0x13; - ek_ring[1].value[4] = 0x14; - ek_ring[1].value[5] = 0x15; - ek_ring[1].value[6] = 0x16; - ek_ring[1].value[7] = 0x17; - ek_ring[1].value[8] = 0x18; - ek_ring[1].value[9] = 0x19; - ek_ring[1].value[10] = 0x1A; - ek_ring[1].value[11] = 0x1B; - ek_ring[1].value[12] = 0x1C; - ek_ring[1].value[13] = 0x1D; - ek_ring[1].value[14] = 0x1E; - ek_ring[1].value[15] = 0x1F; - ek_ring[1].value[16] = 0x10; - ek_ring[1].value[17] = 0x11; - ek_ring[1].value[18] = 0x12; - ek_ring[1].value[19] = 0x13; - ek_ring[1].value[20] = 0x14; - ek_ring[1].value[21] = 0x15; - ek_ring[1].value[22] = 0x16; - ek_ring[1].value[23] = 0x17; - ek_ring[1].value[24] = 0x18; - ek_ring[1].value[25] = 0x19; - ek_ring[1].value[26] = 0x1A; - ek_ring[1].value[27] = 0x1B; - ek_ring[1].value[28] = 0x1C; - ek_ring[1].value[29] = 0x1D; - ek_ring[1].value[30] = 0x1E; - ek_ring[1].value[31] = 0x1F; - ek_ring[1].key_state = KEY_ACTIVE; - // 2 - 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F -> ACTIVE - ek_ring[2].value[0] = 0x20; - ek_ring[2].value[1] = 0x21; - ek_ring[2].value[2] = 0x22; - ek_ring[2].value[3] = 0x23; - ek_ring[2].value[4] = 0x24; - ek_ring[2].value[5] = 0x25; - ek_ring[2].value[6] = 0x26; - ek_ring[2].value[7] = 0x27; - ek_ring[2].value[8] = 0x28; - ek_ring[2].value[9] = 0x29; - ek_ring[2].value[10] = 0x2A; - ek_ring[2].value[11] = 0x2B; - ek_ring[2].value[12] = 0x2C; - ek_ring[2].value[13] = 0x2D; - ek_ring[2].value[14] = 0x2E; - ek_ring[2].value[15] = 0x2F; - ek_ring[2].value[16] = 0x20; - ek_ring[2].value[17] = 0x21; - ek_ring[2].value[18] = 0x22; - ek_ring[2].value[19] = 0x23; - ek_ring[2].value[20] = 0x24; - ek_ring[2].value[21] = 0x25; - ek_ring[2].value[22] = 0x26; - ek_ring[2].value[23] = 0x27; - ek_ring[2].value[24] = 0x28; - ek_ring[2].value[25] = 0x29; - ek_ring[2].value[26] = 0x2A; - ek_ring[2].value[27] = 0x2B; - ek_ring[2].value[28] = 0x2C; - ek_ring[2].value[29] = 0x2D; - ek_ring[2].value[30] = 0x2E; - ek_ring[2].value[31] = 0x2F; - ek_ring[2].key_state = KEY_ACTIVE; - - // Session Keys - // 128 - 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -> ACTIVE - ek_ring[128].value[0] = 0x01; - ek_ring[128].value[1] = 0x23; - ek_ring[128].value[2] = 0x45; - ek_ring[128].value[3] = 0x67; - ek_ring[128].value[4] = 0x89; - ek_ring[128].value[5] = 0xAB; - ek_ring[128].value[6] = 0xCD; - ek_ring[128].value[7] = 0xEF; - ek_ring[128].value[8] = 0x01; - ek_ring[128].value[9] = 0x23; - ek_ring[128].value[10] = 0x45; - ek_ring[128].value[11] = 0x67; - ek_ring[128].value[12] = 0x89; - ek_ring[128].value[13] = 0xAB; - ek_ring[128].value[14] = 0xCD; - ek_ring[128].value[15] = 0xEF; - ek_ring[128].value[16] = 0x01; - ek_ring[128].value[17] = 0x23; - ek_ring[128].value[18] = 0x45; - ek_ring[128].value[19] = 0x67; - ek_ring[128].value[20] = 0x89; - ek_ring[128].value[21] = 0xAB; - ek_ring[128].value[22] = 0xCD; - ek_ring[128].value[23] = 0xEF; - ek_ring[128].value[24] = 0x01; - ek_ring[128].value[25] = 0x23; - ek_ring[128].value[26] = 0x45; - ek_ring[128].value[27] = 0x67; - ek_ring[128].value[28] = 0x89; - ek_ring[128].value[29] = 0xAB; - ek_ring[128].value[30] = 0xCD; - ek_ring[128].value[31] = 0xEF; - ek_ring[128].key_state = KEY_ACTIVE; - // 129 - ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 -> ACTIVE - ek_ring[129].value[0] = 0xAB; - ek_ring[129].value[1] = 0xCD; - ek_ring[129].value[2] = 0xEF; - ek_ring[129].value[3] = 0x01; - ek_ring[129].value[4] = 0x23; - ek_ring[129].value[5] = 0x45; - ek_ring[129].value[6] = 0x67; - ek_ring[129].value[7] = 0x89; - ek_ring[129].value[8] = 0xAB; - ek_ring[129].value[9] = 0xCD; - ek_ring[129].value[10] = 0xEF; - ek_ring[129].value[11] = 0x01; - ek_ring[129].value[12] = 0x23; - ek_ring[129].value[13] = 0x45; - ek_ring[129].value[14] = 0x67; - ek_ring[129].value[15] = 0x89; - ek_ring[129].value[16] = 0xAB; - ek_ring[129].value[17] = 0xCD; - ek_ring[129].value[18] = 0xEF; - ek_ring[129].value[19] = 0x01; - ek_ring[129].value[20] = 0x23; - ek_ring[129].value[21] = 0x45; - ek_ring[129].value[22] = 0x67; - ek_ring[129].value[23] = 0x89; - ek_ring[129].value[24] = 0xAB; - ek_ring[129].value[25] = 0xCD; - ek_ring[129].value[26] = 0xEF; - ek_ring[129].value[27] = 0x01; - ek_ring[129].value[28] = 0x23; - ek_ring[129].value[29] = 0x45; - ek_ring[129].value[30] = 0x67; - ek_ring[129].value[31] = 0x89; - ek_ring[129].key_state = KEY_ACTIVE; - // 130 - FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210 -> ACTIVE - ek_ring[130].value[0] = 0xFE; - ek_ring[130].value[1] = 0xDC; - ek_ring[130].value[2] = 0xBA; - ek_ring[130].value[3] = 0x98; - ek_ring[130].value[4] = 0x76; - ek_ring[130].value[5] = 0x54; - ek_ring[130].value[6] = 0x32; - ek_ring[130].value[7] = 0x10; - ek_ring[130].value[8] = 0xFE; - ek_ring[130].value[9] = 0xDC; - ek_ring[130].value[10] = 0xBA; - ek_ring[130].value[11] = 0x98; - ek_ring[130].value[12] = 0x76; - ek_ring[130].value[13] = 0x54; - ek_ring[130].value[14] = 0x32; - ek_ring[130].value[15] = 0x10; - ek_ring[130].value[16] = 0xFE; - ek_ring[130].value[17] = 0xDC; - ek_ring[130].value[18] = 0xBA; - ek_ring[130].value[19] = 0x98; - ek_ring[130].value[20] = 0x76; - ek_ring[130].value[21] = 0x54; - ek_ring[130].value[22] = 0x32; - ek_ring[130].value[23] = 0x10; - ek_ring[130].value[24] = 0xFE; - ek_ring[130].value[25] = 0xDC; - ek_ring[130].value[26] = 0xBA; - ek_ring[130].value[27] = 0x98; - ek_ring[130].value[28] = 0x76; - ek_ring[130].value[29] = 0x54; - ek_ring[130].value[30] = 0x32; - ek_ring[130].value[31] = 0x10; - ek_ring[130].key_state = KEY_ACTIVE; - // 131 - 9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA -> ACTIVE - ek_ring[131].value[0] = 0x98; - ek_ring[131].value[1] = 0x76; - ek_ring[131].value[2] = 0x54; - ek_ring[131].value[3] = 0x32; - ek_ring[131].value[4] = 0x10; - ek_ring[131].value[5] = 0xFE; - ek_ring[131].value[6] = 0xDC; - ek_ring[131].value[7] = 0xBA; - ek_ring[131].value[8] = 0x98; - ek_ring[131].value[9] = 0x76; - ek_ring[131].value[10] = 0x54; - ek_ring[131].value[11] = 0x32; - ek_ring[131].value[12] = 0x10; - ek_ring[131].value[13] = 0xFE; - ek_ring[131].value[14] = 0xDC; - ek_ring[131].value[15] = 0xBA; - ek_ring[131].value[16] = 0x98; - ek_ring[131].value[17] = 0x76; - ek_ring[131].value[18] = 0x54; - ek_ring[131].value[19] = 0x32; - ek_ring[131].value[20] = 0x10; - ek_ring[131].value[21] = 0xFE; - ek_ring[131].value[22] = 0xDC; - ek_ring[131].value[23] = 0xBA; - ek_ring[131].value[24] = 0x98; - ek_ring[131].value[25] = 0x76; - ek_ring[131].value[26] = 0x54; - ek_ring[131].value[27] = 0x32; - ek_ring[131].value[28] = 0x10; - ek_ring[131].value[29] = 0xFE; - ek_ring[131].value[30] = 0xDC; - ek_ring[131].value[31] = 0xBA; - ek_ring[131].key_state = KEY_ACTIVE; - // 132 - 0123456789ABCDEFABCDEF01234567890123456789ABCDEFABCDEF0123456789 -> PRE_ACTIVATION - ek_ring[132].value[0] = 0x01; - ek_ring[132].value[1] = 0x23; - ek_ring[132].value[2] = 0x45; - ek_ring[132].value[3] = 0x67; - ek_ring[132].value[4] = 0x89; - ek_ring[132].value[5] = 0xAB; - ek_ring[132].value[6] = 0xCD; - ek_ring[132].value[7] = 0xEF; - ek_ring[132].value[8] = 0xAB; - ek_ring[132].value[9] = 0xCD; - ek_ring[132].value[10] = 0xEF; - ek_ring[132].value[11] = 0x01; - ek_ring[132].value[12] = 0x23; - ek_ring[132].value[13] = 0x45; - ek_ring[132].value[14] = 0x67; - ek_ring[132].value[15] = 0x89; - ek_ring[132].value[16] = 0x01; - ek_ring[132].value[17] = 0x23; - ek_ring[132].value[18] = 0x45; - ek_ring[132].value[19] = 0x67; - ek_ring[132].value[20] = 0x89; - ek_ring[132].value[21] = 0xAB; - ek_ring[132].value[22] = 0xCD; - ek_ring[132].value[23] = 0xEF; - ek_ring[132].value[24] = 0xAB; - ek_ring[132].value[25] = 0xCD; - ek_ring[132].value[26] = 0xEF; - ek_ring[132].value[27] = 0x01; - ek_ring[132].value[28] = 0x23; - ek_ring[132].value[29] = 0x45; - ek_ring[132].value[30] = 0x67; - ek_ring[132].value[31] = 0x89; - ek_ring[132].key_state = KEY_PREACTIVE; - // 133 - ABCDEF01234567890123456789ABCDEFABCDEF01234567890123456789ABCDEF -> ACTIVE - ek_ring[133].value[0] = 0xAB; - ek_ring[133].value[1] = 0xCD; - ek_ring[133].value[2] = 0xEF; - ek_ring[133].value[3] = 0x01; - ek_ring[133].value[4] = 0x23; - ek_ring[133].value[5] = 0x45; - ek_ring[133].value[6] = 0x67; - ek_ring[133].value[7] = 0x89; - ek_ring[133].value[8] = 0x01; - ek_ring[133].value[9] = 0x23; - ek_ring[133].value[10] = 0x45; - ek_ring[133].value[11] = 0x67; - ek_ring[133].value[12] = 0x89; - ek_ring[133].value[13] = 0xAB; - ek_ring[133].value[14] = 0xCD; - ek_ring[133].value[15] = 0xEF; - ek_ring[133].value[16] = 0xAB; - ek_ring[133].value[17] = 0xCD; - ek_ring[133].value[18] = 0xEF; - ek_ring[133].value[19] = 0x01; - ek_ring[133].value[20] = 0x23; - ek_ring[133].value[21] = 0x45; - ek_ring[133].value[22] = 0x67; - ek_ring[133].value[23] = 0x89; - ek_ring[133].value[24] = 0x01; - ek_ring[133].value[25] = 0x23; - ek_ring[133].value[26] = 0x45; - ek_ring[133].value[27] = 0x67; - ek_ring[133].value[28] = 0x89; - ek_ring[133].value[29] = 0xAB; - ek_ring[133].value[30] = 0xCD; - ek_ring[133].value[31] = 0xEF; - ek_ring[133].key_state = KEY_ACTIVE; - // 134 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE - ek_ring[134].value[0] = 0xAB; - ek_ring[134].value[1] = 0xCD; - ek_ring[134].value[2] = 0xEF; - ek_ring[134].value[3] = 0x01; - ek_ring[134].value[4] = 0x23; - ek_ring[134].value[5] = 0x45; - ek_ring[134].value[6] = 0x67; - ek_ring[134].value[7] = 0x89; - ek_ring[134].value[8] = 0xFE; - ek_ring[134].value[9] = 0xDC; - ek_ring[134].value[10] = 0xBA; - ek_ring[134].value[11] = 0x98; - ek_ring[134].value[12] = 0x76; - ek_ring[134].value[13] = 0x54; - ek_ring[134].value[14] = 0x32; - ek_ring[134].value[15] = 0x10; - ek_ring[134].value[16] = 0xAB; - ek_ring[134].value[17] = 0xCD; - ek_ring[134].value[18] = 0xEF; - ek_ring[134].value[19] = 0x01; - ek_ring[134].value[20] = 0x23; - ek_ring[134].value[21] = 0x45; - ek_ring[134].value[22] = 0x67; - ek_ring[134].value[23] = 0x89; - ek_ring[134].value[24] = 0xFE; - ek_ring[134].value[25] = 0xDC; - ek_ring[134].value[26] = 0xBA; - ek_ring[134].value[27] = 0x98; - ek_ring[134].value[28] = 0x76; - ek_ring[134].value[29] = 0x54; - ek_ring[134].value[30] = 0x32; - ek_ring[134].value[31] = 0x10; - ek_ring[134].key_state = KEY_DEACTIVATED; -} - -static void Crypto_Local_Init(void) -{ - - // Initialize TM Frame - // TM Header - tm_frame.tm_header.tfvn = 0; // Shall be 00 for TM-/TC-SDLP - tm_frame.tm_header.scid = SCID & 0x3FF; - tm_frame.tm_header.vcid = 0; - tm_frame.tm_header.ocff = 1; - tm_frame.tm_header.mcfc = 1; - tm_frame.tm_header.vcfc = 1; - tm_frame.tm_header.tfsh = 0; - tm_frame.tm_header.sf = 0; - tm_frame.tm_header.pof = 0; // Shall be set to 0 - tm_frame.tm_header.slid = 3; // Shall be set to 11 - tm_frame.tm_header.fhp = 0; - // TM Security Header - tm_frame.tm_sec_header.spi = 0x0000; - for ( int x = 0; x < IV_SIZE; x++) - { // Initialization Vector - tm_frame.tm_sec_header.iv[x] = 0x00; - } - // TM Payload Data Unit - for ( int x = 0; x < TM_FRAME_DATA_SIZE; x++) - { // Zero TM PDU - tm_frame.tm_pdu[x] = 0x00; - } - // TM Security Trailer - for ( int x = 0; x < MAC_SIZE; x++) - { // Zero TM Message Authentication Code - tm_frame.tm_sec_trailer.mac[x] = 0x00; - } - for ( int x = 0; x < OCF_SIZE; x++) - { // Zero TM Operational Control Field - tm_frame.tm_sec_trailer.ocf[x] = 0x00; - } - tm_frame.tm_sec_trailer.fecf = 0xFECF; - - // Initialize CLCW - clcw.cwt = 0; // Control Word Type "0" - clcw.cvn = 0; // CLCW Version Number "00" - clcw.sf = 0; // Status Field - clcw.cie = 1; // COP In Effect - clcw.vci = 0; // Virtual Channel Identification - clcw.spare0 = 0; // Reserved Spare - clcw.nrfa = 0; // No RF Avaliable Flag - clcw.nbl = 0; // No Bit Lock Flag - clcw.lo = 0; // Lock-Out Flag - clcw.wait = 0; // Wait Flag - clcw.rt = 0; // Retransmit Flag - clcw.fbc = 0; // FARM-B Counter - clcw.spare1 = 0; // Reserved Spare - clcw.rv = 0; // Report Value - - // Initialize Frame Security Report - report.cwt = 1; // Control Word Type "0b1"" - report.vnum = 4; // FSR Version "0b100"" - report.af = 0; // Alarm Field - report.bsnf = 0; // Bad SN Flag - report.bmacf = 0; // Bad MAC Flag - report.ispif = 0; // Invalid SPI Flag - report.lspiu = 0; // Last SPI Used - report.snval = 0; // SN Value (LSB) - -} - -static void Crypto_Calc_CRC_Init_Table(void) -{ - uint16 val; - uint32 poly = 0xEDB88320; - uint32 crc; - - // http://create.stephan-brumme.com/crc32/ - for (unsigned int i = 0; i <= 0xFF; i++) - { - crc = i; - for (unsigned int j = 0; j < 8; j++) - { - crc = (crc >> 1) ^ (-(int)(crc & 1) & poly); - } - crc32Table[i] = crc; - //OS_printf("crc32Table[%d] = 0x%08x \n", i, crc32Table[i]); - } - - // Code provided by ESA - for (int i = 0; i < 256; i++) - { - val = 0; - if ( (i & 1) != 0 ) val ^= 0x1021; - if ( (i & 2) != 0 ) val ^= 0x2042; - if ( (i & 4) != 0 ) val ^= 0x4084; - if ( (i & 8) != 0 ) val ^= 0x8108; - if ( (i & 16) != 0 ) val ^= 0x1231; - if ( (i & 32) != 0 ) val ^= 0x2462; - if ( (i & 64) != 0 ) val ^= 0x48C4; - if ( (i & 128) != 0 ) val ^= 0x9188; - crc16Table[i] = val; - //OS_printf("crc16Table[%d] = 0x%04x \n", i, crc16Table[i]); - } -} - -/* -** Assisting Functions -*/ -static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame) -// Returns the payload length of current tc_frame in BYTES! -{ - int seg_hdr = 0;if(SEGMENTATION_HDR){seg_hdr=1;} - int fecf = 0;if(HAS_FECF){fecf=FECF_SIZE;} - int spi = 2; - int iv_size = IV_SIZE_TC; if(PUS_HDR){iv_size=IV_SIZE - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. - int tf_hdr = 5; - - return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (MAC_SIZE + FECF_SIZE) ); - //return (tc_frame->tc_header.fl - (5 + 2 + IV_SIZE ) - (MAC_SIZE + FECF_SIZE) ); - //TFHDR=5bytes, SegHdr=1byte,SPI=2bytes,SeqNum=4bytes,MAC=16bytes,FECF=2bytes -- should be 30 bytes max, above calculation seems incorrect. -} - -static int32 Crypto_Get_tmLength(int len) -// Returns the total length of the current tm_frame in BYTES! -{ - #ifdef FILL - len = TM_FILL_SIZE; - #else - len = TM_FRAME_PRIMARYHEADER_SIZE + TM_FRAME_SECHEADER_SIZE + len + TM_FRAME_SECTRAILER_SIZE + TM_FRAME_CLCW_SIZE; - #endif - - return len; -} - -static void Crypto_TM_updatePDU(char* ingest, int len_ingest) -// Update the Telemetry Payload Data Unit -{ // Copy ingest to PDU - int x = 0; - int fill_size = 0; - SecurityAssociation_t* sa_ptr; - - if(sadb_routine->sadb_get_sa_from_spi(tm_frame.tm_sec_header.spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - return; //Error -- unable to get SA from SPI. - } - - if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) - { - fill_size = 1129 - MAC_SIZE - IV_SIZE + 2; // +2 for padding bytes - } - else - { - fill_size = 1129; - } - - #ifdef TM_ZERO_FILL - for (int x = 0; x < TM_FILL_SIZE; x++) - { - if (x < len_ingest) - { // Fill - tm_frame.tm_pdu[x] = (uint8)ingest[x]; - } - else - { // Zero - tm_frame.tm_pdu[x] = 0x00; - } - } - #else - // Pre-append remaining packet if exist - if (tm_offset == 63) - { - tm_frame.tm_pdu[x++] = 0xff; - tm_offset--; - } - if (tm_offset == 62) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (tm_offset == 61) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (tm_offset == 60) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (tm_offset == 59) - { - tm_frame.tm_pdu[x++] = 0x39; - tm_offset--; - } - while (x < tm_offset) - { - tm_frame.tm_pdu[x] = 0x00; - x++; - } - // Copy actual packet - while (x < len_ingest + tm_offset) - { - //OS_printf("ingest[x - tm_offset] = 0x%02x \n", (uint8)ingest[x - tm_offset]); - tm_frame.tm_pdu[x] = (uint8)ingest[x - tm_offset]; - x++; - } - #ifdef TM_IDLE_FILL - // Check for idle frame trigger - if (((uint8)ingest[0] == 0x08) && ((uint8)ingest[1] == 0x90)) - { - // Don't fill idle frames - } - else - { - while (x < (fill_size - 64) ) - { - tm_frame.tm_pdu[x++] = 0x07; - tm_frame.tm_pdu[x++] = 0xff; - tm_frame.tm_pdu[x++] = 0x00; - tm_frame.tm_pdu[x++] = 0x00; - tm_frame.tm_pdu[x++] = 0x00; - tm_frame.tm_pdu[x++] = 0x39; - for (int y = 0; y < 58; y++) - { - tm_frame.tm_pdu[x++] = 0x00; - } - } - // Add partial packet, if possible, and set offset - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x07; - tm_offset = 63; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0xff; - tm_offset--; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x39; - tm_offset--; - } - for (int y = 0; x < fill_size; y++) - { - tm_frame.tm_pdu[x++] = 00; - tm_offset--; - } - } - while (x < TM_FILL_SIZE) - { - tm_frame.tm_pdu[x++] = 0x00; - } - #endif - #endif - - return; -} - -static void Crypto_TM_updateOCF(void) -{ - if (ocf == 0) - { // CLCW - clcw.vci = tm_frame.tm_header.vcid; - - tm_frame.tm_sec_trailer.ocf[0] = (clcw.cwt << 7) | (clcw.cvn << 5) | (clcw.sf << 2) | (clcw.cie); - tm_frame.tm_sec_trailer.ocf[1] = (clcw.vci << 2) | (clcw.spare0); - tm_frame.tm_sec_trailer.ocf[2] = (clcw.nrfa << 7) | (clcw.nbl << 6) | (clcw.lo << 5) | (clcw.wait << 4) | (clcw.rt << 3) | (clcw.fbc << 1) | (clcw.spare1); - tm_frame.tm_sec_trailer.ocf[3] = (clcw.rv); - // Alternate OCF - ocf = 1; - #ifdef OCF_DEBUG - Crypto_clcwPrint(&clcw); - #endif - } - else - { // FSR - tm_frame.tm_sec_trailer.ocf[0] = (report.cwt << 7) | (report.vnum << 4) | (report.af << 3) | (report.bsnf << 2) | (report.bmacf << 1) | (report.ispif); - tm_frame.tm_sec_trailer.ocf[1] = (report.lspiu & 0xFF00) >> 8; - tm_frame.tm_sec_trailer.ocf[2] = (report.lspiu & 0x00FF); - tm_frame.tm_sec_trailer.ocf[3] = (report.snval); - // Alternate OCF - ocf = 0; - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - } -} - -//TODO - Review this. Not sure it quite works how we think -int32 Crypto_increment(uint8 *num, int length) -{ - int i; - /* go from right (least significant) to left (most signifcant) */ - for(i = length - 1; i >= 0; --i) - { - ++(num[i]); /* increment current byte */ - - if(num[i] != 0) /* if byte did not overflow, we're done! */ - break; - } - - if(i < 0) /* this means num[0] was incremented and overflowed */ - return OS_ERROR; - else - return OS_SUCCESS; -} - -static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window) -{ - int status = OS_ERROR; - int result = 0; - uint8 temp[length]; - - CFE_PSP_MemCpy(temp, expected, length); - - for (int i = 0; i < window; i++) - { - result = 0; - /* go from right (least significant) to left (most signifcant) */ - for (int j = length - 1; j >= 0; --j) - { - if (actual[j] == temp[j]) - { - result++; - } - } - if (result == length) - { - status = OS_SUCCESS; - break; - } - Crypto_increment(&temp[0], length); - } - return status; -} - -static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length) -{ - int status = OS_ERROR; - - for(int i = 0; i < length - 1; i++) - { - if (actual[i] > expected[i]) - { - status = OS_SUCCESS; - break; - } - else if (actual[i] < expected[i]) - { - status = OS_ERROR; - break; - } - } - return status; -} - -uint8 Crypto_Prep_Reply(char* ingest, uint8 appID) -// Assumes that both the pkt_length and pdu_len are set properly -{ - uint8 count = 0; - - // Prepare CCSDS for reply - sdls_frame.hdr.pvn = 0; - sdls_frame.hdr.type = 0; - sdls_frame.hdr.shdr = 1; - sdls_frame.hdr.appID = appID; - - sdls_frame.pdu.type = 1; - - // Fill ingest with reply header - ingest[count++] = (sdls_frame.hdr.pvn << 5) | (sdls_frame.hdr.type << 4) | (sdls_frame.hdr.shdr << 3) | ((sdls_frame.hdr.appID & 0x700 >> 8)); - ingest[count++] = (sdls_frame.hdr.appID & 0x00FF); - ingest[count++] = (sdls_frame.hdr.seq << 6) | ((sdls_frame.hdr.pktid & 0x3F00) >> 8); - ingest[count++] = (sdls_frame.hdr.pktid & 0x00FF); - ingest[count++] = (sdls_frame.hdr.pkt_length & 0xFF00) >> 8; - ingest[count++] = (sdls_frame.hdr.pkt_length & 0x00FF); - - // Fill ingest with PUS - //ingest[count++] = (sdls_frame.pus.shf << 7) | (sdls_frame.pus.pusv << 4) | (sdls_frame.pus.ack); - //ingest[count++] = (sdls_frame.pus.st); - //ingest[count++] = (sdls_frame.pus.sst); - //ingest[count++] = (sdls_frame.pus.sid << 4) | (sdls_frame.pus.spare); - - // Fill ingest with Tag and Length - ingest[count++] = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | (sdls_frame.pdu.pid); - ingest[count++] = (sdls_frame.pdu.pdu_len & 0xFF00) >> 8; - ingest[count++] = (sdls_frame.pdu.pdu_len & 0x00FF); - - return count; -} - -static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame) -// Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) -{ - int32 result = OS_SUCCESS; - uint16 calc_fecf = Crypto_Calc_FECF(ingest, len_ingest); - - if ( (fecf & 0xFFFF) != calc_fecf ) - { - if (((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) - { - // User packet check only used for ESA Testing! - } - else - { // TODO: Error Correction - OS_printf(KRED "Error: FECF incorrect!\n" RESET); - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = FECF_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - #ifdef FECF_DEBUG - OS_printf("\t Calculated = 0x%04x \n\t Received = 0x%04x \n", calc_fecf, tc_frame->tc_sec_trailer.fecf); - #endif - result = OS_ERROR; - } - } - - return result; -} - -static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest) -// Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) -{ - uint16 fecf = 0xFFFF; - uint16 poly = 0x1021; // TODO: This polynomial is (CRC-CCITT) for ESA testing, may not match standard protocol - uint8 bit; - uint8 c15; - - for (int i = 0; i <= len_ingest; i++) - { // Byte Logic - for (int j = 0; j < 8; j++) - { // Bit Logic - bit = ((ingest[i] >> (7 - j) & 1) == 1); - c15 = ((fecf >> 15 & 1) == 1); - fecf <<= 1; - if (c15 ^ bit) - { - fecf ^= poly; - } - } - } - - // Check if Testing - if (badFECF == 1) - { - fecf++; - } - - #ifdef FECF_DEBUG - OS_printf(KCYN "Crypto_Calc_FECF: 0x%02x%02x%02x%02x%02x, len_ingest = %d\n" RESET, ingest[0], ingest[1], ingest[2], ingest[3], ingest[4], len_ingest); - OS_printf(KCYN "0x" RESET); - for (int x = 0; x < len_ingest; x++) - { - OS_printf(KCYN "%02x" RESET, (uint8)*(ingest+x)); - } - OS_printf(KCYN "\n" RESET); - OS_printf(KCYN "In Crypto_Calc_FECF! fecf = 0x%04x\n" RESET, fecf); - #endif - - return fecf; -} - -static uint16 Crypto_Calc_CRC16(char* data, int size) -{ // Code provided by ESA - uint16 crc = 0xFFFF; - - for ( ; size > 0; size--) - { - //OS_printf("*data = 0x%02x \n", (uint8) *data); - crc = ((crc << 8) & 0xFF00) ^ crc16Table[(crc >> 8) ^ *data++]; - } - - return crc; -} - -/* -** Key Management Services -*/ -static int32 Crypto_Key_OTAR(void) -// The OTAR Rekeying procedure shall have the following Service Parameters: -// a- Key ID of the Master Key (Integer, unmanaged) -// b- Size of set of Upload Keys (Integer, managed) -// c- Set of Upload Keys (Integer[Session Key]; managed) -// NOTE- The size of the session keys is mission specific. -// a- Set of Key IDs of Upload Keys (Integer[Key IDs]; managed) -// b- Set of Encrypted Upload Keys (Integer[Size of set of Key ID]; unmanaged) -// c- Agreed Cryptographic Algorithm (managed) -{ - // Local variables - SDLS_OTAR_t packet; - int count = 0; - int x = 0; - int32 status = OS_SUCCESS; - int pdu_keys = (sdls_frame.pdu.pdu_len - 30) / (2 + KEY_SIZE); - - gcry_cipher_hd_t tmp_hd; - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - - // Master Key ID - packet.mkid = (sdls_frame.pdu.data[0] << 8) | (sdls_frame.pdu.data[1]); - - if (packet.mkid >= 128) - { - report.af = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = MKID_INVALID_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: MKID is not valid! \n" RESET); - status = OS_ERROR; - return status; - } - - for (int count = 2; count < (2 + IV_SIZE); count++) - { // Initialization Vector - packet.iv[count-2] = sdls_frame.pdu.data[count]; - //OS_printf("packet.iv[%d] = 0x%02x\n", count-2, packet.iv[count-2]); - } - - count = sdls_frame.pdu.pdu_len - MAC_SIZE; - for (int w = 0; w < 16; w++) - { // MAC - packet.mac[w] = sdls_frame.pdu.data[count + w]; - //OS_printf("packet.mac[%d] = 0x%02x\n", w, packet.mac[w]); - } - - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[packet.mkid].value[0]), - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(packet.iv[0]), - IV_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_decrypt( - tmp_hd, - &(sdls_frame.pdu.data[14]), // plaintext output - pdu_keys * (2 + KEY_SIZE), // length of data - NULL, // in place decryption - 0 // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_checktag( - tmp_hd, - &(packet.mac[0]), // tag input - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_cipher_close(tmp_hd); - - // Read in Decrypted Data - for (int count = 14; x < pdu_keys; x++) - { // Encrypted Key Blocks - packet.EKB[x].ekid = (sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1]); - if (packet.EKB[x].ekid < 128) - { - report.af = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = OTAR_MK_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; // N - log.blk[log_count].emv[1] = 0x41; // A - log.blk[log_count].emv[2] = 0x53; // S - log.blk[log_count].emv[3] = 0x41; // A - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: Cannot OTAR master key! \n" RESET); - status = OS_ERROR; - return status; - } - else - { - count = count + 2; - for (int y = count; y < (KEY_SIZE + count); y++) - { // Encrypted Key - packet.EKB[x].ek[y-count] = sdls_frame.pdu.data[y]; - #ifdef SA_DEBUG - OS_printf("\t packet.EKB[%d].ek[%d] = 0x%02x\n", x, y-count, packet.EKB[x].ek[y-count]); - #endif - - // Setup Key Ring - ek_ring[packet.EKB[x].ekid].value[y - count] = sdls_frame.pdu.data[y]; - } - count = count + KEY_SIZE; - - // Set state to PREACTIVE - ek_ring[packet.EKB[x].ekid].key_state = KEY_PREACTIVE; - } - } - - #ifdef PDU_DEBUG - OS_printf("Received %d keys via master key %d: \n", pdu_keys, packet.mkid); - for (int x = 0; x < pdu_keys; x++) - { - OS_printf("%d) Key ID = %d, 0x", x+1, packet.EKB[x].ekid); - for(int y = 0; y < KEY_SIZE; y++) - { - OS_printf("%02x", packet.EKB[x].ek[y]); - } - OS_printf("\n"); - } - #endif - - return OS_SUCCESS; -} - -static int32 Crypto_Key_update(uint8 state) -// Updates the state of the all keys in the received SDLS EP PDU -{ // Local variables - SDLS_KEY_BLK_t packet; - int count = 0; - int pdu_keys = sdls_frame.pdu.pdu_len / 2; - #ifdef PDU_DEBUG - OS_printf("Keys "); - #endif - // Read in PDU - for (int x = 0; x < pdu_keys; x++) - { - packet.kblk[x].kid = (sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1]); - count = count + 2; - #ifdef PDU_DEBUG - if (x != (pdu_keys - 1)) - { - OS_printf("%d, ", packet.kblk[x].kid); - } - else - { - OS_printf("and %d ", packet.kblk[x].kid); - } - #endif - } - #ifdef PDU_DEBUG - OS_printf("changed to state "); - switch (state) - { - case KEY_PREACTIVE: - OS_printf("PREACTIVE. \n"); - break; - case KEY_ACTIVE: - OS_printf("ACTIVE. \n"); - break; - case KEY_DEACTIVATED: - OS_printf("DEACTIVATED. \n"); - break; - case KEY_DESTROYED: - OS_printf("DESTROYED. \n"); - break; - case KEY_CORRUPTED: - OS_printf("CORRUPTED. \n"); - break; - default: - OS_printf("ERROR. \n"); - break; - } - #endif - // Update Key State - for (int x = 0; x < pdu_keys; x++) - { - if (packet.kblk[x].kid < 128) - { - report.af = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = MKID_STATE_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: MKID state cannot be changed! \n" RESET); - // TODO: Exit - } - - if (ek_ring[packet.kblk[x].kid].key_state == (state - 1)) - { - ek_ring[packet.kblk[x].kid].key_state = state; - #ifdef PDU_DEBUG - //OS_printf("Key ID %d state changed to ", packet.kblk[x].kid); - #endif - } - else - { - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = KEY_TRANSITION_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: Key %d cannot transition to desired state! \n" RESET, packet.kblk[x].kid); - } - } - return OS_SUCCESS; -} - -static int32 Crypto_Key_inventory(char* ingest) -{ - // Local variables - SDLS_KEY_INVENTORY_t packet; - int count = 0; - uint16_t range = 0; - - // Read in PDU - packet.kid_first = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); - count = count + 2; - packet.kid_last = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); - count = count + 2; - - // Prepare for Reply - range = packet.kid_last - packet.kid_first; - sdls_frame.pdu.pdu_len = 2 + (range * (2 + 1)); - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - ingest[count++] = (range & 0xFF00) >> 8; - ingest[count++] = (range & 0x00FF); - for (uint16_t x = packet.kid_first; x < packet.kid_last; x++) - { // Key ID - ingest[count++] = (x & 0xFF00) >> 8; - ingest[count++] = (x & 0x00FF); - // Key State - ingest[count++] = ek_ring[x].key_state; - } - return count; -} - -static int32 Crypto_Key_verify(char* ingest,TC_t* tc_frame) -{ - // Local variables - SDLS_KEYV_CMD_t packet; - int count = 0; - int pdu_keys = sdls_frame.pdu.pdu_len / SDLS_KEYV_CMD_BLK_SIZE; - - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - gcry_cipher_hd_t tmp_hd; - uint8 iv_loc; - - //uint8 tmp_mac[MAC_SIZE]; - - #ifdef PDU_DEBUG - OS_printf("Crypto_Key_verify: Requested %d key(s) to verify \n", pdu_keys); - #endif - - // Read in PDU - for (int x = 0; x < pdu_keys; x++) - { - // Key ID - packet.blk[x].kid = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); - count = count + 2; - #ifdef PDU_DEBUG - OS_printf("Crypto_Key_verify: Block %d Key ID is %d \n", x, packet.blk[x].kid); - #endif - // Key Challenge - for (int y = 0; y < CHALLENGE_SIZE; y++) - { - packet.blk[x].challenge[y] = sdls_frame.pdu.data[count++]; - } - #ifdef PDU_DEBUG - OS_printf("\n"); - #endif - } - - // Prepare for Reply - sdls_frame.pdu.pdu_len = pdu_keys * (2 + IV_SIZE + CHALLENGE_SIZE + CHALLENGE_MAC_SIZE); - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - for (int x = 0; x < pdu_keys; x++) - { // Key ID - ingest[count++] = (packet.blk[x].kid & 0xFF00) >> 8; - ingest[count++] = (packet.blk[x].kid & 0x00FF); - - // Initialization Vector - iv_loc = count; - for (int y = 0; y < IV_SIZE; y++) - { - ingest[count++] = tc_frame->tc_sec_header.iv[y]; - } - ingest[count-1] = ingest[count-1] + x + 1; - - // Encrypt challenge - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[packet.blk[x].kid].value[0]), - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(ingest[iv_loc]), - IV_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - gcry_error = gcry_cipher_encrypt( - tmp_hd, - &(ingest[count]), // ciphertext output - CHALLENGE_SIZE, // length of data - &(packet.blk[x].challenge[0]), // plaintext input - CHALLENGE_SIZE // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - count = count + CHALLENGE_SIZE; // Don't forget to increment count! - - gcry_error = gcry_cipher_gettag( - tmp_hd, - &(ingest[count]), // tag output - CHALLENGE_MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_gettag error code %d \n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - count = count + CHALLENGE_MAC_SIZE; // Don't forget to increment count! - - // Copy from tmp_mac into ingest - //for( int y = 0; y < CHALLENGE_MAC_SIZE; y++) - //{ - // ingest[count++] = tmp_mac[y]; - //} - gcry_cipher_close(tmp_hd); - } - - #ifdef PDU_DEBUG - OS_printf("Crypto_Key_verify: Response is %d bytes \n", count); - #endif - - return count; -} - -/* - -/* -** Security Association Monitoring and Control -*/ -static int32 Crypto_MC_ping(char* ingest) -{ - int count = 0; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 0; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - return count; -} - -static int32 Crypto_MC_status(char* ingest) -{ - int count = 0; - - // TODO: Update log_summary.rs; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 2; // 4 - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - // PDU - //ingest[count++] = (log_summary.num_se & 0xFF00) >> 8; - ingest[count++] = (log_summary.num_se & 0x00FF); - //ingest[count++] = (log_summary.rs & 0xFF00) >> 8; - ingest[count++] = (log_summary.rs & 0x00FF); - - #ifdef PDU_DEBUG - OS_printf("log_summary.num_se = 0x%02x \n",log_summary.num_se); - OS_printf("log_summary.rs = 0x%02x \n",log_summary.rs); - #endif - - return count; -} - -static int32 Crypto_MC_dump(char* ingest) -{ - int count = 0; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = (log_count * 6); // SDLS_MC_DUMP_RPLY_SIZE - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - // PDU - for (int x = 0; x < log_count; x++) - { - ingest[count++] = log.blk[x].emt; - //ingest[count++] = (log.blk[x].em_len & 0xFF00) >> 8; - ingest[count++] = (log.blk[x].em_len & 0x00FF); - for (int y = 0; y < EMV_SIZE; y++) - { - ingest[count++] = log.blk[x].emv[y]; - } - } - - #ifdef PDU_DEBUG - OS_printf("log_count = %d \n", log_count); - OS_printf("log_summary.num_se = 0x%02x \n",log_summary.num_se); - OS_printf("log_summary.rs = 0x%02x \n",log_summary.rs); - #endif - - return count; -} - -static int32 Crypto_MC_erase(char* ingest) -{ - int count = 0; - - // Zero Logs - for (int x = 0; x < LOG_SIZE; x++) - { - log.blk[x].emt = 0; - log.blk[x].em_len = 0; - for (int y = 0; y < EMV_SIZE; y++) - { - log.blk[x].emv[y] = 0; - } - } - - // Compute Summary - log_count = 0; - log_summary.num_se = 0; - log_summary.rs = LOG_SIZE; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 2; // 4 - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - // PDU - //ingest[count++] = (log_summary.num_se & 0xFF00) >> 8; - ingest[count++] = (log_summary.num_se & 0x00FF); - //ingest[count++] = (log_summary.rs & 0xFF00) >> 8; - ingest[count++] = (log_summary.rs & 0x00FF); - - return count; -} - -static int32 Crypto_MC_selftest(char* ingest) -{ - uint8 count = 0; - uint8 result = ST_OK; - - // TODO: Perform test - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 1; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - ingest[count++] = result; - - return count; -} - -static int32 Crypto_SA_readARSN(char* ingest) -{ - uint8 count = 0; - uint16 spi = 0x0000; - SecurityAssociation_t* sa_ptr; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 2 + IV_SIZE; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - // Write SPI to reply - ingest[count++] = (spi & 0xFF00) >> 8; - ingest[count++] = (spi & 0x00FF); - - - if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - return OS_ERROR; //Error -- unable to get SA from SPI. - } - - - if (sa_ptr->iv_len > 0) - { // Set IV - authenticated encryption - for (int x = 0; x < sa_ptr->iv_len - 1; x++) - { - ingest[count++] = sa_ptr->iv[x]; - } - - // TODO: Do we need this? - if (sa_ptr->iv[IV_SIZE - 1] > 0) - { // Adjust to report last received, not expected - ingest[count++] = sa_ptr->iv[IV_SIZE - 1] - 1; - } - else - { - ingest[count++] = sa_ptr->iv[IV_SIZE - 1]; - } - } - else - { - // TODO - } - - #ifdef PDU_DEBUG - OS_printf("spi = %d \n", spi); - if (sa_ptr->iv_len > 0) - { - OS_printf("ARSN = 0x"); - for (int x = 0; x < sa_ptr->iv_len; x++) - { - OS_printf("%02x", sa_ptr->iv[x]); - } - OS_printf("\n"); - } - #endif - - return count; -} - -static int32 Crypto_MC_resetalarm(void) -{ // Reset all alarm flags - report.af = 0; - report.bsnf = 0; - report.bmacf = 0; - report.ispif = 0; - return OS_SUCCESS; -} - -static int32 Crypto_User_IdleTrigger(char* ingest) -{ - uint8 count = 0; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 0; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 144); - - return count; -} - -static int32 Crypto_User_BadSPI(void) -{ - // Toggle Bad Sequence Number - if (badSPI == 0) - { - badSPI = 1; - } - else - { - badSPI = 0; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_BadMAC(void) -{ - // Toggle Bad MAC - if (badMAC == 0) - { - badMAC = 1; - } - else - { - badMAC = 0; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_BadIV(void) -{ - // Toggle Bad MAC - if (badIV == 0) - { - badIV = 1; - } - else - { - badIV = 0; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_BadFECF(void) -{ - // Toggle Bad FECF - if (badFECF == 0) - { - badFECF = 1; - } - else - { - badFECF = 0; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_ModifyKey(void) -{ - // Local variables - uint16 kid = ((uint8)sdls_frame.pdu.data[0] << 8) | ((uint8)sdls_frame.pdu.data[1]); - uint8 mod = (uint8)sdls_frame.pdu.data[2]; - - switch (mod) - { - case 1: // Invalidate Key - ek_ring[kid].value[KEY_SIZE-1]++; - OS_printf("Key %d value invalidated! \n", kid); - break; - case 2: // Modify key state - ek_ring[kid].key_state = (uint8)sdls_frame.pdu.data[3] & 0x0F; - OS_printf("Key %d state changed to %d! \n", kid, mod); - break; - default: - // Error - break; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_ModifyActiveTM(void) -{ - tm_frame.tm_sec_header.spi = (uint8)sdls_frame.pdu.data[0]; - return OS_SUCCESS; -} - -static int32 Crypto_User_ModifyVCID(void) -{ - tm_frame.tm_header.vcid = (uint8)sdls_frame.pdu.data[0]; - SecurityAssociation_t* sa_ptr; - - for (int i = 0; i < NUM_GVCID; i++) - { - if(sadb_routine->sadb_get_sa_from_spi(i,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - return OS_ERROR; //Error -- unable to get SA from SPI. - } - for (int j = 0; j < NUM_SA; j++) - { - - if (sa_ptr->gvcid_tm_blk[j].mapid == TYPE_TM) - { - if (sa_ptr->gvcid_tm_blk[j].vcid == tm_frame.tm_header.vcid) - { - tm_frame.tm_sec_header.spi = i; - OS_printf("TM Frame SPI changed to %d \n",i); - break; - } - } - } - } - - return OS_SUCCESS; -} - -/* -** Procedures Specifications -*/ -static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) -{ - int32 status = OS_SUCCESS; - - switch (sdls_frame.pdu.type) - { - case 0: // Command - switch (sdls_frame.pdu.uf) - { - case 0: // CCSDS Defined Command - switch (sdls_frame.pdu.sg) - { - case SG_KEY_MGMT: // Key Management Procedure - switch (sdls_frame.pdu.pid) - { - case PID_OTAR: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key OTAR\n" RESET); - #endif - status = Crypto_Key_OTAR(); - break; - case PID_KEY_ACTIVATION: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Activate\n" RESET); - #endif - status = Crypto_Key_update(KEY_ACTIVE); - break; - case PID_KEY_DEACTIVATION: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Deactivate\n" RESET); - #endif - status = Crypto_Key_update(KEY_DEACTIVATED); - break; - case PID_KEY_VERIFICATION: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Verify\n" RESET); - #endif - status = Crypto_Key_verify(ingest,tc_frame); - break; - case PID_KEY_DESTRUCTION: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Destroy\n" RESET); - #endif - status = Crypto_Key_update(KEY_DESTROYED); - break; - case PID_KEY_INVENTORY: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Inventory\n" RESET); - #endif - status = Crypto_Key_inventory(ingest); - break; - default: - OS_printf(KRED "Error: Crypto_PDU failed interpreting Key Management Procedure Identification Field! \n" RESET); - break; - } - break; - case SG_SA_MGMT: // Security Association Management Procedure - switch (sdls_frame.pdu.pid) - { - case PID_CREATE_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Create\n" RESET); - #endif - status = sadb_routine->sadb_sa_create(); - break; - case PID_DELETE_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Delete\n" RESET); - #endif - status = sadb_routine->sadb_sa_delete(); - break; - case PID_SET_ARSNW: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA setARSNW\n" RESET); - #endif - status = sadb_routine->sadb_sa_setARSNW(); - break; - case PID_REKEY_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Rekey\n" RESET); - #endif - status = sadb_routine->sadb_sa_rekey(); - break; - case PID_EXPIRE_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Expire\n" RESET); - #endif - status = sadb_routine->sadb_sa_expire(); - break; - case PID_SET_ARSN: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA SetARSN\n" RESET); - #endif - status = sadb_routine->sadb_sa_setARSN(); - break; - case PID_START_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Start\n" RESET); - #endif - status = sadb_routine->sadb_sa_start(tc_frame); - break; - case PID_STOP_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Stop\n" RESET); - #endif - status = sadb_routine->sadb_sa_stop(); - break; - case PID_READ_ARSN: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA readARSN\n" RESET); - #endif - status = Crypto_SA_readARSN(ingest); - break; - case PID_SA_STATUS: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Status\n" RESET); - #endif - status = sadb_routine->sadb_sa_status(ingest); - break; - default: - OS_printf(KRED "Error: Crypto_PDU failed interpreting SA Procedure Identification Field! \n" RESET); - break; - } - break; - case SG_SEC_MON_CTRL: // Security Monitoring & Control Procedure - switch (sdls_frame.pdu.pid) - { - case PID_PING: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Ping\n" RESET); - #endif - status = Crypto_MC_ping(ingest); - break; - case PID_LOG_STATUS: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Status\n" RESET); - #endif - status = Crypto_MC_status(ingest); - break; - case PID_DUMP_LOG: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Dump\n" RESET); - #endif - status = Crypto_MC_dump(ingest); - break; - case PID_ERASE_LOG: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Erase\n" RESET); - #endif - status = Crypto_MC_erase(ingest); - break; - case PID_SELF_TEST: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Selftest\n" RESET); - #endif - status = Crypto_MC_selftest(ingest); - break; - case PID_ALARM_FLAG: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Reset Alarm\n" RESET); - #endif - status = Crypto_MC_resetalarm(); - break; - default: - OS_printf(KRED "Error: Crypto_PDU failed interpreting MC Procedure Identification Field! \n" RESET); - break; - } - break; - default: // ERROR - OS_printf(KRED "Error: Crypto_PDU failed interpreting Service Group! \n" RESET); - break; - } - break; - - case 1: // User Defined Command - switch (sdls_frame.pdu.sg) - { - default: - switch (sdls_frame.pdu.pid) - { - case 0: // Idle Frame Trigger - #ifdef PDU_DEBUG - OS_printf(KMAG "User Idle Trigger\n" RESET); - #endif - status = Crypto_User_IdleTrigger(ingest); - break; - case 1: // Toggle Bad SPI - #ifdef PDU_DEBUG - OS_printf(KMAG "User Toggle Bad SPI\n" RESET); - #endif - status = Crypto_User_BadSPI(); - break; - case 2: // Toggle Bad IV - #ifdef PDU_DEBUG - OS_printf(KMAG "User Toggle Bad IV\n" RESET); - #endif - status = Crypto_User_BadIV();\ - break; - case 3: // Toggle Bad MAC - #ifdef PDU_DEBUG - OS_printf(KMAG "User Toggle Bad MAC\n" RESET); - #endif - status = Crypto_User_BadMAC(); - break; - case 4: // Toggle Bad FECF - #ifdef PDU_DEBUG - OS_printf(KMAG "User Toggle Bad FECF\n" RESET); - #endif - status = Crypto_User_BadFECF(); - break; - case 5: // Modify Key - #ifdef PDU_DEBUG - OS_printf(KMAG "User Modify Key\n" RESET); - #endif - status = Crypto_User_ModifyKey(); - break; - case 6: // Modify ActiveTM - #ifdef PDU_DEBUG - OS_printf(KMAG "User Modify Active TM\n" RESET); - #endif - status = Crypto_User_ModifyActiveTM(); - break; - case 7: // Modify TM VCID - #ifdef PDU_DEBUG - OS_printf(KMAG "User Modify VCID\n" RESET); - #endif - status = Crypto_User_ModifyVCID(); - break; - default: - OS_printf(KRED "Error: Crypto_PDU received user defined command! \n" RESET); - break; - } - } - break; - } - break; - - case 1: // Reply - OS_printf(KRED "Error: Crypto_PDU failed interpreting PDU Type! Received a Reply!?! \n" RESET); - break; - } - - #ifdef CCSDS_DEBUG - if (status > 0) - { - OS_printf(KMAG "CCSDS message put on software bus: 0x" RESET); - for (int x = 0; x < status; x++) - { - OS_printf(KMAG "%02x" RESET, (uint8) ingest[x]); - } - OS_printf("\n"); - } - #endif - - return status; -} -int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ - uint8 **pp_in_frame, uint16 *p_enc_frame_len) -{ - // Local Variables - int32 status = OS_SUCCESS; - TC_FramePrimaryHeader_t temp_tc_header; - SecurityAssociation_t temp_SA; - uint8 *p_new_enc_frame = NULL; - int16_t spi = -1; - uint8 sa_service_type = -1; - uint16 mac_loc = 0; - uint16 tf_payload_len = 0x0000; - uint16 new_fecf = 0x0000; - uint8 aad[20]; - gcry_cipher_hd_t tmp_hd; - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); - #endif - - #ifdef DEBUG - OS_printf("%d TF Bytes received\n", in_frame_length); - OS_printf("DEBUG - "); - for(int i=0; i < in_frame_length; i++) - { - OS_printf("%02X", ((uint8 *)&*p_in_frame)[i]); - } - OS_printf("\nPrinted %d bytes\n", in_frame_length); - #endif - - // Primary Header - temp_tc_header.tfvn = ((uint8)p_in_frame[0] & 0xC0) >> 6; - temp_tc_header.bypass = ((uint8)p_in_frame[0] & 0x20) >> 5; - temp_tc_header.cc = ((uint8)p_in_frame[0] & 0x10) >> 4; - temp_tc_header.spare = ((uint8)p_in_frame[0] & 0x0C) >> 2; - temp_tc_header.scid = ((uint8)p_in_frame[0] & 0x03) << 8; - temp_tc_header.scid = temp_tc_header.scid | (uint8)p_in_frame[1]; - temp_tc_header.vcid = ((uint8)p_in_frame[2] & 0xFC) >> 2; - temp_tc_header.fl = ((uint8)p_in_frame[2] & 0x03) << 8; - temp_tc_header.fl = temp_tc_header.fl | (uint8)p_in_frame[3]; - temp_tc_header.fsn = (uint8)p_in_frame[4]; - - // Check if command frame flag set - if (temp_tc_header.cc == 1) - { - /* - ** CCSDS 232.0-B-3 - ** Section 6.3.1 - ** "Type-C frames do not have the Security Header and Security Trailer." - */ - #ifdef TC_DEBUG - OS_printf(KYEL "DEBUG - Received Control/Command frame - nothing to do.\n" RESET); - #endif - status = OS_ERROR; - } - - // TODO: If command frame flag not set, need to know SDLS parameters - // What is the best way to do this - copy in the entire SA for a channel? - // Expect these calls will return an error is the SA is not usable - // Will need to know lengths of various parameters from the SA DB - if (status == OS_SUCCESS) - { - // Query SA DB for active SA / SDLS paremeters - // TODO: Likely API call - // TODO: Magic to make sure we're getting the correct SA.. - // currently SA DB allows for more than one - for (int i=0; i < NUM_SA;i++) - { - if (sa[i].sa_state == SA_OPERATIONAL) - { - spi = i; - //break; // Needs modified to ACTUALLY get the correct SA - // TODO: Likely API discussion - } - } - - // If no active SA found - if (spi == -1) - { - OS_printf(KRED "Error: No operational SA found! \n" RESET); - status = OS_ERROR; - } - // Found an active SA - else - { - CFE_PSP_MemCpy(&temp_SA, &(sa[spi]), SA_SIZE); - #ifdef TC_DEBUG - OS_printf("Operational SA found at index %d.\n", spi); - #endif - } - - #ifdef SA_DEBUG - OS_printf(KYEL "DEBUG - Received data frame.\n" RESET); - OS_printf("Using SA 0x%04X settings.\n", spi); - #endif - - // Verify SCID - if ((temp_tc_header.scid != temp_SA.gvcid_tc_blk[temp_tc_header.vcid].scid) \ - && (status == OS_SUCCESS)) - { - OS_printf(KRED "Error: SCID incorrect! \n" RESET); - status = OS_ERROR; - } - - #ifdef SA_DEBUG - OS_printf(KYEL "DEBUG - Printing local copy of SA Entry for current SPI.\n" RESET); - Crypto_saPrint(&temp_SA); - #endif - - // Verify SA SPI configurations - // Check if SA is operational - if ((temp_SA.sa_state != SA_OPERATIONAL) && (status == OS_SUCCESS)) - { - OS_printf(KRED "Error: SA is not operational! \n" RESET); - status = OS_ERROR; - } - // Check if this VCID exists / is mapped to TCs - if ((temp_SA.gvcid_tc_blk[temp_tc_header.vcid].mapid != TYPE_TC) && (status = OS_SUCCESS)) - { - OS_printf(KRED "Error: SA does not map this VCID to TC! \n" RESET); - status = OS_ERROR; - } - - // If a check is invalid so far, can return - if (status != OS_SUCCESS) - { - return status; - } - - // Determine SA Service Type - if ((temp_SA.est == 0) && (temp_SA.ast == 0)) - { - sa_service_type = SA_PLAINTEXT; - } - else if ((temp_SA.est == 0) && (temp_SA.ast == 1)) - { - sa_service_type = SA_AUTHENTICATION; - } - else if ((temp_SA.est == 1) && (temp_SA.ast == 0)) - { - sa_service_type = SA_ENCRYPTION; - } - else if ((temp_SA.est == 1) && (temp_SA.ast == 1)) - { - sa_service_type = SA_AUTHENTICATED_ENCRYPTION; - } - else - { - // Probably unnecessary check - // Leaving for now as it would be cleaner in SA to have an association enum returned I believe - OS_printf(KRED "Error: SA Service Type is not defined! \n" RESET); - status = OS_ERROR; - return status; - } - - #ifdef TC_DEBUG - switch(sa_service_type) - { - case SA_PLAINTEXT: - OS_printf(KBLU "Creating a TC - CLEAR!\n" RESET); - break; - case SA_AUTHENTICATION: - OS_printf(KBLU "Creating a TC - AUTHENTICATED!\n" RESET); - break; - case SA_ENCRYPTION: - OS_printf(KBLU "Creating a TC - ENCRYPTED!\n" RESET); - break; - case SA_AUTHENTICATED_ENCRYPTION: - OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION!\n" RESET); - break; - } - #endif - - // Determine length of buffer to be malloced - // TODO: Determine presence of FECF & TC_PAD_SIZE - // TODO: Note: Currently assumes ciphertext output length is same as ciphertext input length - switch(sa_service_type) - { - case SA_PLAINTEXT: - // Ingest length + segment header (1) + spi_index (2) + some variable length fields - *p_enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shplf_len; - case SA_AUTHENTICATION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size + stmacf_len - *p_enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ - temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len;; - case SA_ENCRYPTION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size - *p_enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ - temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE; - case SA_AUTHENTICATED_ENCRYPTION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size + stmacf_len - *p_enc_frame_len = in_frame_length + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + \ - temp_SA.shplf_len + temp_SA.arc_len + TC_PAD_SIZE + temp_SA.stmacf_len; - } - - #ifdef TC_DEBUG - OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *p_enc_frame_len); - OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); - OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded - OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); - OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, temp_SA.shivf_len); - OS_printf(KYEL "\tshsnf_len\t = %d\n" RESET, temp_SA.shsnf_len); - OS_printf(KYEL "\tshplf len\t = %d\n" RESET, temp_SA.shplf_len); - OS_printf(KYEL "\tarc_len\t\t = %d\n" RESET, temp_SA.arc_len); - OS_printf(KYEL "\tpad_size\t = %d\n" RESET, TC_PAD_SIZE); - OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, temp_SA.stmacf_len); - #endif - - // Accio buffer - p_new_enc_frame = (uint8 *)malloc(*p_enc_frame_len * sizeof (unsigned char)); - if(!p_new_enc_frame) - { - OS_printf(KRED "Error: Malloc for encrypted output buffer failed! \n" RESET); - status = OS_ERROR; - return status; - } - CFE_PSP_MemSet(p_new_enc_frame, 0, *p_enc_frame_len); - - // Copy original TF header - CFE_PSP_MemCpy(p_new_enc_frame, p_in_frame, TC_FRAME_PRIMARYHEADER_SIZE); - - // Set new TF Header length - // Recall: Length field is one minus total length per spec - *(p_new_enc_frame+2) = ((*(p_new_enc_frame+2) & 0xFC) | (((*p_enc_frame_len - 1) & (0x0300)) >> 8)); - *(p_new_enc_frame+3) = ((*p_enc_frame_len - 1) & (0x00FF)); - - #ifdef TC_DEBUG - OS_printf(KYEL "Printing updated TF Header:\n\t"); - for (int i=0; i> 8); - *(p_new_enc_frame + index + 1) = (spi & 0x00FF); - index += 2; - - // Set initialization vector if specified - if ((sa_service_type == SA_AUTHENTICATION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) - { - #ifdef SA_DEBUG - OS_printf(KYEL "Old IV value was:\n\t"); - for(int i=0; i 0) - { - // If using anti-replay counter, increment it - // TODO: API call instead? - // TODO: Check return code - Crypto_increment(sa[spi].arc, sa[spi].shsnf_len); - for (int i=0; i < temp_SA.shsnf_len; i++) - { - *(p_new_enc_frame + index) = sa[spi].arc[i]; - index++; - } - } - - // Set security header padding if specified - /* - ** 4.2.3.4 h) if the algorithm and mode selected for the SA require the use of - ** fill padding, place the number of fill bytes used into the Pad Length field - ** of the Security Header - Reference CCSDS 3550b1 - */ - // TODO: Revisit this - // TODO: Likely SA API Call - for (int i=0; i < temp_SA.shplf_len; i++) - { - /* 4.1.1.5.2 The Pad Length field shall contain the count of fill bytes used in the - ** cryptographic process, consisting of an integral number of octets. - CCSDS 3550b1 - */ - // TODO: Set this depending on crypto cipher used - *(p_new_enc_frame + index) = 0x00; - index++; - } - - /* - ** End Security Header Fields - */ - - // Copy in original TF data - except FECF - // Will be over-written if using encryption later - // TODO: This will change depending on how we handle segment header and FECF above, - // and if it was present in the original TCTF - //if FECF - tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - FECF_SIZE; - //if no FECF - //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; - CFE_PSP_MemCpy((p_new_enc_frame+index), (p_in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); - //index += tf_payload_len; - - /* - ** Begin Security Trailer Fields - */ - - // Set MAC Field if present - /* - ** May be present and unused if switching between clear and authenticated - ** CCSDS 3550b1 4.1.2.3 - */ - // By leaving MAC as zeros, can use index for encryption output - // for (int i=0; i < temp_SA.stmacf_len; i++) - // { - // // Temp fill MAC - // *(p_new_enc_frame + index) = 0x00; - // index++; - // } - - /* - ** End Security Trailer Fields - */ - - /* - ** Begin Authentication / Encryption - */ - - if (sa_service_type != SA_PLAINTEXT) - { - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[sa[spi].ekid].value[0]), - KEY_SIZE //TODO: look into this - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(sa[spi].iv[0]), - sa[spi].iv_len - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - - // Prepare additional authenticated data, if needed - if ((sa_service_type == SA_AUTHENTICATION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) - { - for (int y = 0; y < sa[spi].abm_len; y++) - { - aad[y] = p_in_frame[y] & sa[spi].abm[y]; - } - #ifdef MAC_DEBUG - OS_printf(KYEL "Preparing AAD:\n"); - OS_printf("\tUsing ABM Length of %d\n\t", sa[spi].abm_len); - for (int y = 0; y < sa[spi].abm_len; y++) - { - OS_printf("%02x", aad[y]); - } - OS_printf("\n" RESET); - #endif - - gcry_error = gcry_cipher_authenticate( - tmp_hd, - &(aad[0]), // additional authenticated data - sa[spi].abm_len // length of AAD - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); - status = OS_ERROR; - return status; - } - } - - if ((sa_service_type == SA_ENCRYPTION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) - { - // TODO: More robust calculation of this location - // uint16 output_loc = TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; - #ifdef TC_DEBUG - OS_printf("Encrypted bytes output_loc is %d\n", index); - OS_printf("tf_payload_len is %d\n", tf_payload_len); - OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); - for(int i=0; i < *p_enc_frame_len; i++) - { - OS_printf("%02X", *(p_new_enc_frame + i)); - } - OS_printf("\n"); - #endif - - gcry_error = gcry_cipher_encrypt( - tmp_hd, - &p_new_enc_frame[index], // ciphertext output - tf_payload_len, // length of data - (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now - tf_payload_len // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - } - - if ((sa_service_type == SA_AUTHENTICATION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) - { - // TODO - Know if FECF exists - mac_loc = *p_enc_frame_len - sa[spi].stmacf_len - FECF_SIZE; - #ifdef MAC_DEBUG - OS_printf(KYEL "MAC location is: %d\n" RESET, mac_loc); - OS_printf(KYEL "MAC size is: %d\n" RESET, MAC_SIZE); - #endif - gcry_error = gcry_cipher_gettag( - tmp_hd, - &p_new_enc_frame[mac_loc], // tag output - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - } - // Zeroise any sensitive information - if (sa_service_type != SA_PLAINTEXT) - { - gcry_cipher_close(tmp_hd); - } - } - /* - ** End Authentication / Encryption - */ - - // Set FECF Field if present - // TODO: Determine is FECF is even present - // on this particular channel - // Calc new fecf, don't include old fecf in length - #ifdef FECF_DEBUG - OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *p_enc_frame_len - 2); - #endif - new_fecf = Crypto_Calc_FECF(p_new_enc_frame, *p_enc_frame_len - 2); - *(p_new_enc_frame + *p_enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); - *(p_new_enc_frame + *p_enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); - index += 2; - - #ifdef TC_DEBUG - OS_printf(KYEL "Printing new TC Frame:\n\t"); - for(int i=0; i < *p_enc_frame_len; i++) - { - OS_printf("%02X", *(p_new_enc_frame + i)); - } - OS_printf("\n\tThe returned length is: %d\n" RESET, *p_enc_frame_len); - #endif - - *pp_in_frame = p_new_enc_frame; - } - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_TC_ApplySecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_processed_frame) -// Loads the ingest frame into the global tc_frame while performing decryption -{ - // Local Variables - int32 status = OS_SUCCESS; - int x = 0; - int y = 0; - gcry_cipher_hd_t tmp_hd; - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - SecurityAssociation_t* sa_ptr = NULL; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_TC_ProcessSecurity START -----\n" RESET); - #endif - - int byte_idx = 0; - // Primary Header - tc_sdls_processed_frame->tc_header.tfvn = ((uint8)ingest[byte_idx] & 0xC0) >> 6; - tc_sdls_processed_frame->tc_header.bypass = ((uint8)ingest[byte_idx] & 0x20) >> 5; - tc_sdls_processed_frame->tc_header.cc = ((uint8)ingest[byte_idx] & 0x10) >> 4; - tc_sdls_processed_frame->tc_header.spare = ((uint8)ingest[byte_idx] & 0x0C) >> 2; - tc_sdls_processed_frame->tc_header.scid = ((uint8)ingest[byte_idx] & 0x03) << 8; - byte_idx++; - tc_sdls_processed_frame->tc_header.scid = tc_sdls_processed_frame->tc_header.scid | (uint8)ingest[byte_idx]; - byte_idx++; - tc_sdls_processed_frame->tc_header.vcid = (((uint8)ingest[byte_idx] & 0xFC) >> 2) & VCID_BITMASK; - tc_sdls_processed_frame->tc_header.fl = ((uint8)ingest[byte_idx] & 0x03) << 8; - byte_idx++; - tc_sdls_processed_frame->tc_header.fl = tc_sdls_processed_frame->tc_header.fl | (uint8)ingest[byte_idx]; - byte_idx++; - tc_sdls_processed_frame->tc_header.fsn = (uint8)ingest[byte_idx]; - byte_idx++; - - // Security Header - if(SEGMENTATION_HDR){ - tc_sdls_processed_frame->tc_sec_header.sh = (uint8)ingest[byte_idx]; - byte_idx++; - } - tc_sdls_processed_frame->tc_sec_header.spi = ((uint8)ingest[byte_idx] << 8) | (uint8)ingest[byte_idx+1]; - byte_idx+=2; - #ifdef TC_DEBUG - OS_printf("vcid = %d \n", tc_sdls_processed_frame->tc_header.vcid ); - OS_printf("spi = %d \n", tc_sdls_processed_frame->tc_sec_header.spi); - #endif - - // Checks - if (PUS_HDR && ((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) - { - // User packet check only used for ESA Testing! - } - else - { // Update last spi used - report.lspiu = tc_sdls_processed_frame->tc_sec_header.spi; - - // Verify - if (tc_sdls_processed_frame->tc_header.scid != (SCID & 0x3FF)) - { - OS_printf(KRED "Error: SCID incorrect! \n" RESET); - status = OS_ERROR; - } - else - { - switch (report.lspiu) - { // Invalid SPIs fall through to trigger flag in FSR - case 0x0000: - case 0xFFFF: - status = OS_ERROR; - report.ispif = 1; - OS_printf(KRED "Error: SPI invalid! \n" RESET); - break; - default: - break; - } - } - - - if ((report.lspiu > NUM_SA) && (status == OS_SUCCESS)) - { - report.ispif = 1; - OS_printf(KRED "Error: SPI value greater than NUM_SA! \n" RESET); - status = OS_ERROR; - } - if (status == OS_SUCCESS) - { - if(sadb_routine->sadb_get_sa_from_spi(report.lspiu,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - status = OS_ERROR; //Error -- unable to get SA from SPI. - } - } - if (status == OS_SUCCESS) - { - if (sa_ptr->gvcid_tc_blk.mapid != TYPE_TC) - { - OS_printf(KRED "Error: SA invalid type! \n" RESET); - status = OS_ERROR; - } - } - // TODO: I don't think this is needed. - //if (status == OS_SUCCESS) - //{ - // if (sa_ptr->gvcid_tc_blk.vcid != tc_sdls_processed_frame->tc_header.vcid) - // { - // OS_printf(KRED "Error: VCID not mapped to provided SPI! \n" RESET); - // status = OS_ERROR; - // } - //} - if (status == OS_SUCCESS) - { - if (sa_ptr->sa_state != SA_OPERATIONAL) - { - OS_printf(KRED "Error: SA state not operational! \n" RESET); - status = OS_ERROR; - } - } - if (status != OS_SUCCESS) - { - report.af = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = SPI_INVALID_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - *len_ingest = 0; - return status; - } - } - if(sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - status = OS_ERROR; //Error -- unable to get SA from SPI. - return status; - } - // Determine mode via SPI - if ((sa_ptr->est == 1) && - (sa_ptr->ast == 1)) - { // Authenticated Encryption - #ifdef DEBUG - OS_printf(KBLU "ENCRYPTED TC Received!\n" RESET); - #endif - #ifdef TC_DEBUG - OS_printf("IV: \n"); - #endif - for (x = byte_idx; x < (byte_idx + IV_SIZE); x++) - { - tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; - #ifdef TC_DEBUG - OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); - #endif - } - byte_idx += IV_SIZE; - report.snval = tc_sdls_processed_frame->tc_sec_header.iv[IV_SIZE-1]; - - #ifdef DEBUG - OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", IV_SIZE-1, tc_sdls_processed_frame->tc_sec_header.iv[IV_SIZE-1]); - OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, IV_SIZE-1, sa_ptr->iv[IV_SIZE-1]); - #endif - - // Check IV is in ARCW - if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, IV_SIZE, - sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) - { - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_WINDOW_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV not in window! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { - if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, IV_SIZE) == OS_SUCCESS ) - { // Replay - IV value lower than expected - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_REPLAY_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { // Adjust expected IV to acceptable received value - for (int i = 0; i < (IV_SIZE); i++) - { - sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; - } - } - } - - if ( status == OS_ERROR ) - { // Exit - *len_ingest = 0; - return status; - } - - tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame); - - x = x + tc_sdls_processed_frame->tc_pdu_len; - - #ifdef TC_DEBUG - OS_printf("TC: \n"); - for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) - { - OS_printf("\t ingest[%d] = 0x%02x \n", temp, (uint8)ingest[temp+20]); - } - #endif - - // Security Trailer - #ifdef TC_DEBUG - OS_printf("MAC: \n"); - #endif - for (y = x; y < (x + MAC_SIZE); y++) - { - tc_sdls_processed_frame->tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; - #ifdef TC_DEBUG - OS_printf("\t mac[%d] = 0x%02x\n", y-x, tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); - #endif - } - x = x + MAC_SIZE; - - // FECF - tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); - Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 2),tc_sdls_processed_frame); - - // Initialize the key - //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[sa_ptr->ekid]); - - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - #ifdef DEBUG - OS_printf("Key ID = %d, 0x", sa_ptr->ekid); - for(int y = 0; y < KEY_SIZE; y++) - { - OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); - } - OS_printf("\n"); - #endif - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[sa_ptr->ekid].value[0]), - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(sa_ptr->iv[0]), - sa_ptr->iv_len - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - #ifdef MAC_DEBUG - OS_printf("AAD = 0x"); - #endif - // Prepare additional authenticated data (AAD) - for (y = 0; y < sa_ptr->abm_len; y++) - { - ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); - #ifdef MAC_DEBUG - OS_printf("%02x", (uint8) ingest[y]); - #endif - } - #ifdef MAC_DEBUG - OS_printf("\n"); - #endif - - gcry_error = gcry_cipher_decrypt( - tmp_hd, - &(tc_sdls_processed_frame->tc_pdu[0]), // plaintext output - tc_sdls_processed_frame->tc_pdu_len, // length of data - &(ingest[20]), // ciphertext input - tc_sdls_processed_frame->tc_pdu_len // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_checktag( - tmp_hd, - &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag input - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - - OS_printf("Actual MAC = 0x"); - for (int z = 0; z < MAC_SIZE; z++) - { - OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); - } - OS_printf("\n"); - - gcry_error = gcry_cipher_gettag( - tmp_hd, - &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - - OS_printf("Expected MAC = 0x"); - for (int z = 0; z < MAC_SIZE; z++) - { - OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); - } - OS_printf("\n"); - status = OS_ERROR; - report.bmacf = 1; - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - return status; - } - gcry_cipher_close(tmp_hd); - - // Increment the IV for next time - #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, IV_SIZE); - #endif - } - else - { // Clear - #ifdef DEBUG - OS_printf(KBLU "CLEAR TC Received!\n" RESET); - #endif - - for (y = 10; y <= (tc_sdls_processed_frame->tc_header.fl - 2); y++) //tfhdr+seghdr+sechdr=5+1+6=12 - { - tc_sdls_processed_frame->tc_pdu[y - 10] = (uint8)ingest[y]; - } - // FECF - tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[y] << 8) | ((uint8)ingest[y+1]); - Crypto_FECF((int) tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 2),tc_sdls_processed_frame); - } - - #ifdef TC_DEBUG - Crypto_tcPrint(tc_sdls_processed_frame); - #endif - - // Zero ingest - for (x = 0; x < *len_ingest; x++) - { - ingest[x] = 0; - } - - - if(!TC_PROCESS_SDLS_PDUS) //If we don't want to process frame data for SDLS PDUs, only reverse security & return content. - { - // CCSDS Pass-through - #ifdef DEBUG - OS_printf(KGRN "CCSDS Pass-through \n" RESET); - #endif - if (PUS_HDR) { - for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl - 11); x++) { - ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; - #ifdef CCSDS_DEBUG - OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); - #endif - *len_ingest = x; - } - } else { - for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl); x++) { //with no PUS header, entire PDU is data - ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; - #ifdef CCSDS_DEBUG - OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); - #endif - *len_ingest = x; - } - } - } - else //Process SDLS PDU - { - if (PUS_HDR) - { - if ((tc_sdls_processed_frame->tc_pdu[0] == 0x18) && (tc_sdls_processed_frame->tc_pdu[1] == 0x80)) - // Crypto Lib Application ID - { - #ifdef DEBUG - OS_printf(KGRN "Received SDLS command: " RESET); - #endif - // CCSDS Header - sdls_frame.hdr.pvn = (tc_sdls_processed_frame->tc_pdu[0] & 0xE0) >> 5; - sdls_frame.hdr.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x10) >> 4; - sdls_frame.hdr.shdr = (tc_sdls_processed_frame->tc_pdu[0] & 0x08) >> 3; - sdls_frame.hdr.appID = - ((tc_sdls_processed_frame->tc_pdu[0] & 0x07) << 8) | tc_sdls_processed_frame->tc_pdu[1]; - sdls_frame.hdr.seq = (tc_sdls_processed_frame->tc_pdu[2] & 0xC0) >> 6; - sdls_frame.hdr.pktid = - ((tc_sdls_processed_frame->tc_pdu[2] & 0x3F) << 8) | tc_sdls_processed_frame->tc_pdu[3]; - sdls_frame.hdr.pkt_length = (tc_sdls_processed_frame->tc_pdu[4] << 8) | tc_sdls_processed_frame->tc_pdu[5]; - - // CCSDS PUS - sdls_frame.pus.shf = (tc_sdls_processed_frame->tc_pdu[6] & 0x80) >> 7; - sdls_frame.pus.pusv = (tc_sdls_processed_frame->tc_pdu[6] & 0x70) >> 4; - sdls_frame.pus.ack = (tc_sdls_processed_frame->tc_pdu[6] & 0x0F); - sdls_frame.pus.st = tc_sdls_processed_frame->tc_pdu[7]; - sdls_frame.pus.sst = tc_sdls_processed_frame->tc_pdu[8]; - sdls_frame.pus.sid = (tc_sdls_processed_frame->tc_pdu[9] & 0xF0) >> 4; - sdls_frame.pus.spare = (tc_sdls_processed_frame->tc_pdu[9] & 0x0F); - - // SDLS TLV PDU - sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[10] & 0x80) >> 7; - sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[10] & 0x40) >> 6; - sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[10] & 0x30) >> 4; - sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[10] & 0x0F); - sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[11] << 8) | tc_sdls_processed_frame->tc_pdu[12]; - for (x = 13; x < (13 + sdls_frame.hdr.pkt_length); x++) { - sdls_frame.pdu.data[x - 13] = tc_sdls_processed_frame->tc_pdu[x]; - } - - #ifdef CCSDS_DEBUG - Crypto_ccsdsPrint(&sdls_frame); - #endif - - // Determine type of PDU - *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); - } - } - else if (tc_sdls_processed_frame->tc_header.vcid == TC_SDLS_EP_VCID) //TC SDLS PDU with no packet layer - { - #ifdef DEBUG - OS_printf(KGRN "Received SDLS command: " RESET); - #endif - // No Packet HDR or PUS in these frames - // SDLS TLV PDU - sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x80) >> 7; - sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[0] & 0x40) >> 6; - sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[0] & 0x30) >> 4; - sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[0] & 0x0F); - sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[1] << 8) | tc_sdls_processed_frame->tc_pdu[2]; - for (x = 3; x < (3 + tc_sdls_processed_frame->tc_header.fl); x++) { - //Todo - Consider how this behaves with large OTAR PDUs that are larger than 1 TC in size. Most likely fails. Must consider Uplink Sessions (sequence numbers). - sdls_frame.pdu.data[x - 3] = tc_sdls_processed_frame->tc_pdu[x]; - } - - #ifdef CCSDS_DEBUG - Crypto_ccsdsPrint(&sdls_frame); - #endif - - // Determine type of PDU - *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); - } - else { - //TODO - Process SDLS PDU with Packet Layer without PUS_HDR - } - }//End Process SDLS PDU - - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_TC_ProcessSecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) -// Accepts CCSDS message in ingest, and packs into TM before encryption -{ - int32 status = ITC_GCM128_SUCCESS; - int count = 0; - int pdu_loc = 0; - int pdu_len = *len_ingest - TM_MIN_SIZE; - int pad_len = 0; - int mac_loc = 0; - int fecf_loc = 0; - uint8 tempTM[TM_SIZE]; - int x = 0; - int y = 0; - uint8 aad[20]; - uint16 spi = tm_frame.tm_sec_header.spi; - uint16 spp_crc = 0x0000; - SecurityAssociation_t* sa_ptr; - SecurityAssociation_t sa; - - gcry_cipher_hd_t tmp_hd; - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - CFE_PSP_MemSet(&tempTM, 0, TM_SIZE); - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_TM_ApplySecurity START -----\n" RESET); - #endif - - // Check for idle frame trigger - if (((uint8)ingest[0] == 0x08) && ((uint8)ingest[1] == 0x90)) - { // Zero ingest - for (x = 0; x < *len_ingest; x++) - { - ingest[x] = 0; - } - // Update TM First Header Pointer - tm_frame.tm_header.fhp = 0xFE; - } - else - { // Update the length of the ingest from the CCSDS header - *len_ingest = (ingest[4] << 8) | ingest[5]; - ingest[5] = ingest[5] - 5; - // Remove outgoing secondary space packet header flag - ingest[0] = 0x00; - // Change sequence flags to 0xFFFF - ingest[2] = 0xFF; - ingest[3] = 0xFF; - // Add 2 bytes of CRC to space packet - spp_crc = Crypto_Calc_CRC16((char*) ingest, *len_ingest); - ingest[*len_ingest] = (spp_crc & 0xFF00) >> 8; - ingest[*len_ingest+1] = (spp_crc & 0x00FF); - *len_ingest = *len_ingest + 2; - // Update TM First Header Pointer - tm_frame.tm_header.fhp = tm_offset; - #ifdef TM_DEBUG - OS_printf("tm_offset = %d \n", tm_offset); - #endif - } - - // Update Current Telemetry Frame in Memory - // Counters - tm_frame.tm_header.mcfc++; - tm_frame.tm_header.vcfc++; - // Operational Control Field - Crypto_TM_updateOCF(); - // Payload Data Unit - Crypto_TM_updatePDU(ingest, *len_ingest); - - if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - return OS_ERROR; //Error -- unable to get SA from SPI. - } - - - // Check test flags - if (badSPI == 1) - { - tm_frame.tm_sec_header.spi++; - } - if (badIV == 1) - { - sa_ptr->iv[IV_SIZE-1]++; - } - if (badMAC == 1) - { - tm_frame.tm_sec_trailer.mac[MAC_SIZE-1]++; - } - - // Initialize the temporary TM frame - // Header - tempTM[count++] = (uint8) ((tm_frame.tm_header.tfvn << 6) | ((tm_frame.tm_header.scid & 0x3F0) >> 4)); - tempTM[count++] = (uint8) (((tm_frame.tm_header.scid & 0x00F) << 4) | (tm_frame.tm_header.vcid << 1) | (tm_frame.tm_header.ocff)); - tempTM[count++] = (uint8) (tm_frame.tm_header.mcfc); - tempTM[count++] = (uint8) (tm_frame.tm_header.vcfc); - tempTM[count++] = (uint8) ((tm_frame.tm_header.tfsh << 7) | (tm_frame.tm_header.sf << 6) | (tm_frame.tm_header.pof << 5) | (tm_frame.tm_header.slid << 3) | ((tm_frame.tm_header.fhp & 0x700) >> 8)); - tempTM[count++] = (uint8) (tm_frame.tm_header.fhp & 0x0FF); - // tempTM[count++] = (uint8) ((tm_frame.tm_header.tfshvn << 6) | tm_frame.tm_header.tfshlen); - // Security Header - tempTM[count++] = (uint8) ((spi & 0xFF00) >> 8); - tempTM[count++] = (uint8) ((spi & 0x00FF)); - CFE_PSP_MemCpy(tm_frame.tm_sec_header.iv, sa_ptr->iv, IV_SIZE); - - // Padding Length - pad_len = Crypto_Get_tmLength(*len_ingest) - TM_MIN_SIZE + IV_SIZE + TM_PAD_SIZE - *len_ingest; - - // Only add IV for authenticated encryption - if ((sa_ptr->est == 1) && - (sa_ptr->ast == 1)) - { // Initialization Vector - #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, IV_SIZE); - #endif - if ((sa_ptr->est == 1) || (sa_ptr->ast == 1)) - { for (x = 0; x < IV_SIZE; x++) - { - tempTM[count++] = sa_ptr->iv[x]; - } - } - pdu_loc = count; - pad_len = pad_len - IV_SIZE - TM_PAD_SIZE + OCF_SIZE; - pdu_len = *len_ingest + pad_len; - } - else - { // Include padding length bytes - hard coded per ESA testing - tempTM[count++] = 0x00; // pad_len >> 8; - tempTM[count++] = 0x1A; // pad_len - pdu_loc = count; - pdu_len = *len_ingest + pad_len; - } - - // Payload Data Unit - for (x = 0; x < (pdu_len); x++) - { - tempTM[count++] = (uint8) tm_frame.tm_pdu[x]; - } - // Message Authentication Code - mac_loc = count; - for (x = 0; x < MAC_SIZE; x++) - { - tempTM[count++] = 0x00; - } - // Operational Control Field - for (x = 0; x < OCF_SIZE; x++) - { - tempTM[count++] = (uint8) tm_frame.tm_sec_trailer.ocf[x]; - } - // Frame Error Control Field - fecf_loc = count; - tm_frame.tm_sec_trailer.fecf = Crypto_Calc_FECF((char*) tempTM, count); - tempTM[count++] = (uint8) ((tm_frame.tm_sec_trailer.fecf & 0xFF00) >> 8); - tempTM[count++] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); - - // Determine Mode - // Clear - if ((sa_ptr->est == 0) && - (sa_ptr->ast == 0)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TM - CLEAR! \n" RESET); - #endif - // Copy temporary frame to ingest - CFE_PSP_MemCpy(ingest, tempTM, count); - } - // Authenticated Encryption - else if ((sa_ptr->est == 1) && - (sa_ptr->ast == 1)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TM - AUTHENTICATED ENCRYPTION! \n" RESET); - #endif - - // Copy TM to ingest - CFE_PSP_MemCpy(ingest, tempTM, pdu_loc); - - #ifdef MAC_DEBUG - OS_printf("AAD = 0x"); - #endif - // Prepare additional authenticated data - for (y = 0; y < sa_ptr->abm_len; y++) - { - aad[y] = ingest[y] & sa_ptr->abm[y]; - #ifdef MAC_DEBUG - OS_printf("%02x", aad[y]); - #endif - } - #ifdef MAC_DEBUG - OS_printf("\n"); - #endif - - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[sa_ptr->ekid].value[0]), - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(sa_ptr->iv[0]), - sa_ptr->iv_len - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_encrypt( - tmp_hd, - &(ingest[pdu_loc]), // ciphertext output - pdu_len, // length of data - &(tempTM[pdu_loc]), // plaintext input - pdu_len // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_authenticate( - tmp_hd, - &(aad[0]), // additional authenticated data - sa_ptr->abm_len // length of AAD - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_gettag( - tmp_hd, - &(ingest[mac_loc]), // tag output - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - - #ifdef MAC_DEBUG - OS_printf("MAC = 0x"); - for(x = 0; x < MAC_SIZE; x++) - { - OS_printf("%02x", (uint8) ingest[x + mac_loc]); - } - OS_printf("\n"); - #endif - - // Update OCF - y = 0; - for (x = OCF_SIZE; x > 0; x--) - { - ingest[fecf_loc - x] = tm_frame.tm_sec_trailer.ocf[y++]; - } - - // Update FECF - tm_frame.tm_sec_trailer.fecf = Crypto_Calc_FECF((char*) ingest, fecf_loc - 1); - ingest[fecf_loc] = (uint8) ((tm_frame.tm_sec_trailer.fecf & 0xFF00) >> 8); - ingest[fecf_loc + 1] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); - } - // Authentication - else if ((sa_ptr->est == 0) && - (sa_ptr->ast == 1)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TM - AUTHENTICATED! \n" RESET); - #endif - // TODO: Future work. Operationally same as clear. - CFE_PSP_MemCpy(ingest, tempTM, count); - } - // Encryption - else if ((sa_ptr->est == 1) && - (sa_ptr->ast == 0)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TM - ENCRYPTED! \n" RESET); - #endif - // TODO: Future work. Operationally same as clear. - CFE_PSP_MemCpy(ingest, tempTM, count); - } - - #ifdef TM_DEBUG - Crypto_tmPrint(&tm_frame); - #endif - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_TM_ApplySecurity END -----\n" RESET); - #endif - - *len_ingest = count; - return status; -} - -int32 Crypto_TM_ProcessSecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_TM_ProcessSecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_TM_ProcessSecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_AOS_ApplySecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_AOS_ApplySecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_AOS_ApplySecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_AOS_ProcessSecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_AOS_ProcessSecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_AOS_ProcessSecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_ApplySecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_ApplySecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_ApplySecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_ProcessSecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_ProcessSecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_ProcessSecurity END -----\n" RESET); - #endif - - return status; -} - +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + +This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not +limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +any warranty that the software will be error free. + +In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +arising out of, resulting from, or in any0 way connected with the software or its documentation. Whether or not based upon warranty, +contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +documentation or services provided hereunder + +ITC Team +NASA IV&V +ivv-itc@lists.nasa.gov +*/ +#ifndef _crypto_c_ +#define _crypto_c_ + +/* +** Includes +*/ +#include "crypto.h" +#include "sadb_routine.h" + +#include "itc_aes128.h" +#include "itc_gcm128.h" + +#include "crypto_structs.h" +#include "crypto_print.h" +#include "crypto_config.h" +#include "crypto_events.h" + + + +#include + + +/* +** Static Library Declaration +*/ +#ifdef BUILD_STATIC + CFS_MODULE_DECLARE_LIB(crypto); +#endif + +static SadbRoutine sadb_routine = NULL; + +/* +** Static Prototypes +*/ +// Assisting Functions +static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame); +static int32 Crypto_Get_tmLength(int len); +static void Crypto_TM_updatePDU(char* ingest, int len_ingest); +static void Crypto_TM_updateOCF(void); +static void Crypto_Local_Config(void); +static void Crypto_Local_Init(void); +//static int32 Crypto_gcm_err(int gcm_err); +static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window); +static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length); +static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame); +static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest); +static void Crypto_Calc_CRC_Init_Table(void); +static uint16 Crypto_Calc_CRC16(char* data, int size); +// Key Management Functions +static int32 Crypto_Key_OTAR(void); +static int32 Crypto_Key_update(uint8 state); +static int32 Crypto_Key_inventory(char*); +static int32 Crypto_Key_verify(char*,TC_t* tc_frame); +// Security Monitoring & Control Procedure +static int32 Crypto_MC_ping(char* ingest); +static int32 Crypto_MC_status(char* ingest); +static int32 Crypto_MC_dump(char* ingest); +static int32 Crypto_MC_erase(char* ingest); +static int32 Crypto_MC_selftest(char* ingest); +static int32 Crypto_SA_readARSN(char* ingest); +static int32 Crypto_MC_resetalarm(void); +// User Functions +static int32 Crypto_User_IdleTrigger(char* ingest); +static int32 Crypto_User_BadSPI(void); +static int32 Crypto_User_BadIV(void); +static int32 Crypto_User_BadMAC(void); +static int32 Crypto_User_BadFECF(void); +static int32 Crypto_User_ModifyKey(void); +static int32 Crypto_User_ModifyActiveTM(void); +static int32 Crypto_User_ModifyVCID(void); +// Determine Payload Data Unit +static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); + +/* +** Global Variables +*/ +// Security +crypto_key_t ek_ring[NUM_KEYS]; +//static crypto_key_t ak_ring[NUM_KEYS]; +CCSDS_t sdls_frame; +TM_t tm_frame; +// OCF +static uint8 ocf = 0; +static SDLS_FSR_t report; +static TM_FrameCLCW_t clcw; +// Flags +static SDLS_MC_LOG_RPLY_t log_summary; +static SDLS_MC_DUMP_BLK_RPLY_t log; +static uint8 log_count = 0; +static uint16 tm_offset = 0; +// ESA Testing - 0 = disabled, 1 = enabled +static uint8 badSPI = 0; +static uint8 badIV = 0; +static uint8 badMAC = 0; +static uint8 badFECF = 0; +// CRC +static uint32 crc32Table[256]; +static uint16 crc16Table[256]; + +/* +** Initialization Functions +*/ +int32 Crypto_Init(void) +{ + int32 status = OS_SUCCESS; + + //TODO -- Make the routine that gets called variable based on configuration! + sadb_routine = get_sadb_routine_inmemory(); + //sadb_routine = get_sadb_routine_mariadb(); + + + // Initialize libgcrypt + if (!gcry_check_version(GCRYPT_VERSION)) + { + fprintf(stderr, "Gcrypt Version: %s",GCRYPT_VERSION); + OS_printf(KRED "\tERROR: gcrypt version mismatch! \n" RESET); + } + if (gcry_control(GCRYCTL_SELFTEST) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcrypt self test failed\n" RESET); + } + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + + // Init Security Associations + status = sadb_routine->sadb_init(); + status = sadb_routine->sadb_config(); + + Crypto_Local_Init(); + Crypto_Local_Config(); + + // TODO - Add error checking + + // Init table for CRC calculations + Crypto_Calc_CRC_Init_Table(); + + // cFS Standard Initialized Message + OS_printf (KBLU "Crypto Lib Intialized. Version %d.%d.%d.%d\n" RESET, + CRYPTO_LIB_MAJOR_VERSION, + CRYPTO_LIB_MINOR_VERSION, + CRYPTO_LIB_REVISION, + CRYPTO_LIB_MISSION_REV); + + return status; +} + +static void Crypto_Local_Config(void) +{ + // Initial TM configuration + tm_frame.tm_sec_header.spi = 1; + + // Initialize Log + log_summary.num_se = 2; + log_summary.rs = LOG_SIZE; + // Add a two messages to the log + log_summary.rs--; + log.blk[log_count].emt = STARTUP; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + log_summary.rs--; + log.blk[log_count].emt = STARTUP; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + + // Master Keys + // 0 - 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F -> ACTIVE + ek_ring[0].value[0] = 0x00; + ek_ring[0].value[1] = 0x01; + ek_ring[0].value[2] = 0x02; + ek_ring[0].value[3] = 0x03; + ek_ring[0].value[4] = 0x04; + ek_ring[0].value[5] = 0x05; + ek_ring[0].value[6] = 0x06; + ek_ring[0].value[7] = 0x07; + ek_ring[0].value[8] = 0x08; + ek_ring[0].value[9] = 0x09; + ek_ring[0].value[10] = 0x0A; + ek_ring[0].value[11] = 0x0B; + ek_ring[0].value[12] = 0x0C; + ek_ring[0].value[13] = 0x0D; + ek_ring[0].value[14] = 0x0E; + ek_ring[0].value[15] = 0x0F; + ek_ring[0].value[16] = 0x00; + ek_ring[0].value[17] = 0x01; + ek_ring[0].value[18] = 0x02; + ek_ring[0].value[19] = 0x03; + ek_ring[0].value[20] = 0x04; + ek_ring[0].value[21] = 0x05; + ek_ring[0].value[22] = 0x06; + ek_ring[0].value[23] = 0x07; + ek_ring[0].value[24] = 0x08; + ek_ring[0].value[25] = 0x09; + ek_ring[0].value[26] = 0x0A; + ek_ring[0].value[27] = 0x0B; + ek_ring[0].value[28] = 0x0C; + ek_ring[0].value[29] = 0x0D; + ek_ring[0].value[30] = 0x0E; + ek_ring[0].value[31] = 0x0F; + ek_ring[0].key_state = KEY_ACTIVE; + // 1 - 101112131415161718191A1B1C1D1E1F101112131415161718191A1B1C1D1E1F -> ACTIVE + ek_ring[1].value[0] = 0x10; + ek_ring[1].value[1] = 0x11; + ek_ring[1].value[2] = 0x12; + ek_ring[1].value[3] = 0x13; + ek_ring[1].value[4] = 0x14; + ek_ring[1].value[5] = 0x15; + ek_ring[1].value[6] = 0x16; + ek_ring[1].value[7] = 0x17; + ek_ring[1].value[8] = 0x18; + ek_ring[1].value[9] = 0x19; + ek_ring[1].value[10] = 0x1A; + ek_ring[1].value[11] = 0x1B; + ek_ring[1].value[12] = 0x1C; + ek_ring[1].value[13] = 0x1D; + ek_ring[1].value[14] = 0x1E; + ek_ring[1].value[15] = 0x1F; + ek_ring[1].value[16] = 0x10; + ek_ring[1].value[17] = 0x11; + ek_ring[1].value[18] = 0x12; + ek_ring[1].value[19] = 0x13; + ek_ring[1].value[20] = 0x14; + ek_ring[1].value[21] = 0x15; + ek_ring[1].value[22] = 0x16; + ek_ring[1].value[23] = 0x17; + ek_ring[1].value[24] = 0x18; + ek_ring[1].value[25] = 0x19; + ek_ring[1].value[26] = 0x1A; + ek_ring[1].value[27] = 0x1B; + ek_ring[1].value[28] = 0x1C; + ek_ring[1].value[29] = 0x1D; + ek_ring[1].value[30] = 0x1E; + ek_ring[1].value[31] = 0x1F; + ek_ring[1].key_state = KEY_ACTIVE; + // 2 - 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F -> ACTIVE + ek_ring[2].value[0] = 0x20; + ek_ring[2].value[1] = 0x21; + ek_ring[2].value[2] = 0x22; + ek_ring[2].value[3] = 0x23; + ek_ring[2].value[4] = 0x24; + ek_ring[2].value[5] = 0x25; + ek_ring[2].value[6] = 0x26; + ek_ring[2].value[7] = 0x27; + ek_ring[2].value[8] = 0x28; + ek_ring[2].value[9] = 0x29; + ek_ring[2].value[10] = 0x2A; + ek_ring[2].value[11] = 0x2B; + ek_ring[2].value[12] = 0x2C; + ek_ring[2].value[13] = 0x2D; + ek_ring[2].value[14] = 0x2E; + ek_ring[2].value[15] = 0x2F; + ek_ring[2].value[16] = 0x20; + ek_ring[2].value[17] = 0x21; + ek_ring[2].value[18] = 0x22; + ek_ring[2].value[19] = 0x23; + ek_ring[2].value[20] = 0x24; + ek_ring[2].value[21] = 0x25; + ek_ring[2].value[22] = 0x26; + ek_ring[2].value[23] = 0x27; + ek_ring[2].value[24] = 0x28; + ek_ring[2].value[25] = 0x29; + ek_ring[2].value[26] = 0x2A; + ek_ring[2].value[27] = 0x2B; + ek_ring[2].value[28] = 0x2C; + ek_ring[2].value[29] = 0x2D; + ek_ring[2].value[30] = 0x2E; + ek_ring[2].value[31] = 0x2F; + ek_ring[2].key_state = KEY_ACTIVE; + + // Session Keys + // 128 - 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -> ACTIVE + ek_ring[128].value[0] = 0x01; + ek_ring[128].value[1] = 0x23; + ek_ring[128].value[2] = 0x45; + ek_ring[128].value[3] = 0x67; + ek_ring[128].value[4] = 0x89; + ek_ring[128].value[5] = 0xAB; + ek_ring[128].value[6] = 0xCD; + ek_ring[128].value[7] = 0xEF; + ek_ring[128].value[8] = 0x01; + ek_ring[128].value[9] = 0x23; + ek_ring[128].value[10] = 0x45; + ek_ring[128].value[11] = 0x67; + ek_ring[128].value[12] = 0x89; + ek_ring[128].value[13] = 0xAB; + ek_ring[128].value[14] = 0xCD; + ek_ring[128].value[15] = 0xEF; + ek_ring[128].value[16] = 0x01; + ek_ring[128].value[17] = 0x23; + ek_ring[128].value[18] = 0x45; + ek_ring[128].value[19] = 0x67; + ek_ring[128].value[20] = 0x89; + ek_ring[128].value[21] = 0xAB; + ek_ring[128].value[22] = 0xCD; + ek_ring[128].value[23] = 0xEF; + ek_ring[128].value[24] = 0x01; + ek_ring[128].value[25] = 0x23; + ek_ring[128].value[26] = 0x45; + ek_ring[128].value[27] = 0x67; + ek_ring[128].value[28] = 0x89; + ek_ring[128].value[29] = 0xAB; + ek_ring[128].value[30] = 0xCD; + ek_ring[128].value[31] = 0xEF; + ek_ring[128].key_state = KEY_ACTIVE; + // 129 - ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 -> ACTIVE + ek_ring[129].value[0] = 0xAB; + ek_ring[129].value[1] = 0xCD; + ek_ring[129].value[2] = 0xEF; + ek_ring[129].value[3] = 0x01; + ek_ring[129].value[4] = 0x23; + ek_ring[129].value[5] = 0x45; + ek_ring[129].value[6] = 0x67; + ek_ring[129].value[7] = 0x89; + ek_ring[129].value[8] = 0xAB; + ek_ring[129].value[9] = 0xCD; + ek_ring[129].value[10] = 0xEF; + ek_ring[129].value[11] = 0x01; + ek_ring[129].value[12] = 0x23; + ek_ring[129].value[13] = 0x45; + ek_ring[129].value[14] = 0x67; + ek_ring[129].value[15] = 0x89; + ek_ring[129].value[16] = 0xAB; + ek_ring[129].value[17] = 0xCD; + ek_ring[129].value[18] = 0xEF; + ek_ring[129].value[19] = 0x01; + ek_ring[129].value[20] = 0x23; + ek_ring[129].value[21] = 0x45; + ek_ring[129].value[22] = 0x67; + ek_ring[129].value[23] = 0x89; + ek_ring[129].value[24] = 0xAB; + ek_ring[129].value[25] = 0xCD; + ek_ring[129].value[26] = 0xEF; + ek_ring[129].value[27] = 0x01; + ek_ring[129].value[28] = 0x23; + ek_ring[129].value[29] = 0x45; + ek_ring[129].value[30] = 0x67; + ek_ring[129].value[31] = 0x89; + ek_ring[129].key_state = KEY_ACTIVE; + // 130 - FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210 -> ACTIVE + ek_ring[130].value[0] = 0xFE; + ek_ring[130].value[1] = 0xDC; + ek_ring[130].value[2] = 0xBA; + ek_ring[130].value[3] = 0x98; + ek_ring[130].value[4] = 0x76; + ek_ring[130].value[5] = 0x54; + ek_ring[130].value[6] = 0x32; + ek_ring[130].value[7] = 0x10; + ek_ring[130].value[8] = 0xFE; + ek_ring[130].value[9] = 0xDC; + ek_ring[130].value[10] = 0xBA; + ek_ring[130].value[11] = 0x98; + ek_ring[130].value[12] = 0x76; + ek_ring[130].value[13] = 0x54; + ek_ring[130].value[14] = 0x32; + ek_ring[130].value[15] = 0x10; + ek_ring[130].value[16] = 0xFE; + ek_ring[130].value[17] = 0xDC; + ek_ring[130].value[18] = 0xBA; + ek_ring[130].value[19] = 0x98; + ek_ring[130].value[20] = 0x76; + ek_ring[130].value[21] = 0x54; + ek_ring[130].value[22] = 0x32; + ek_ring[130].value[23] = 0x10; + ek_ring[130].value[24] = 0xFE; + ek_ring[130].value[25] = 0xDC; + ek_ring[130].value[26] = 0xBA; + ek_ring[130].value[27] = 0x98; + ek_ring[130].value[28] = 0x76; + ek_ring[130].value[29] = 0x54; + ek_ring[130].value[30] = 0x32; + ek_ring[130].value[31] = 0x10; + ek_ring[130].key_state = KEY_ACTIVE; + // 131 - 9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA -> ACTIVE + ek_ring[131].value[0] = 0x98; + ek_ring[131].value[1] = 0x76; + ek_ring[131].value[2] = 0x54; + ek_ring[131].value[3] = 0x32; + ek_ring[131].value[4] = 0x10; + ek_ring[131].value[5] = 0xFE; + ek_ring[131].value[6] = 0xDC; + ek_ring[131].value[7] = 0xBA; + ek_ring[131].value[8] = 0x98; + ek_ring[131].value[9] = 0x76; + ek_ring[131].value[10] = 0x54; + ek_ring[131].value[11] = 0x32; + ek_ring[131].value[12] = 0x10; + ek_ring[131].value[13] = 0xFE; + ek_ring[131].value[14] = 0xDC; + ek_ring[131].value[15] = 0xBA; + ek_ring[131].value[16] = 0x98; + ek_ring[131].value[17] = 0x76; + ek_ring[131].value[18] = 0x54; + ek_ring[131].value[19] = 0x32; + ek_ring[131].value[20] = 0x10; + ek_ring[131].value[21] = 0xFE; + ek_ring[131].value[22] = 0xDC; + ek_ring[131].value[23] = 0xBA; + ek_ring[131].value[24] = 0x98; + ek_ring[131].value[25] = 0x76; + ek_ring[131].value[26] = 0x54; + ek_ring[131].value[27] = 0x32; + ek_ring[131].value[28] = 0x10; + ek_ring[131].value[29] = 0xFE; + ek_ring[131].value[30] = 0xDC; + ek_ring[131].value[31] = 0xBA; + ek_ring[131].key_state = KEY_ACTIVE; + // 132 - 0123456789ABCDEFABCDEF01234567890123456789ABCDEFABCDEF0123456789 -> PRE_ACTIVATION + ek_ring[132].value[0] = 0x01; + ek_ring[132].value[1] = 0x23; + ek_ring[132].value[2] = 0x45; + ek_ring[132].value[3] = 0x67; + ek_ring[132].value[4] = 0x89; + ek_ring[132].value[5] = 0xAB; + ek_ring[132].value[6] = 0xCD; + ek_ring[132].value[7] = 0xEF; + ek_ring[132].value[8] = 0xAB; + ek_ring[132].value[9] = 0xCD; + ek_ring[132].value[10] = 0xEF; + ek_ring[132].value[11] = 0x01; + ek_ring[132].value[12] = 0x23; + ek_ring[132].value[13] = 0x45; + ek_ring[132].value[14] = 0x67; + ek_ring[132].value[15] = 0x89; + ek_ring[132].value[16] = 0x01; + ek_ring[132].value[17] = 0x23; + ek_ring[132].value[18] = 0x45; + ek_ring[132].value[19] = 0x67; + ek_ring[132].value[20] = 0x89; + ek_ring[132].value[21] = 0xAB; + ek_ring[132].value[22] = 0xCD; + ek_ring[132].value[23] = 0xEF; + ek_ring[132].value[24] = 0xAB; + ek_ring[132].value[25] = 0xCD; + ek_ring[132].value[26] = 0xEF; + ek_ring[132].value[27] = 0x01; + ek_ring[132].value[28] = 0x23; + ek_ring[132].value[29] = 0x45; + ek_ring[132].value[30] = 0x67; + ek_ring[132].value[31] = 0x89; + ek_ring[132].key_state = KEY_PREACTIVE; + // 133 - ABCDEF01234567890123456789ABCDEFABCDEF01234567890123456789ABCDEF -> ACTIVE + ek_ring[133].value[0] = 0xAB; + ek_ring[133].value[1] = 0xCD; + ek_ring[133].value[2] = 0xEF; + ek_ring[133].value[3] = 0x01; + ek_ring[133].value[4] = 0x23; + ek_ring[133].value[5] = 0x45; + ek_ring[133].value[6] = 0x67; + ek_ring[133].value[7] = 0x89; + ek_ring[133].value[8] = 0x01; + ek_ring[133].value[9] = 0x23; + ek_ring[133].value[10] = 0x45; + ek_ring[133].value[11] = 0x67; + ek_ring[133].value[12] = 0x89; + ek_ring[133].value[13] = 0xAB; + ek_ring[133].value[14] = 0xCD; + ek_ring[133].value[15] = 0xEF; + ek_ring[133].value[16] = 0xAB; + ek_ring[133].value[17] = 0xCD; + ek_ring[133].value[18] = 0xEF; + ek_ring[133].value[19] = 0x01; + ek_ring[133].value[20] = 0x23; + ek_ring[133].value[21] = 0x45; + ek_ring[133].value[22] = 0x67; + ek_ring[133].value[23] = 0x89; + ek_ring[133].value[24] = 0x01; + ek_ring[133].value[25] = 0x23; + ek_ring[133].value[26] = 0x45; + ek_ring[133].value[27] = 0x67; + ek_ring[133].value[28] = 0x89; + ek_ring[133].value[29] = 0xAB; + ek_ring[133].value[30] = 0xCD; + ek_ring[133].value[31] = 0xEF; + ek_ring[133].key_state = KEY_ACTIVE; + // 134 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE + ek_ring[134].value[0] = 0xAB; + ek_ring[134].value[1] = 0xCD; + ek_ring[134].value[2] = 0xEF; + ek_ring[134].value[3] = 0x01; + ek_ring[134].value[4] = 0x23; + ek_ring[134].value[5] = 0x45; + ek_ring[134].value[6] = 0x67; + ek_ring[134].value[7] = 0x89; + ek_ring[134].value[8] = 0xFE; + ek_ring[134].value[9] = 0xDC; + ek_ring[134].value[10] = 0xBA; + ek_ring[134].value[11] = 0x98; + ek_ring[134].value[12] = 0x76; + ek_ring[134].value[13] = 0x54; + ek_ring[134].value[14] = 0x32; + ek_ring[134].value[15] = 0x10; + ek_ring[134].value[16] = 0xAB; + ek_ring[134].value[17] = 0xCD; + ek_ring[134].value[18] = 0xEF; + ek_ring[134].value[19] = 0x01; + ek_ring[134].value[20] = 0x23; + ek_ring[134].value[21] = 0x45; + ek_ring[134].value[22] = 0x67; + ek_ring[134].value[23] = 0x89; + ek_ring[134].value[24] = 0xFE; + ek_ring[134].value[25] = 0xDC; + ek_ring[134].value[26] = 0xBA; + ek_ring[134].value[27] = 0x98; + ek_ring[134].value[28] = 0x76; + ek_ring[134].value[29] = 0x54; + ek_ring[134].value[30] = 0x32; + ek_ring[134].value[31] = 0x10; + ek_ring[134].key_state = KEY_DEACTIVATED; +} + +static void Crypto_Local_Init(void) +{ + + // Initialize TM Frame + // TM Header + tm_frame.tm_header.tfvn = 0; // Shall be 00 for TM-/TC-SDLP + tm_frame.tm_header.scid = SCID & 0x3FF; + tm_frame.tm_header.vcid = 0; + tm_frame.tm_header.ocff = 1; + tm_frame.tm_header.mcfc = 1; + tm_frame.tm_header.vcfc = 1; + tm_frame.tm_header.tfsh = 0; + tm_frame.tm_header.sf = 0; + tm_frame.tm_header.pof = 0; // Shall be set to 0 + tm_frame.tm_header.slid = 3; // Shall be set to 11 + tm_frame.tm_header.fhp = 0; + // TM Security Header + tm_frame.tm_sec_header.spi = 0x0000; + for ( int x = 0; x < IV_SIZE; x++) + { // Initialization Vector + tm_frame.tm_sec_header.iv[x] = 0x00; + } + // TM Payload Data Unit + for ( int x = 0; x < TM_FRAME_DATA_SIZE; x++) + { // Zero TM PDU + tm_frame.tm_pdu[x] = 0x00; + } + // TM Security Trailer + for ( int x = 0; x < MAC_SIZE; x++) + { // Zero TM Message Authentication Code + tm_frame.tm_sec_trailer.mac[x] = 0x00; + } + for ( int x = 0; x < OCF_SIZE; x++) + { // Zero TM Operational Control Field + tm_frame.tm_sec_trailer.ocf[x] = 0x00; + } + tm_frame.tm_sec_trailer.fecf = 0xFECF; + + // Initialize CLCW + clcw.cwt = 0; // Control Word Type "0" + clcw.cvn = 0; // CLCW Version Number "00" + clcw.sf = 0; // Status Field + clcw.cie = 1; // COP In Effect + clcw.vci = 0; // Virtual Channel Identification + clcw.spare0 = 0; // Reserved Spare + clcw.nrfa = 0; // No RF Avaliable Flag + clcw.nbl = 0; // No Bit Lock Flag + clcw.lo = 0; // Lock-Out Flag + clcw.wait = 0; // Wait Flag + clcw.rt = 0; // Retransmit Flag + clcw.fbc = 0; // FARM-B Counter + clcw.spare1 = 0; // Reserved Spare + clcw.rv = 0; // Report Value + + // Initialize Frame Security Report + report.cwt = 1; // Control Word Type "0b1"" + report.vnum = 4; // FSR Version "0b100"" + report.af = 0; // Alarm Field + report.bsnf = 0; // Bad SN Flag + report.bmacf = 0; // Bad MAC Flag + report.ispif = 0; // Invalid SPI Flag + report.lspiu = 0; // Last SPI Used + report.snval = 0; // SN Value (LSB) + +} + +static void Crypto_Calc_CRC_Init_Table(void) +{ + uint16 val; + uint32 poly = 0xEDB88320; + uint32 crc; + + // http://create.stephan-brumme.com/crc32/ + for (unsigned int i = 0; i <= 0xFF; i++) + { + crc = i; + for (unsigned int j = 0; j < 8; j++) + { + crc = (crc >> 1) ^ (-(int)(crc & 1) & poly); + } + crc32Table[i] = crc; + //OS_printf("crc32Table[%d] = 0x%08x \n", i, crc32Table[i]); + } + + // Code provided by ESA + for (int i = 0; i < 256; i++) + { + val = 0; + if ( (i & 1) != 0 ) val ^= 0x1021; + if ( (i & 2) != 0 ) val ^= 0x2042; + if ( (i & 4) != 0 ) val ^= 0x4084; + if ( (i & 8) != 0 ) val ^= 0x8108; + if ( (i & 16) != 0 ) val ^= 0x1231; + if ( (i & 32) != 0 ) val ^= 0x2462; + if ( (i & 64) != 0 ) val ^= 0x48C4; + if ( (i & 128) != 0 ) val ^= 0x9188; + crc16Table[i] = val; + //OS_printf("crc16Table[%d] = 0x%04x \n", i, crc16Table[i]); + } +} + +/* +** Assisting Functions +*/ +static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame) +// Returns the payload length of current tc_frame in BYTES! +{ + int seg_hdr = 0;if(SEGMENTATION_HDR){seg_hdr=1;} + int fecf = 0;if(HAS_FECF){fecf=FECF_SIZE;} + int spi = 2; + int iv_size = IV_SIZE_TC; if(PUS_HDR){iv_size=IV_SIZE - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. + int tf_hdr = 5; + + return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (MAC_SIZE + FECF_SIZE) ); + //return (tc_frame->tc_header.fl - (5 + 2 + IV_SIZE ) - (MAC_SIZE + FECF_SIZE) ); + //TFHDR=5bytes, SegHdr=1byte,SPI=2bytes,SeqNum=4bytes,MAC=16bytes,FECF=2bytes -- should be 30 bytes max, above calculation seems incorrect. +} + +static int32 Crypto_Get_tmLength(int len) +// Returns the total length of the current tm_frame in BYTES! +{ + #ifdef FILL + len = TM_FILL_SIZE; + #else + len = TM_FRAME_PRIMARYHEADER_SIZE + TM_FRAME_SECHEADER_SIZE + len + TM_FRAME_SECTRAILER_SIZE + TM_FRAME_CLCW_SIZE; + #endif + + return len; +} + +static void Crypto_TM_updatePDU(char* ingest, int len_ingest) +// Update the Telemetry Payload Data Unit +{ // Copy ingest to PDU + int x = 0; + int fill_size = 0; + SecurityAssociation_t* sa_ptr; + + if(sadb_routine->sadb_get_sa_from_spi(tm_frame.tm_sec_header.spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return; //Error -- unable to get SA from SPI. + } + + if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) + { + fill_size = 1129 - MAC_SIZE - IV_SIZE + 2; // +2 for padding bytes + } + else + { + fill_size = 1129; + } + + #ifdef TM_ZERO_FILL + for (int x = 0; x < TM_FILL_SIZE; x++) + { + if (x < len_ingest) + { // Fill + tm_frame.tm_pdu[x] = (uint8)ingest[x]; + } + else + { // Zero + tm_frame.tm_pdu[x] = 0x00; + } + } + #else + // Pre-append remaining packet if exist + if (tm_offset == 63) + { + tm_frame.tm_pdu[x++] = 0xff; + tm_offset--; + } + if (tm_offset == 62) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (tm_offset == 61) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (tm_offset == 60) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (tm_offset == 59) + { + tm_frame.tm_pdu[x++] = 0x39; + tm_offset--; + } + while (x < tm_offset) + { + tm_frame.tm_pdu[x] = 0x00; + x++; + } + // Copy actual packet + while (x < len_ingest + tm_offset) + { + //OS_printf("ingest[x - tm_offset] = 0x%02x \n", (uint8)ingest[x - tm_offset]); + tm_frame.tm_pdu[x] = (uint8)ingest[x - tm_offset]; + x++; + } + #ifdef TM_IDLE_FILL + // Check for idle frame trigger + if (((uint8)ingest[0] == 0x08) && ((uint8)ingest[1] == 0x90)) + { + // Don't fill idle frames + } + else + { + while (x < (fill_size - 64) ) + { + tm_frame.tm_pdu[x++] = 0x07; + tm_frame.tm_pdu[x++] = 0xff; + tm_frame.tm_pdu[x++] = 0x00; + tm_frame.tm_pdu[x++] = 0x00; + tm_frame.tm_pdu[x++] = 0x00; + tm_frame.tm_pdu[x++] = 0x39; + for (int y = 0; y < 58; y++) + { + tm_frame.tm_pdu[x++] = 0x00; + } + } + // Add partial packet, if possible, and set offset + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x07; + tm_offset = 63; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0xff; + tm_offset--; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x39; + tm_offset--; + } + for (int y = 0; x < fill_size; y++) + { + tm_frame.tm_pdu[x++] = 00; + tm_offset--; + } + } + while (x < TM_FILL_SIZE) + { + tm_frame.tm_pdu[x++] = 0x00; + } + #endif + #endif + + return; +} + +static void Crypto_TM_updateOCF(void) +{ + if (ocf == 0) + { // CLCW + clcw.vci = tm_frame.tm_header.vcid; + + tm_frame.tm_sec_trailer.ocf[0] = (clcw.cwt << 7) | (clcw.cvn << 5) | (clcw.sf << 2) | (clcw.cie); + tm_frame.tm_sec_trailer.ocf[1] = (clcw.vci << 2) | (clcw.spare0); + tm_frame.tm_sec_trailer.ocf[2] = (clcw.nrfa << 7) | (clcw.nbl << 6) | (clcw.lo << 5) | (clcw.wait << 4) | (clcw.rt << 3) | (clcw.fbc << 1) | (clcw.spare1); + tm_frame.tm_sec_trailer.ocf[3] = (clcw.rv); + // Alternate OCF + ocf = 1; + #ifdef OCF_DEBUG + Crypto_clcwPrint(&clcw); + #endif + } + else + { // FSR + tm_frame.tm_sec_trailer.ocf[0] = (report.cwt << 7) | (report.vnum << 4) | (report.af << 3) | (report.bsnf << 2) | (report.bmacf << 1) | (report.ispif); + tm_frame.tm_sec_trailer.ocf[1] = (report.lspiu & 0xFF00) >> 8; + tm_frame.tm_sec_trailer.ocf[2] = (report.lspiu & 0x00FF); + tm_frame.tm_sec_trailer.ocf[3] = (report.snval); + // Alternate OCF + ocf = 0; + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + } +} + +//TODO - Review this. Not sure it quite works how we think +int32 Crypto_increment(uint8 *num, int length) +{ + int i; + /* go from right (least significant) to left (most signifcant) */ + for(i = length - 1; i >= 0; --i) + { + ++(num[i]); /* increment current byte */ + + if(num[i] != 0) /* if byte did not overflow, we're done! */ + break; + } + + if(i < 0) /* this means num[0] was incremented and overflowed */ + return OS_ERROR; + else + return OS_SUCCESS; +} + +static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window) +{ + int status = OS_ERROR; + int result = 0; + uint8 temp[length]; + + CFE_PSP_MemCpy(temp, expected, length); + + for (int i = 0; i < window; i++) + { + result = 0; + /* go from right (least significant) to left (most signifcant) */ + for (int j = length - 1; j >= 0; --j) + { + if (actual[j] == temp[j]) + { + result++; + } + } + if (result == length) + { + status = OS_SUCCESS; + break; + } + Crypto_increment(&temp[0], length); + } + return status; +} + +static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length) +{ + int status = OS_ERROR; + + for(int i = 0; i < length - 1; i++) + { + if (actual[i] > expected[i]) + { + status = OS_SUCCESS; + break; + } + else if (actual[i] < expected[i]) + { + status = OS_ERROR; + break; + } + } + return status; +} + +uint8 Crypto_Prep_Reply(char* ingest, uint8 appID) +// Assumes that both the pkt_length and pdu_len are set properly +{ + uint8 count = 0; + + // Prepare CCSDS for reply + sdls_frame.hdr.pvn = 0; + sdls_frame.hdr.type = 0; + sdls_frame.hdr.shdr = 1; + sdls_frame.hdr.appID = appID; + + sdls_frame.pdu.type = 1; + + // Fill ingest with reply header + ingest[count++] = (sdls_frame.hdr.pvn << 5) | (sdls_frame.hdr.type << 4) | (sdls_frame.hdr.shdr << 3) | ((sdls_frame.hdr.appID & 0x700 >> 8)); + ingest[count++] = (sdls_frame.hdr.appID & 0x00FF); + ingest[count++] = (sdls_frame.hdr.seq << 6) | ((sdls_frame.hdr.pktid & 0x3F00) >> 8); + ingest[count++] = (sdls_frame.hdr.pktid & 0x00FF); + ingest[count++] = (sdls_frame.hdr.pkt_length & 0xFF00) >> 8; + ingest[count++] = (sdls_frame.hdr.pkt_length & 0x00FF); + + // Fill ingest with PUS + //ingest[count++] = (sdls_frame.pus.shf << 7) | (sdls_frame.pus.pusv << 4) | (sdls_frame.pus.ack); + //ingest[count++] = (sdls_frame.pus.st); + //ingest[count++] = (sdls_frame.pus.sst); + //ingest[count++] = (sdls_frame.pus.sid << 4) | (sdls_frame.pus.spare); + + // Fill ingest with Tag and Length + ingest[count++] = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | (sdls_frame.pdu.pid); + ingest[count++] = (sdls_frame.pdu.pdu_len & 0xFF00) >> 8; + ingest[count++] = (sdls_frame.pdu.pdu_len & 0x00FF); + + return count; +} + +static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame) +// Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) +{ + int32 result = OS_SUCCESS; + uint16 calc_fecf = Crypto_Calc_FECF(ingest, len_ingest); + + if ( (fecf & 0xFFFF) != calc_fecf ) + { + if (((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) + { + // User packet check only used for ESA Testing! + } + else + { // TODO: Error Correction + OS_printf(KRED "Error: FECF incorrect!\n" RESET); + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = FECF_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + #ifdef FECF_DEBUG + OS_printf("\t Calculated = 0x%04x \n\t Received = 0x%04x \n", calc_fecf, tc_frame->tc_sec_trailer.fecf); + #endif + result = OS_ERROR; + } + } + + return result; +} + +static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest) +// Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) +{ + uint16 fecf = 0xFFFF; + uint16 poly = 0x1021; // TODO: This polynomial is (CRC-CCITT) for ESA testing, may not match standard protocol + uint8 bit; + uint8 c15; + + for (int i = 0; i <= len_ingest; i++) + { // Byte Logic + for (int j = 0; j < 8; j++) + { // Bit Logic + bit = ((ingest[i] >> (7 - j) & 1) == 1); + c15 = ((fecf >> 15 & 1) == 1); + fecf <<= 1; + if (c15 ^ bit) + { + fecf ^= poly; + } + } + } + + // Check if Testing + if (badFECF == 1) + { + fecf++; + } + + #ifdef FECF_DEBUG + OS_printf(KCYN "Crypto_Calc_FECF: 0x%02x%02x%02x%02x%02x, len_ingest = %d\n" RESET, ingest[0], ingest[1], ingest[2], ingest[3], ingest[4], len_ingest); + OS_printf(KCYN "0x" RESET); + for (int x = 0; x < len_ingest; x++) + { + OS_printf(KCYN "%02x" RESET, (uint8)*(ingest+x)); + } + OS_printf(KCYN "\n" RESET); + OS_printf(KCYN "In Crypto_Calc_FECF! fecf = 0x%04x\n" RESET, fecf); + #endif + + return fecf; +} + +static uint16 Crypto_Calc_CRC16(char* data, int size) +{ // Code provided by ESA + uint16 crc = 0xFFFF; + + for ( ; size > 0; size--) + { + //OS_printf("*data = 0x%02x \n", (uint8) *data); + crc = ((crc << 8) & 0xFF00) ^ crc16Table[(crc >> 8) ^ *data++]; + } + + return crc; +} + +/* +** Key Management Services +*/ +static int32 Crypto_Key_OTAR(void) +// The OTAR Rekeying procedure shall have the following Service Parameters: +// a- Key ID of the Master Key (Integer, unmanaged) +// b- Size of set of Upload Keys (Integer, managed) +// c- Set of Upload Keys (Integer[Session Key]; managed) +// NOTE- The size of the session keys is mission specific. +// a- Set of Key IDs of Upload Keys (Integer[Key IDs]; managed) +// b- Set of Encrypted Upload Keys (Integer[Size of set of Key ID]; unmanaged) +// c- Agreed Cryptographic Algorithm (managed) +{ + // Local variables + SDLS_OTAR_t packet; + int count = 0; + int x = 0; + int32 status = OS_SUCCESS; + int pdu_keys = (sdls_frame.pdu.pdu_len - 30) / (2 + KEY_SIZE); + + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + + // Master Key ID + packet.mkid = (sdls_frame.pdu.data[0] << 8) | (sdls_frame.pdu.data[1]); + + if (packet.mkid >= 128) + { + report.af = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = MKID_INVALID_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: MKID is not valid! \n" RESET); + status = OS_ERROR; + return status; + } + + for (int count = 2; count < (2 + IV_SIZE); count++) + { // Initialization Vector + packet.iv[count-2] = sdls_frame.pdu.data[count]; + //OS_printf("packet.iv[%d] = 0x%02x\n", count-2, packet.iv[count-2]); + } + + count = sdls_frame.pdu.pdu_len - MAC_SIZE; + for (int w = 0; w < 16; w++) + { // MAC + packet.mac[w] = sdls_frame.pdu.data[count + w]; + //OS_printf("packet.mac[%d] = 0x%02x\n", w, packet.mac[w]); + } + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[packet.mkid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(packet.iv[0]), + IV_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_decrypt( + tmp_hd, + &(sdls_frame.pdu.data[14]), // plaintext output + pdu_keys * (2 + KEY_SIZE), // length of data + NULL, // in place decryption + 0 // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_checktag( + tmp_hd, + &(packet.mac[0]), // tag input + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_cipher_close(tmp_hd); + + // Read in Decrypted Data + for (int count = 14; x < pdu_keys; x++) + { // Encrypted Key Blocks + packet.EKB[x].ekid = (sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1]); + if (packet.EKB[x].ekid < 128) + { + report.af = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = OTAR_MK_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; // N + log.blk[log_count].emv[1] = 0x41; // A + log.blk[log_count].emv[2] = 0x53; // S + log.blk[log_count].emv[3] = 0x41; // A + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: Cannot OTAR master key! \n" RESET); + status = OS_ERROR; + return status; + } + else + { + count = count + 2; + for (int y = count; y < (KEY_SIZE + count); y++) + { // Encrypted Key + packet.EKB[x].ek[y-count] = sdls_frame.pdu.data[y]; + #ifdef SA_DEBUG + OS_printf("\t packet.EKB[%d].ek[%d] = 0x%02x\n", x, y-count, packet.EKB[x].ek[y-count]); + #endif + + // Setup Key Ring + ek_ring[packet.EKB[x].ekid].value[y - count] = sdls_frame.pdu.data[y]; + } + count = count + KEY_SIZE; + + // Set state to PREACTIVE + ek_ring[packet.EKB[x].ekid].key_state = KEY_PREACTIVE; + } + } + + #ifdef PDU_DEBUG + OS_printf("Received %d keys via master key %d: \n", pdu_keys, packet.mkid); + for (int x = 0; x < pdu_keys; x++) + { + OS_printf("%d) Key ID = %d, 0x", x+1, packet.EKB[x].ekid); + for(int y = 0; y < KEY_SIZE; y++) + { + OS_printf("%02x", packet.EKB[x].ek[y]); + } + OS_printf("\n"); + } + #endif + + return OS_SUCCESS; +} + +static int32 Crypto_Key_update(uint8 state) +// Updates the state of the all keys in the received SDLS EP PDU +{ // Local variables + SDLS_KEY_BLK_t packet; + int count = 0; + int pdu_keys = sdls_frame.pdu.pdu_len / 2; + #ifdef PDU_DEBUG + OS_printf("Keys "); + #endif + // Read in PDU + for (int x = 0; x < pdu_keys; x++) + { + packet.kblk[x].kid = (sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1]); + count = count + 2; + #ifdef PDU_DEBUG + if (x != (pdu_keys - 1)) + { + OS_printf("%d, ", packet.kblk[x].kid); + } + else + { + OS_printf("and %d ", packet.kblk[x].kid); + } + #endif + } + #ifdef PDU_DEBUG + OS_printf("changed to state "); + switch (state) + { + case KEY_PREACTIVE: + OS_printf("PREACTIVE. \n"); + break; + case KEY_ACTIVE: + OS_printf("ACTIVE. \n"); + break; + case KEY_DEACTIVATED: + OS_printf("DEACTIVATED. \n"); + break; + case KEY_DESTROYED: + OS_printf("DESTROYED. \n"); + break; + case KEY_CORRUPTED: + OS_printf("CORRUPTED. \n"); + break; + default: + OS_printf("ERROR. \n"); + break; + } + #endif + // Update Key State + for (int x = 0; x < pdu_keys; x++) + { + if (packet.kblk[x].kid < 128) + { + report.af = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = MKID_STATE_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: MKID state cannot be changed! \n" RESET); + // TODO: Exit + } + + if (ek_ring[packet.kblk[x].kid].key_state == (state - 1)) + { + ek_ring[packet.kblk[x].kid].key_state = state; + #ifdef PDU_DEBUG + //OS_printf("Key ID %d state changed to ", packet.kblk[x].kid); + #endif + } + else + { + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = KEY_TRANSITION_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: Key %d cannot transition to desired state! \n" RESET, packet.kblk[x].kid); + } + } + return OS_SUCCESS; +} + +static int32 Crypto_Key_inventory(char* ingest) +{ + // Local variables + SDLS_KEY_INVENTORY_t packet; + int count = 0; + uint16_t range = 0; + + // Read in PDU + packet.kid_first = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); + count = count + 2; + packet.kid_last = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); + count = count + 2; + + // Prepare for Reply + range = packet.kid_last - packet.kid_first; + sdls_frame.pdu.pdu_len = 2 + (range * (2 + 1)); + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + ingest[count++] = (range & 0xFF00) >> 8; + ingest[count++] = (range & 0x00FF); + for (uint16_t x = packet.kid_first; x < packet.kid_last; x++) + { // Key ID + ingest[count++] = (x & 0xFF00) >> 8; + ingest[count++] = (x & 0x00FF); + // Key State + ingest[count++] = ek_ring[x].key_state; + } + return count; +} + +static int32 Crypto_Key_verify(char* ingest,TC_t* tc_frame) +{ + // Local variables + SDLS_KEYV_CMD_t packet; + int count = 0; + int pdu_keys = sdls_frame.pdu.pdu_len / SDLS_KEYV_CMD_BLK_SIZE; + + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + gcry_cipher_hd_t tmp_hd; + uint8 iv_loc; + + //uint8 tmp_mac[MAC_SIZE]; + + #ifdef PDU_DEBUG + OS_printf("Crypto_Key_verify: Requested %d key(s) to verify \n", pdu_keys); + #endif + + // Read in PDU + for (int x = 0; x < pdu_keys; x++) + { + // Key ID + packet.blk[x].kid = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); + count = count + 2; + #ifdef PDU_DEBUG + OS_printf("Crypto_Key_verify: Block %d Key ID is %d \n", x, packet.blk[x].kid); + #endif + // Key Challenge + for (int y = 0; y < CHALLENGE_SIZE; y++) + { + packet.blk[x].challenge[y] = sdls_frame.pdu.data[count++]; + } + #ifdef PDU_DEBUG + OS_printf("\n"); + #endif + } + + // Prepare for Reply + sdls_frame.pdu.pdu_len = pdu_keys * (2 + IV_SIZE + CHALLENGE_SIZE + CHALLENGE_MAC_SIZE); + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + for (int x = 0; x < pdu_keys; x++) + { // Key ID + ingest[count++] = (packet.blk[x].kid & 0xFF00) >> 8; + ingest[count++] = (packet.blk[x].kid & 0x00FF); + + // Initialization Vector + iv_loc = count; + for (int y = 0; y < IV_SIZE; y++) + { + ingest[count++] = tc_frame->tc_sec_header.iv[y]; + } + ingest[count-1] = ingest[count-1] + x + 1; + + // Encrypt challenge + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[packet.blk[x].kid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(ingest[iv_loc]), + IV_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + gcry_error = gcry_cipher_encrypt( + tmp_hd, + &(ingest[count]), // ciphertext output + CHALLENGE_SIZE, // length of data + &(packet.blk[x].challenge[0]), // plaintext input + CHALLENGE_SIZE // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + count = count + CHALLENGE_SIZE; // Don't forget to increment count! + + gcry_error = gcry_cipher_gettag( + tmp_hd, + &(ingest[count]), // tag output + CHALLENGE_MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_gettag error code %d \n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + count = count + CHALLENGE_MAC_SIZE; // Don't forget to increment count! + + // Copy from tmp_mac into ingest + //for( int y = 0; y < CHALLENGE_MAC_SIZE; y++) + //{ + // ingest[count++] = tmp_mac[y]; + //} + gcry_cipher_close(tmp_hd); + } + + #ifdef PDU_DEBUG + OS_printf("Crypto_Key_verify: Response is %d bytes \n", count); + #endif + + return count; +} + +/* + +/* +** Security Association Monitoring and Control +*/ +static int32 Crypto_MC_ping(char* ingest) +{ + int count = 0; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 0; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + return count; +} + +static int32 Crypto_MC_status(char* ingest) +{ + int count = 0; + + // TODO: Update log_summary.rs; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 2; // 4 + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + // PDU + //ingest[count++] = (log_summary.num_se & 0xFF00) >> 8; + ingest[count++] = (log_summary.num_se & 0x00FF); + //ingest[count++] = (log_summary.rs & 0xFF00) >> 8; + ingest[count++] = (log_summary.rs & 0x00FF); + + #ifdef PDU_DEBUG + OS_printf("log_summary.num_se = 0x%02x \n",log_summary.num_se); + OS_printf("log_summary.rs = 0x%02x \n",log_summary.rs); + #endif + + return count; +} + +static int32 Crypto_MC_dump(char* ingest) +{ + int count = 0; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = (log_count * 6); // SDLS_MC_DUMP_RPLY_SIZE + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + // PDU + for (int x = 0; x < log_count; x++) + { + ingest[count++] = log.blk[x].emt; + //ingest[count++] = (log.blk[x].em_len & 0xFF00) >> 8; + ingest[count++] = (log.blk[x].em_len & 0x00FF); + for (int y = 0; y < EMV_SIZE; y++) + { + ingest[count++] = log.blk[x].emv[y]; + } + } + + #ifdef PDU_DEBUG + OS_printf("log_count = %d \n", log_count); + OS_printf("log_summary.num_se = 0x%02x \n",log_summary.num_se); + OS_printf("log_summary.rs = 0x%02x \n",log_summary.rs); + #endif + + return count; +} + +static int32 Crypto_MC_erase(char* ingest) +{ + int count = 0; + + // Zero Logs + for (int x = 0; x < LOG_SIZE; x++) + { + log.blk[x].emt = 0; + log.blk[x].em_len = 0; + for (int y = 0; y < EMV_SIZE; y++) + { + log.blk[x].emv[y] = 0; + } + } + + // Compute Summary + log_count = 0; + log_summary.num_se = 0; + log_summary.rs = LOG_SIZE; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 2; // 4 + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + // PDU + //ingest[count++] = (log_summary.num_se & 0xFF00) >> 8; + ingest[count++] = (log_summary.num_se & 0x00FF); + //ingest[count++] = (log_summary.rs & 0xFF00) >> 8; + ingest[count++] = (log_summary.rs & 0x00FF); + + return count; +} + +static int32 Crypto_MC_selftest(char* ingest) +{ + uint8 count = 0; + uint8 result = ST_OK; + + // TODO: Perform test + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 1; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + ingest[count++] = result; + + return count; +} + +static int32 Crypto_SA_readARSN(char* ingest) +{ + uint8 count = 0; + uint16 spi = 0x0000; + SecurityAssociation_t* sa_ptr; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 2 + IV_SIZE; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + // Write SPI to reply + ingest[count++] = (spi & 0xFF00) >> 8; + ingest[count++] = (spi & 0x00FF); + + + if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } + + + if (sa_ptr->iv_len > 0) + { // Set IV - authenticated encryption + for (int x = 0; x < sa_ptr->iv_len - 1; x++) + { + ingest[count++] = sa_ptr->iv[x]; + } + + // TODO: Do we need this? + if (sa_ptr->iv[IV_SIZE - 1] > 0) + { // Adjust to report last received, not expected + ingest[count++] = sa_ptr->iv[IV_SIZE - 1] - 1; + } + else + { + ingest[count++] = sa_ptr->iv[IV_SIZE - 1]; + } + } + else + { + // TODO + } + + #ifdef PDU_DEBUG + OS_printf("spi = %d \n", spi); + if (sa_ptr->iv_len > 0) + { + OS_printf("ARSN = 0x"); + for (int x = 0; x < sa_ptr->iv_len; x++) + { + OS_printf("%02x", sa_ptr->iv[x]); + } + OS_printf("\n"); + } + #endif + + return count; +} + +static int32 Crypto_MC_resetalarm(void) +{ // Reset all alarm flags + report.af = 0; + report.bsnf = 0; + report.bmacf = 0; + report.ispif = 0; + return OS_SUCCESS; +} + +static int32 Crypto_User_IdleTrigger(char* ingest) +{ + uint8 count = 0; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 0; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 144); + + return count; +} + +static int32 Crypto_User_BadSPI(void) +{ + // Toggle Bad Sequence Number + if (badSPI == 0) + { + badSPI = 1; + } + else + { + badSPI = 0; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_BadMAC(void) +{ + // Toggle Bad MAC + if (badMAC == 0) + { + badMAC = 1; + } + else + { + badMAC = 0; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_BadIV(void) +{ + // Toggle Bad MAC + if (badIV == 0) + { + badIV = 1; + } + else + { + badIV = 0; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_BadFECF(void) +{ + // Toggle Bad FECF + if (badFECF == 0) + { + badFECF = 1; + } + else + { + badFECF = 0; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_ModifyKey(void) +{ + // Local variables + uint16 kid = ((uint8)sdls_frame.pdu.data[0] << 8) | ((uint8)sdls_frame.pdu.data[1]); + uint8 mod = (uint8)sdls_frame.pdu.data[2]; + + switch (mod) + { + case 1: // Invalidate Key + ek_ring[kid].value[KEY_SIZE-1]++; + OS_printf("Key %d value invalidated! \n", kid); + break; + case 2: // Modify key state + ek_ring[kid].key_state = (uint8)sdls_frame.pdu.data[3] & 0x0F; + OS_printf("Key %d state changed to %d! \n", kid, mod); + break; + default: + // Error + break; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_ModifyActiveTM(void) +{ + tm_frame.tm_sec_header.spi = (uint8)sdls_frame.pdu.data[0]; + return OS_SUCCESS; +} + +static int32 Crypto_User_ModifyVCID(void) +{ + tm_frame.tm_header.vcid = (uint8)sdls_frame.pdu.data[0]; + SecurityAssociation_t* sa_ptr; + + for (int i = 0; i < NUM_GVCID; i++) + { + if(sadb_routine->sadb_get_sa_from_spi(i,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } + for (int j = 0; j < NUM_SA; j++) + { + + if (sa_ptr->gvcid_tm_blk[j].mapid == TYPE_TM) + { + if (sa_ptr->gvcid_tm_blk[j].vcid == tm_frame.tm_header.vcid) + { + tm_frame.tm_sec_header.spi = i; + OS_printf("TM Frame SPI changed to %d \n",i); + break; + } + } + } + } + + return OS_SUCCESS; +} + +/* +** Procedures Specifications +*/ +static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) +{ + int32 status = OS_SUCCESS; + + switch (sdls_frame.pdu.type) + { + case 0: // Command + switch (sdls_frame.pdu.uf) + { + case 0: // CCSDS Defined Command + switch (sdls_frame.pdu.sg) + { + case SG_KEY_MGMT: // Key Management Procedure + switch (sdls_frame.pdu.pid) + { + case PID_OTAR: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key OTAR\n" RESET); + #endif + status = Crypto_Key_OTAR(); + break; + case PID_KEY_ACTIVATION: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Activate\n" RESET); + #endif + status = Crypto_Key_update(KEY_ACTIVE); + break; + case PID_KEY_DEACTIVATION: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Deactivate\n" RESET); + #endif + status = Crypto_Key_update(KEY_DEACTIVATED); + break; + case PID_KEY_VERIFICATION: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Verify\n" RESET); + #endif + status = Crypto_Key_verify(ingest,tc_frame); + break; + case PID_KEY_DESTRUCTION: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Destroy\n" RESET); + #endif + status = Crypto_Key_update(KEY_DESTROYED); + break; + case PID_KEY_INVENTORY: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Inventory\n" RESET); + #endif + status = Crypto_Key_inventory(ingest); + break; + default: + OS_printf(KRED "Error: Crypto_PDU failed interpreting Key Management Procedure Identification Field! \n" RESET); + break; + } + break; + case SG_SA_MGMT: // Security Association Management Procedure + switch (sdls_frame.pdu.pid) + { + case PID_CREATE_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Create\n" RESET); + #endif + status = sadb_routine->sadb_sa_create(); + break; + case PID_DELETE_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Delete\n" RESET); + #endif + status = sadb_routine->sadb_sa_delete(); + break; + case PID_SET_ARSNW: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA setARSNW\n" RESET); + #endif + status = sadb_routine->sadb_sa_setARSNW(); + break; + case PID_REKEY_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Rekey\n" RESET); + #endif + status = sadb_routine->sadb_sa_rekey(); + break; + case PID_EXPIRE_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Expire\n" RESET); + #endif + status = sadb_routine->sadb_sa_expire(); + break; + case PID_SET_ARSN: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA SetARSN\n" RESET); + #endif + status = sadb_routine->sadb_sa_setARSN(); + break; + case PID_START_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Start\n" RESET); + #endif + status = sadb_routine->sadb_sa_start(tc_frame); + break; + case PID_STOP_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Stop\n" RESET); + #endif + status = sadb_routine->sadb_sa_stop(); + break; + case PID_READ_ARSN: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA readARSN\n" RESET); + #endif + status = Crypto_SA_readARSN(ingest); + break; + case PID_SA_STATUS: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Status\n" RESET); + #endif + status = sadb_routine->sadb_sa_status(ingest); + break; + default: + OS_printf(KRED "Error: Crypto_PDU failed interpreting SA Procedure Identification Field! \n" RESET); + break; + } + break; + case SG_SEC_MON_CTRL: // Security Monitoring & Control Procedure + switch (sdls_frame.pdu.pid) + { + case PID_PING: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Ping\n" RESET); + #endif + status = Crypto_MC_ping(ingest); + break; + case PID_LOG_STATUS: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Status\n" RESET); + #endif + status = Crypto_MC_status(ingest); + break; + case PID_DUMP_LOG: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Dump\n" RESET); + #endif + status = Crypto_MC_dump(ingest); + break; + case PID_ERASE_LOG: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Erase\n" RESET); + #endif + status = Crypto_MC_erase(ingest); + break; + case PID_SELF_TEST: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Selftest\n" RESET); + #endif + status = Crypto_MC_selftest(ingest); + break; + case PID_ALARM_FLAG: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Reset Alarm\n" RESET); + #endif + status = Crypto_MC_resetalarm(); + break; + default: + OS_printf(KRED "Error: Crypto_PDU failed interpreting MC Procedure Identification Field! \n" RESET); + break; + } + break; + default: // ERROR + OS_printf(KRED "Error: Crypto_PDU failed interpreting Service Group! \n" RESET); + break; + } + break; + + case 1: // User Defined Command + switch (sdls_frame.pdu.sg) + { + default: + switch (sdls_frame.pdu.pid) + { + case 0: // Idle Frame Trigger + #ifdef PDU_DEBUG + OS_printf(KMAG "User Idle Trigger\n" RESET); + #endif + status = Crypto_User_IdleTrigger(ingest); + break; + case 1: // Toggle Bad SPI + #ifdef PDU_DEBUG + OS_printf(KMAG "User Toggle Bad SPI\n" RESET); + #endif + status = Crypto_User_BadSPI(); + break; + case 2: // Toggle Bad IV + #ifdef PDU_DEBUG + OS_printf(KMAG "User Toggle Bad IV\n" RESET); + #endif + status = Crypto_User_BadIV();\ + break; + case 3: // Toggle Bad MAC + #ifdef PDU_DEBUG + OS_printf(KMAG "User Toggle Bad MAC\n" RESET); + #endif + status = Crypto_User_BadMAC(); + break; + case 4: // Toggle Bad FECF + #ifdef PDU_DEBUG + OS_printf(KMAG "User Toggle Bad FECF\n" RESET); + #endif + status = Crypto_User_BadFECF(); + break; + case 5: // Modify Key + #ifdef PDU_DEBUG + OS_printf(KMAG "User Modify Key\n" RESET); + #endif + status = Crypto_User_ModifyKey(); + break; + case 6: // Modify ActiveTM + #ifdef PDU_DEBUG + OS_printf(KMAG "User Modify Active TM\n" RESET); + #endif + status = Crypto_User_ModifyActiveTM(); + break; + case 7: // Modify TM VCID + #ifdef PDU_DEBUG + OS_printf(KMAG "User Modify VCID\n" RESET); + #endif + status = Crypto_User_ModifyVCID(); + break; + default: + OS_printf(KRED "Error: Crypto_PDU received user defined command! \n" RESET); + break; + } + } + break; + } + break; + + case 1: // Reply + OS_printf(KRED "Error: Crypto_PDU failed interpreting PDU Type! Received a Reply!?! \n" RESET); + break; + } + + #ifdef CCSDS_DEBUG + if (status > 0) + { + OS_printf(KMAG "CCSDS message put on software bus: 0x" RESET); + for (int x = 0; x < status; x++) + { + OS_printf(KMAG "%02x" RESET, (uint8) ingest[x]); + } + OS_printf("\n"); + } + #endif + + return status; +} +int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ + uint8 **pp_in_frame, uint16 *p_enc_frame_len) +{ + // Local Variables + int32 status = OS_SUCCESS; + TC_FramePrimaryHeader_t temp_tc_header; + SecurityAssociation_t* sa_ptr = NULL; + uint8 *p_new_enc_frame = NULL; + uint8 sa_service_type = -1; + uint16 mac_loc = 0; + uint16 tf_payload_len = 0x0000; + uint16 new_fecf = 0x0000; + uint8 aad[20]; + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); + #endif + + #ifdef DEBUG + OS_printf("%d TF Bytes received\n", in_frame_length); + OS_printf("DEBUG - "); + for(int i=0; i < in_frame_length; i++) + { + OS_printf("%02X", ((uint8 *)&*p_in_frame)[i]); + } + OS_printf("\nPrinted %d bytes\n", in_frame_length); + #endif + + // Primary Header + temp_tc_header.tfvn = ((uint8)p_in_frame[0] & 0xC0) >> 6; + temp_tc_header.bypass = ((uint8)p_in_frame[0] & 0x20) >> 5; + temp_tc_header.cc = ((uint8)p_in_frame[0] & 0x10) >> 4; + temp_tc_header.spare = ((uint8)p_in_frame[0] & 0x0C) >> 2; + temp_tc_header.scid = ((uint8)p_in_frame[0] & 0x03) << 8; + temp_tc_header.scid = temp_tc_header.scid | (uint8)p_in_frame[1]; + temp_tc_header.vcid = ((uint8)p_in_frame[2] & 0xFC) >> 2 & VCID_BITMASK; + temp_tc_header.fl = ((uint8)p_in_frame[2] & 0x03) << 8; + temp_tc_header.fl = temp_tc_header.fl | (uint8)p_in_frame[3]; + temp_tc_header.fsn = (uint8)p_in_frame[4]; + + //TODO -- Handle segmentation header logic (this is a per-VCID managed parameter!) + //If segmentation header for VCID, parse out MAP_ID + // probably need to augment crypto_structs.h to handle segmentation headers. + uint8 map_id = 0; + + // Check if command frame flag set + if (temp_tc_header.cc == 1) + { + /* + ** CCSDS 232.0-B-3 + ** Section 6.3.1 + ** "Type-C frames do not have the Security Header and Security Trailer." + */ + #ifdef TC_DEBUG + OS_printf(KYEL "DEBUG - Received Control/Command frame - nothing to do.\n" RESET); + #endif + status = OS_ERROR; + } + + // TODO: If command frame flag not set, need to know SDLS parameters + // What is the best way to do this - copy in the entire SA for a channel? + // Expect these calls will return an error is the SA is not usable + // Will need to know lengths of various parameters from the SA DB + if (status == OS_SUCCESS) + { + // Query SA DB for active SA / SDLS parameters + status = sadb_routine->sadb_get_operational_sa_from_gvcid(temp_tc_header.tfvn, temp_tc_header.scid, temp_tc_header.vcid, map_id,&sa_ptr); + + // If unable to get operational SA, can return + if (status != OS_SUCCESS) + { + return status; + } + + #ifdef SA_DEBUG + OS_printf(KYEL "DEBUG - Printing SA Entry for current frame.\n" RESET); + Crypto_saPrint(sa_ptr); + #endif + + // Determine SA Service Type + if ((sa_ptr->est == 0) && (sa_ptr->ast == 0)) + { + sa_service_type = SA_PLAINTEXT; + } + else if ((sa_ptr->est == 0) && (sa_ptr->ast == 1)) + { + sa_service_type = SA_AUTHENTICATION; + } + else if ((sa_ptr->est == 1) && (sa_ptr->ast == 0)) + { + sa_service_type = SA_ENCRYPTION; + } + else if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) + { + sa_service_type = SA_AUTHENTICATED_ENCRYPTION; + } + else + { + // Probably unnecessary check + // Leaving for now as it would be cleaner in SA to have an association enum returned I believe + OS_printf(KRED "Error: SA Service Type is not defined! \n" RESET); + status = OS_ERROR; + return status; + } + + #ifdef TC_DEBUG + switch(sa_service_type) + { + case SA_PLAINTEXT: + OS_printf(KBLU "Creating a TC - CLEAR!\n" RESET); + break; + case SA_AUTHENTICATION: + OS_printf(KBLU "Creating a TC - AUTHENTICATED!\n" RESET); + break; + case SA_ENCRYPTION: + OS_printf(KBLU "Creating a TC - ENCRYPTED!\n" RESET); + break; + case SA_AUTHENTICATED_ENCRYPTION: + OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION!\n" RESET); + break; + } + #endif + + // Determine length of buffer to be malloced + // TODO: Determine presence of FECF & TC_PAD_SIZE + // TODO: Note: Currently assumes ciphertext output length is same as ciphertext input length + switch(sa_service_type) + { + case SA_PLAINTEXT: + // Ingest length + segment header (1) + spi_index (2) + some variable length fields + *p_enc_frame_len = in_frame_length + 1 + 2 + sa_ptr->shplf_len; + case SA_AUTHENTICATION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + stmacf_len + *p_enc_frame_len = in_frame_length + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len;; + case SA_ENCRYPTION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + *p_enc_frame_len = in_frame_length + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE; + case SA_AUTHENTICATED_ENCRYPTION: + // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + stmacf_len + *p_enc_frame_len = in_frame_length + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; + } + + #ifdef TC_DEBUG + OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *p_enc_frame_len); + OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); + OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded + OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); + OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, sa_ptr->shivf_len); + OS_printf(KYEL "\tshsnf_len\t = %d\n" RESET, sa_ptr->shsnf_len); + OS_printf(KYEL "\tshplf len\t = %d\n" RESET, sa_ptr->shplf_len); + OS_printf(KYEL "\tarc_len\t\t = %d\n" RESET, sa_ptr->arc_len); + OS_printf(KYEL "\tpad_size\t = %d\n" RESET, TC_PAD_SIZE); + OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, sa_ptr->stmacf_len); + #endif + + // Accio buffer + p_new_enc_frame = (uint8 *)malloc(*p_enc_frame_len * sizeof (unsigned char)); + if(!p_new_enc_frame) + { + OS_printf(KRED "Error: Malloc for encrypted output buffer failed! \n" RESET); + status = OS_ERROR; + return status; + } + CFE_PSP_MemSet(p_new_enc_frame, 0, *p_enc_frame_len); + + // Copy original TF header + CFE_PSP_MemCpy(p_new_enc_frame, p_in_frame, TC_FRAME_PRIMARYHEADER_SIZE); + + // Set new TF Header length + // Recall: Length field is one minus total length per spec + *(p_new_enc_frame+2) = ((*(p_new_enc_frame+2) & 0xFC) | (((*p_enc_frame_len - 1) & (0x0300)) >> 8)); + *(p_new_enc_frame+3) = ((*p_enc_frame_len - 1) & (0x00FF)); + + #ifdef TC_DEBUG + OS_printf(KYEL "Printing updated TF Header:\n\t"); + for (int i=0; ispi & 0xFF00) >> 8); + *(p_new_enc_frame + index + 1) = (sa_ptr->spi & 0x00FF); + index += 2; + + // Set initialization vector if specified + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + #ifdef SA_DEBUG + OS_printf(KYEL "Old IV value was:\n\t"); + for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} + OS_printf("\n" RESET); + #endif + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); + #endif + #ifdef SA_DEBUG + OS_printf(KYEL "New IV value is:\n\t"); + for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} + OS_printf("\n" RESET); + #endif + + for (int i=0; i < sa_ptr->shivf_len; i++) + { + // TODO: Likely API call + // Copy in IV from SA + *(p_new_enc_frame + index) = sa_ptr->iv[i]; + index++; + } + } + + // Set anti-replay sequence number if specified + /* + ** See also: 4.1.1.4.2 + ** 4.1.1.4.4 If authentication or authenticated encryption is not selected + ** for an SA, the Sequence Number field shall be zero octets in length. + ** Reference CCSDS 3550b1 + */ + // Determine if seq num field is needed + // TODO: Likely SA API Call + if (sa_ptr->shsnf_len > 0) + { + // If using anti-replay counter, increment it + // TODO: API call instead? + // TODO: Check return code + Crypto_increment(sa_ptr->arc, sa_ptr->shsnf_len); + for (int i=0; i < sa_ptr->shsnf_len; i++) + { + *(p_new_enc_frame + index) = sa_ptr->arc[i]; + index++; + } + } + + // Set security header padding if specified + /* + ** 4.2.3.4 h) if the algorithm and mode selected for the SA require the use of + ** fill padding, place the number of fill bytes used into the Pad Length field + ** of the Security Header - Reference CCSDS 3550b1 + */ + // TODO: Revisit this + // TODO: Likely SA API Call + for (int i=0; i < sa_ptr->shplf_len; i++) + { + /* 4.1.1.5.2 The Pad Length field shall contain the count of fill bytes used in the + ** cryptographic process, consisting of an integral number of octets. - CCSDS 3550b1 + */ + // TODO: Set this depending on crypto cipher used + *(p_new_enc_frame + index) = 0x00; + index++; + } + + /* + ** End Security Header Fields + */ + + // Copy in original TF data - except FECF + // Will be over-written if using encryption later + // TODO: This will change depending on how we handle segment header and FECF above, + // and if it was present in the original TCTF + //if FECF + tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - FECF_SIZE; + //if no FECF + //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; + CFE_PSP_MemCpy((p_new_enc_frame+index), (p_in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); + //index += tf_payload_len; + + /* + ** Begin Security Trailer Fields + */ + + // Set MAC Field if present + /* + ** May be present and unused if switching between clear and authenticated + ** CCSDS 3550b1 4.1.2.3 + */ + // By leaving MAC as zeros, can use index for encryption output + // for (int i=0; i < temp_SA.stmacf_len; i++) + // { + // // Temp fill MAC + // *(p_new_enc_frame + index) = 0x00; + // index++; + // } + + /* + ** End Security Trailer Fields + */ + + /* + ** Begin Authentication / Encryption + */ + + if (sa_service_type != SA_PLAINTEXT) + { + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[sa_ptr->ekid].value[0]), + KEY_SIZE //TODO: look into this + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(sa_ptr->iv[0]), + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + // Prepare additional authenticated data, if needed + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + for (int y = 0; y < sa_ptr->abm_len; y++) + { + aad[y] = p_in_frame[y] & sa_ptr->abm[y]; + } + #ifdef MAC_DEBUG + OS_printf(KYEL "Preparing AAD:\n"); + OS_printf("\tUsing ABM Length of %d\n\t", sa_ptr->abm_len); + for (int y = 0; y < sa_ptr->abm_len; y++) + { + OS_printf("%02x", aad[y]); + } + OS_printf("\n" RESET); + #endif + + gcry_error = gcry_cipher_authenticate( + tmp_hd, + &(aad[0]), // additional authenticated data + sa_ptr->abm_len // length of AAD + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + status = OS_ERROR; + return status; + } + } + + if ((sa_service_type == SA_ENCRYPTION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + // TODO: More robust calculation of this location + // uint16 output_loc = TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; + #ifdef TC_DEBUG + OS_printf("Encrypted bytes output_loc is %d\n", index); + OS_printf("tf_payload_len is %d\n", tf_payload_len); + OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); + for(int i=0; i < *p_enc_frame_len; i++) + { + OS_printf("%02X", *(p_new_enc_frame + i)); + } + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_encrypt( + tmp_hd, + &p_new_enc_frame[index], // ciphertext output + tf_payload_len, // length of data + (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now + tf_payload_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + } + + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + // TODO - Know if FECF exists + mac_loc = *p_enc_frame_len - sa_ptr->stmacf_len - FECF_SIZE; + #ifdef MAC_DEBUG + OS_printf(KYEL "MAC location is: %d\n" RESET, mac_loc); + OS_printf(KYEL "MAC size is: %d\n" RESET, MAC_SIZE); + #endif + gcry_error = gcry_cipher_gettag( + tmp_hd, + &p_new_enc_frame[mac_loc], // tag output + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + } + // Zeroise any sensitive information + if (sa_service_type != SA_PLAINTEXT) + { + gcry_cipher_close(tmp_hd); + } + } + /* + ** End Authentication / Encryption + */ + + // Set FECF Field if present + // TODO: Determine is FECF is even present + // on this particular channel + // Calc new fecf, don't include old fecf in length + #ifdef FECF_DEBUG + OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *p_enc_frame_len - 2); + #endif + new_fecf = Crypto_Calc_FECF(p_new_enc_frame, *p_enc_frame_len - 2); + *(p_new_enc_frame + *p_enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(p_new_enc_frame + *p_enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); + index += 2; + + #ifdef TC_DEBUG + OS_printf(KYEL "Printing new TC Frame:\n\t"); + for(int i=0; i < *p_enc_frame_len; i++) + { + OS_printf("%02X", *(p_new_enc_frame + i)); + } + OS_printf("\n\tThe returned length is: %d\n" RESET, *p_enc_frame_len); + #endif + + *pp_in_frame = p_new_enc_frame; + } + + status = sadb_routine->sadb_save_sa(sa_ptr); + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_TC_ApplySecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_processed_frame) +// Loads the ingest frame into the global tc_frame while performing decryption +{ + // Local Variables + int32 status = OS_SUCCESS; + int x = 0; + int y = 0; + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + SecurityAssociation_t* sa_ptr = NULL; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_TC_ProcessSecurity START -----\n" RESET); + #endif + + int byte_idx = 0; + // Primary Header + tc_sdls_processed_frame->tc_header.tfvn = ((uint8)ingest[byte_idx] & 0xC0) >> 6; + tc_sdls_processed_frame->tc_header.bypass = ((uint8)ingest[byte_idx] & 0x20) >> 5; + tc_sdls_processed_frame->tc_header.cc = ((uint8)ingest[byte_idx] & 0x10) >> 4; + tc_sdls_processed_frame->tc_header.spare = ((uint8)ingest[byte_idx] & 0x0C) >> 2; + tc_sdls_processed_frame->tc_header.scid = ((uint8)ingest[byte_idx] & 0x03) << 8; + byte_idx++; + tc_sdls_processed_frame->tc_header.scid = tc_sdls_processed_frame->tc_header.scid | (uint8)ingest[byte_idx]; + byte_idx++; + tc_sdls_processed_frame->tc_header.vcid = (((uint8)ingest[byte_idx] & 0xFC) >> 2) & VCID_BITMASK; + tc_sdls_processed_frame->tc_header.fl = ((uint8)ingest[byte_idx] & 0x03) << 8; + byte_idx++; + tc_sdls_processed_frame->tc_header.fl = tc_sdls_processed_frame->tc_header.fl | (uint8)ingest[byte_idx]; + byte_idx++; + tc_sdls_processed_frame->tc_header.fsn = (uint8)ingest[byte_idx]; + byte_idx++; + + // Security Header + if(SEGMENTATION_HDR){ + tc_sdls_processed_frame->tc_sec_header.sh = (uint8)ingest[byte_idx]; + byte_idx++; + } + tc_sdls_processed_frame->tc_sec_header.spi = ((uint8)ingest[byte_idx] << 8) | (uint8)ingest[byte_idx+1]; + byte_idx+=2; + #ifdef TC_DEBUG + OS_printf("vcid = %d \n", tc_sdls_processed_frame->tc_header.vcid ); + OS_printf("spi = %d \n", tc_sdls_processed_frame->tc_sec_header.spi); + #endif + + // Checks + if (PUS_HDR && ((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) + { + // User packet check only used for ESA Testing! + } + else + { // Update last spi used + report.lspiu = tc_sdls_processed_frame->tc_sec_header.spi; + + // Verify + if (tc_sdls_processed_frame->tc_header.scid != (SCID & 0x3FF)) + { + OS_printf(KRED "Error: SCID incorrect! \n" RESET); + status = OS_ERROR; + } + else + { + switch (report.lspiu) + { // Invalid SPIs fall through to trigger flag in FSR + case 0x0000: + case 0xFFFF: + status = OS_ERROR; + report.ispif = 1; + OS_printf(KRED "Error: SPI invalid! \n" RESET); + break; + default: + break; + } + } + + + if ((report.lspiu > NUM_SA) && (status == OS_SUCCESS)) + { + report.ispif = 1; + OS_printf(KRED "Error: SPI value greater than NUM_SA! \n" RESET); + status = OS_ERROR; + } + if (status == OS_SUCCESS) + { + if(sadb_routine->sadb_get_sa_from_spi(report.lspiu,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + status = OS_ERROR; //Error -- unable to get SA from SPI. + } + } + if (status == OS_SUCCESS) + { + if (sa_ptr->gvcid_tc_blk.mapid != TYPE_TC) + { + OS_printf(KRED "Error: SA invalid type! \n" RESET); + status = OS_ERROR; + } + } + // TODO: I don't think this is needed. + //if (status == OS_SUCCESS) + //{ + // if (sa_ptr->gvcid_tc_blk.vcid != tc_sdls_processed_frame->tc_header.vcid) + // { + // OS_printf(KRED "Error: VCID not mapped to provided SPI! \n" RESET); + // status = OS_ERROR; + // } + //} + if (status == OS_SUCCESS) + { + if (sa_ptr->sa_state != SA_OPERATIONAL) + { + OS_printf(KRED "Error: SA state not operational! \n" RESET); + status = OS_ERROR; + } + } + if (status != OS_SUCCESS) + { + report.af = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = SPI_INVALID_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + *len_ingest = 0; + return status; + } + } + if(sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + status = OS_ERROR; //Error -- unable to get SA from SPI. + return status; + } + // Determine mode via SPI + if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) + { // Authenticated Encryption + #ifdef DEBUG + OS_printf(KBLU "ENCRYPTED TC Received!\n" RESET); + #endif + #ifdef TC_DEBUG + OS_printf("IV: \n"); + #endif + for (x = byte_idx; x < (byte_idx + IV_SIZE); x++) + { + tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; + #ifdef TC_DEBUG + OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); + #endif + } + byte_idx += IV_SIZE; + report.snval = tc_sdls_processed_frame->tc_sec_header.iv[IV_SIZE-1]; + + #ifdef DEBUG + OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", IV_SIZE-1, tc_sdls_processed_frame->tc_sec_header.iv[IV_SIZE-1]); + OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, IV_SIZE-1, sa_ptr->iv[IV_SIZE-1]); + #endif + + // Check IV is in ARCW + if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, IV_SIZE, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) + { + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV not in window! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { + if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, IV_SIZE) == OS_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value + for (int i = 0; i < (IV_SIZE); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } + } + } + + if ( status == OS_ERROR ) + { // Exit + *len_ingest = 0; + return status; + } + + tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame); + + x = x + tc_sdls_processed_frame->tc_pdu_len; + + #ifdef TC_DEBUG + OS_printf("TC: \n"); + for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) + { + OS_printf("\t ingest[%d] = 0x%02x \n", temp, (uint8)ingest[temp+20]); + } + #endif + + // Security Trailer + #ifdef TC_DEBUG + OS_printf("MAC: \n"); + #endif + for (y = x; y < (x + MAC_SIZE); y++) + { + tc_sdls_processed_frame->tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; + #ifdef TC_DEBUG + OS_printf("\t mac[%d] = 0x%02x\n", y-x, tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); + #endif + } + x = x + MAC_SIZE; + + // FECF + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); + Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 2),tc_sdls_processed_frame); + + // Initialize the key + //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[sa_ptr->ekid]); + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef DEBUG + OS_printf("Key ID = %d, 0x", sa_ptr->ekid); + for(int y = 0; y < KEY_SIZE; y++) + { + OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); + } + OS_printf("\n"); + #endif + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[sa_ptr->ekid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(sa_ptr->iv[0]), + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef MAC_DEBUG + OS_printf("AAD = 0x"); + #endif + // Prepare additional authenticated data (AAD) + for (y = 0; y < sa_ptr->abm_len; y++) + { + ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); + #ifdef MAC_DEBUG + OS_printf("%02x", (uint8) ingest[y]); + #endif + } + #ifdef MAC_DEBUG + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_decrypt( + tmp_hd, + &(tc_sdls_processed_frame->tc_pdu[0]), // plaintext output + tc_sdls_processed_frame->tc_pdu_len, // length of data + &(ingest[20]), // ciphertext input + tc_sdls_processed_frame->tc_pdu_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_checktag( + tmp_hd, + &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag input + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + + OS_printf("Actual MAC = 0x"); + for (int z = 0; z < MAC_SIZE; z++) + { + OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); + } + OS_printf("\n"); + + gcry_error = gcry_cipher_gettag( + tmp_hd, + &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + + OS_printf("Expected MAC = 0x"); + for (int z = 0; z < MAC_SIZE; z++) + { + OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); + } + OS_printf("\n"); + status = OS_ERROR; + report.bmacf = 1; + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + return status; + } + gcry_cipher_close(tmp_hd); + + // Increment the IV for next time + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, IV_SIZE); + #endif + } + else + { // Clear + #ifdef DEBUG + OS_printf(KBLU "CLEAR TC Received!\n" RESET); + #endif + + for (y = 10; y <= (tc_sdls_processed_frame->tc_header.fl - 2); y++) //tfhdr+seghdr+sechdr=5+1+6=12 + { + tc_sdls_processed_frame->tc_pdu[y - 10] = (uint8)ingest[y]; + } + // FECF + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[y] << 8) | ((uint8)ingest[y+1]); + Crypto_FECF((int) tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 2),tc_sdls_processed_frame); + } + + #ifdef TC_DEBUG + Crypto_tcPrint(tc_sdls_processed_frame); + #endif + + // Zero ingest + for (x = 0; x < *len_ingest; x++) + { + ingest[x] = 0; + } + + + if(!TC_PROCESS_SDLS_PDUS) //If we don't want to process frame data for SDLS PDUs, only reverse security & return content. + { + // CCSDS Pass-through + #ifdef DEBUG + OS_printf(KGRN "CCSDS Pass-through \n" RESET); + #endif + if (PUS_HDR) { + for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl - 11); x++) { + ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; + #ifdef CCSDS_DEBUG + OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); + #endif + *len_ingest = x; + } + } else { + for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl); x++) { //with no PUS header, entire PDU is data + ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; + #ifdef CCSDS_DEBUG + OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); + #endif + *len_ingest = x; + } + } + } + else //Process SDLS PDU + { + if (PUS_HDR) + { + if ((tc_sdls_processed_frame->tc_pdu[0] == 0x18) && (tc_sdls_processed_frame->tc_pdu[1] == 0x80)) + // Crypto Lib Application ID + { + #ifdef DEBUG + OS_printf(KGRN "Received SDLS command: " RESET); + #endif + // CCSDS Header + sdls_frame.hdr.pvn = (tc_sdls_processed_frame->tc_pdu[0] & 0xE0) >> 5; + sdls_frame.hdr.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x10) >> 4; + sdls_frame.hdr.shdr = (tc_sdls_processed_frame->tc_pdu[0] & 0x08) >> 3; + sdls_frame.hdr.appID = + ((tc_sdls_processed_frame->tc_pdu[0] & 0x07) << 8) | tc_sdls_processed_frame->tc_pdu[1]; + sdls_frame.hdr.seq = (tc_sdls_processed_frame->tc_pdu[2] & 0xC0) >> 6; + sdls_frame.hdr.pktid = + ((tc_sdls_processed_frame->tc_pdu[2] & 0x3F) << 8) | tc_sdls_processed_frame->tc_pdu[3]; + sdls_frame.hdr.pkt_length = (tc_sdls_processed_frame->tc_pdu[4] << 8) | tc_sdls_processed_frame->tc_pdu[5]; + + // CCSDS PUS + sdls_frame.pus.shf = (tc_sdls_processed_frame->tc_pdu[6] & 0x80) >> 7; + sdls_frame.pus.pusv = (tc_sdls_processed_frame->tc_pdu[6] & 0x70) >> 4; + sdls_frame.pus.ack = (tc_sdls_processed_frame->tc_pdu[6] & 0x0F); + sdls_frame.pus.st = tc_sdls_processed_frame->tc_pdu[7]; + sdls_frame.pus.sst = tc_sdls_processed_frame->tc_pdu[8]; + sdls_frame.pus.sid = (tc_sdls_processed_frame->tc_pdu[9] & 0xF0) >> 4; + sdls_frame.pus.spare = (tc_sdls_processed_frame->tc_pdu[9] & 0x0F); + + // SDLS TLV PDU + sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[10] & 0x80) >> 7; + sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[10] & 0x40) >> 6; + sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[10] & 0x30) >> 4; + sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[10] & 0x0F); + sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[11] << 8) | tc_sdls_processed_frame->tc_pdu[12]; + for (x = 13; x < (13 + sdls_frame.hdr.pkt_length); x++) { + sdls_frame.pdu.data[x - 13] = tc_sdls_processed_frame->tc_pdu[x]; + } + + #ifdef CCSDS_DEBUG + Crypto_ccsdsPrint(&sdls_frame); + #endif + + // Determine type of PDU + *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); + } + } + else if (tc_sdls_processed_frame->tc_header.vcid == TC_SDLS_EP_VCID) //TC SDLS PDU with no packet layer + { + #ifdef DEBUG + OS_printf(KGRN "Received SDLS command: " RESET); + #endif + // No Packet HDR or PUS in these frames + // SDLS TLV PDU + sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x80) >> 7; + sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[0] & 0x40) >> 6; + sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[0] & 0x30) >> 4; + sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[0] & 0x0F); + sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[1] << 8) | tc_sdls_processed_frame->tc_pdu[2]; + for (x = 3; x < (3 + tc_sdls_processed_frame->tc_header.fl); x++) { + //Todo - Consider how this behaves with large OTAR PDUs that are larger than 1 TC in size. Most likely fails. Must consider Uplink Sessions (sequence numbers). + sdls_frame.pdu.data[x - 3] = tc_sdls_processed_frame->tc_pdu[x]; + } + + #ifdef CCSDS_DEBUG + Crypto_ccsdsPrint(&sdls_frame); + #endif + + // Determine type of PDU + *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); + } + else { + //TODO - Process SDLS PDU with Packet Layer without PUS_HDR + } + }//End Process SDLS PDU + + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_TC_ProcessSecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) +// Accepts CCSDS message in ingest, and packs into TM before encryption +{ + int32 status = ITC_GCM128_SUCCESS; + int count = 0; + int pdu_loc = 0; + int pdu_len = *len_ingest - TM_MIN_SIZE; + int pad_len = 0; + int mac_loc = 0; + int fecf_loc = 0; + uint8 tempTM[TM_SIZE]; + int x = 0; + int y = 0; + uint8 aad[20]; + uint16 spi = tm_frame.tm_sec_header.spi; + uint16 spp_crc = 0x0000; + SecurityAssociation_t* sa_ptr; + SecurityAssociation_t sa; + + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + CFE_PSP_MemSet(&tempTM, 0, TM_SIZE); + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_TM_ApplySecurity START -----\n" RESET); + #endif + + // Check for idle frame trigger + if (((uint8)ingest[0] == 0x08) && ((uint8)ingest[1] == 0x90)) + { // Zero ingest + for (x = 0; x < *len_ingest; x++) + { + ingest[x] = 0; + } + // Update TM First Header Pointer + tm_frame.tm_header.fhp = 0xFE; + } + else + { // Update the length of the ingest from the CCSDS header + *len_ingest = (ingest[4] << 8) | ingest[5]; + ingest[5] = ingest[5] - 5; + // Remove outgoing secondary space packet header flag + ingest[0] = 0x00; + // Change sequence flags to 0xFFFF + ingest[2] = 0xFF; + ingest[3] = 0xFF; + // Add 2 bytes of CRC to space packet + spp_crc = Crypto_Calc_CRC16((char*) ingest, *len_ingest); + ingest[*len_ingest] = (spp_crc & 0xFF00) >> 8; + ingest[*len_ingest+1] = (spp_crc & 0x00FF); + *len_ingest = *len_ingest + 2; + // Update TM First Header Pointer + tm_frame.tm_header.fhp = tm_offset; + #ifdef TM_DEBUG + OS_printf("tm_offset = %d \n", tm_offset); + #endif + } + + // Update Current Telemetry Frame in Memory + // Counters + tm_frame.tm_header.mcfc++; + tm_frame.tm_header.vcfc++; + // Operational Control Field + Crypto_TM_updateOCF(); + // Payload Data Unit + Crypto_TM_updatePDU(ingest, *len_ingest); + + if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } + + + // Check test flags + if (badSPI == 1) + { + tm_frame.tm_sec_header.spi++; + } + if (badIV == 1) + { + sa_ptr->iv[IV_SIZE-1]++; + } + if (badMAC == 1) + { + tm_frame.tm_sec_trailer.mac[MAC_SIZE-1]++; + } + + // Initialize the temporary TM frame + // Header + tempTM[count++] = (uint8) ((tm_frame.tm_header.tfvn << 6) | ((tm_frame.tm_header.scid & 0x3F0) >> 4)); + tempTM[count++] = (uint8) (((tm_frame.tm_header.scid & 0x00F) << 4) | (tm_frame.tm_header.vcid << 1) | (tm_frame.tm_header.ocff)); + tempTM[count++] = (uint8) (tm_frame.tm_header.mcfc); + tempTM[count++] = (uint8) (tm_frame.tm_header.vcfc); + tempTM[count++] = (uint8) ((tm_frame.tm_header.tfsh << 7) | (tm_frame.tm_header.sf << 6) | (tm_frame.tm_header.pof << 5) | (tm_frame.tm_header.slid << 3) | ((tm_frame.tm_header.fhp & 0x700) >> 8)); + tempTM[count++] = (uint8) (tm_frame.tm_header.fhp & 0x0FF); + // tempTM[count++] = (uint8) ((tm_frame.tm_header.tfshvn << 6) | tm_frame.tm_header.tfshlen); + // Security Header + tempTM[count++] = (uint8) ((spi & 0xFF00) >> 8); + tempTM[count++] = (uint8) ((spi & 0x00FF)); + CFE_PSP_MemCpy(tm_frame.tm_sec_header.iv, sa_ptr->iv, IV_SIZE); + + // Padding Length + pad_len = Crypto_Get_tmLength(*len_ingest) - TM_MIN_SIZE + IV_SIZE + TM_PAD_SIZE - *len_ingest; + + // Only add IV for authenticated encryption + if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) + { // Initialization Vector + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, IV_SIZE); + #endif + if ((sa_ptr->est == 1) || (sa_ptr->ast == 1)) + { for (x = 0; x < IV_SIZE; x++) + { + tempTM[count++] = sa_ptr->iv[x]; + } + } + pdu_loc = count; + pad_len = pad_len - IV_SIZE - TM_PAD_SIZE + OCF_SIZE; + pdu_len = *len_ingest + pad_len; + } + else + { // Include padding length bytes - hard coded per ESA testing + tempTM[count++] = 0x00; // pad_len >> 8; + tempTM[count++] = 0x1A; // pad_len + pdu_loc = count; + pdu_len = *len_ingest + pad_len; + } + + // Payload Data Unit + for (x = 0; x < (pdu_len); x++) + { + tempTM[count++] = (uint8) tm_frame.tm_pdu[x]; + } + // Message Authentication Code + mac_loc = count; + for (x = 0; x < MAC_SIZE; x++) + { + tempTM[count++] = 0x00; + } + // Operational Control Field + for (x = 0; x < OCF_SIZE; x++) + { + tempTM[count++] = (uint8) tm_frame.tm_sec_trailer.ocf[x]; + } + // Frame Error Control Field + fecf_loc = count; + tm_frame.tm_sec_trailer.fecf = Crypto_Calc_FECF((char*) tempTM, count); + tempTM[count++] = (uint8) ((tm_frame.tm_sec_trailer.fecf & 0xFF00) >> 8); + tempTM[count++] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); + + // Determine Mode + // Clear + if ((sa_ptr->est == 0) && + (sa_ptr->ast == 0)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TM - CLEAR! \n" RESET); + #endif + // Copy temporary frame to ingest + CFE_PSP_MemCpy(ingest, tempTM, count); + } + // Authenticated Encryption + else if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TM - AUTHENTICATED ENCRYPTION! \n" RESET); + #endif + + // Copy TM to ingest + CFE_PSP_MemCpy(ingest, tempTM, pdu_loc); + + #ifdef MAC_DEBUG + OS_printf("AAD = 0x"); + #endif + // Prepare additional authenticated data + for (y = 0; y < sa_ptr->abm_len; y++) + { + aad[y] = ingest[y] & sa_ptr->abm[y]; + #ifdef MAC_DEBUG + OS_printf("%02x", aad[y]); + #endif + } + #ifdef MAC_DEBUG + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[sa_ptr->ekid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(sa_ptr->iv[0]), + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_encrypt( + tmp_hd, + &(ingest[pdu_loc]), // ciphertext output + pdu_len, // length of data + &(tempTM[pdu_loc]), // plaintext input + pdu_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_authenticate( + tmp_hd, + &(aad[0]), // additional authenticated data + sa_ptr->abm_len // length of AAD + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_gettag( + tmp_hd, + &(ingest[mac_loc]), // tag output + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + #ifdef MAC_DEBUG + OS_printf("MAC = 0x"); + for(x = 0; x < MAC_SIZE; x++) + { + OS_printf("%02x", (uint8) ingest[x + mac_loc]); + } + OS_printf("\n"); + #endif + + // Update OCF + y = 0; + for (x = OCF_SIZE; x > 0; x--) + { + ingest[fecf_loc - x] = tm_frame.tm_sec_trailer.ocf[y++]; + } + + // Update FECF + tm_frame.tm_sec_trailer.fecf = Crypto_Calc_FECF((char*) ingest, fecf_loc - 1); + ingest[fecf_loc] = (uint8) ((tm_frame.tm_sec_trailer.fecf & 0xFF00) >> 8); + ingest[fecf_loc + 1] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); + } + // Authentication + else if ((sa_ptr->est == 0) && + (sa_ptr->ast == 1)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TM - AUTHENTICATED! \n" RESET); + #endif + // TODO: Future work. Operationally same as clear. + CFE_PSP_MemCpy(ingest, tempTM, count); + } + // Encryption + else if ((sa_ptr->est == 1) && + (sa_ptr->ast == 0)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TM - ENCRYPTED! \n" RESET); + #endif + // TODO: Future work. Operationally same as clear. + CFE_PSP_MemCpy(ingest, tempTM, count); + } + + #ifdef TM_DEBUG + Crypto_tmPrint(&tm_frame); + #endif + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_TM_ApplySecurity END -----\n" RESET); + #endif + + *len_ingest = count; + return status; +} + +int32 Crypto_TM_ProcessSecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_TM_ProcessSecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_TM_ProcessSecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_AOS_ApplySecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_AOS_ApplySecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_AOS_ApplySecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_AOS_ProcessSecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_AOS_ProcessSecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_AOS_ProcessSecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_ApplySecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_ApplySecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_ApplySecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_ProcessSecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_ProcessSecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_ProcessSecurity END -----\n" RESET); + #endif + + return status; +} + #endif \ No newline at end of file diff --git a/fsw/src/crypto_print.c b/fsw/src/crypto_print.c index 96aef79c..e4627014 100644 --- a/fsw/src/crypto_print.c +++ b/fsw/src/crypto_print.c @@ -161,6 +161,7 @@ void Crypto_saPrint(SecurityAssociation_t* sa) // Prints the Security Association in memory { OS_printf("SA status: \n"); + OS_printf("\t spi = 0x%01x \n", sa->spi); OS_printf("\t sa_state = 0x%01x \n", sa->sa_state); //OS_printf("\t gvcid[0] = 0x%02x \n", sa->gvcid_blk[spi].gvcid[0]); //OS_printf("\t gvcid[1] = 0x%02x \n", sa->gvcid_blk[spi].gvcid[1]); @@ -202,4 +203,32 @@ void Crypto_saPrint(SecurityAssociation_t* sa) OS_printf("\t arcw[0] = 0x%02x \n", sa->arcw[0]); } +//Hex Print: +void Crypto_hexprint(void *c, size_t n) +{ + unsigned char *t = c; + if (c == NULL) + return; + while (n > 0) { + --n; + printf("%02x", t[n]); + } + printf("\n"); +} + +//Binary Print +void Crypto_binprint(void *c, size_t n) +{ + unsigned char *t = c; + if (c == NULL) + return; + while (n > 0) { + int q; + --n; + for(q = 0x80; q; q >>= 1) + printf("%x", !!(t[n] & q)); + } + printf("\n"); +} + #endif \ No newline at end of file diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c index 35733953..468a475f 100644 --- a/fsw/src/sadb_routine_inmemory.template.c +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -23,6 +23,8 @@ static int32 sadb_init(void); static int32 sadb_close(void); // Security Association Interaction Functions static int32 sadb_get_sa_from_spi(uint16,SecurityAssociation_t**); +static int32 sadb_get_operational_sa_from_gvcid(uint8,uint16,uint16,uint8,SecurityAssociation_t**); +static int32 sadb_save_sa(SecurityAssociation_t* sa); // Security Association Utility Functions static int32 sadb_sa_start(TC_t* tc_frame); static int32 sadb_sa_expire(void); @@ -47,6 +49,8 @@ SadbRoutine get_sadb_routine_inmemory(void) sadb_routine.sadb_init = sadb_init; sadb_routine.sadb_close = sadb_close; sadb_routine.sadb_get_sa_from_spi = sadb_get_sa_from_spi; + sadb_routine.sadb_get_operational_sa_from_gvcid = sadb_get_operational_sa_from_gvcid; + sadb_routine.sadb_save_sa = sadb_save_sa; sadb_routine.sadb_sa_start = sadb_sa_start; sadb_routine.sadb_sa_expire = sadb_sa_expire; sadb_routine.sadb_sa_rekey = sadb_sa_rekey; @@ -65,6 +69,7 @@ static int32 sadb_config(void) // Security Associations // SA 1 - CLEAR MODE // SA 1 VC0/1 is now SA 1-VC0, SA 8-VC1 + sa[1].spi = 1; sa[1].sa_state = SA_OPERATIONAL; sa[1].est = 0; sa[1].ast = 0; @@ -76,6 +81,7 @@ static int32 sadb_config(void) sa[1].gvcid_tc_blk.vcid = 0; sa[1].gvcid_tc_blk.mapid = TYPE_TC; // SA 2 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 128 + sa[2].spi = 2; sa[2].ekid = 128; sa[2].sa_state = SA_KEYED; sa[2].est = 1; @@ -92,6 +98,7 @@ static int32 sadb_config(void) sa[2].arcw[0] = 5; sa[2].arc_len = (sa[2].arcw[0] * 2) + 1; // SA 3 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 129 + sa[3].spi = 3; sa[3].ekid = 129; sa[3].sa_state = SA_KEYED; sa[3].est = 1; @@ -109,6 +116,7 @@ static int32 sadb_config(void) sa[3].arc_len = (sa[3].arcw[0] * 2) + 1; // SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 // SA 4 VC0/1 is now 4-VC0, 7-VC1 + sa[4].spi = 4; sa[4].ekid = 130; sa[4].sa_state = SA_KEYED; sa[4].est = 1; @@ -131,6 +139,7 @@ static int32 sadb_config(void) sa[4].gvcid_tc_blk.mapid = TYPE_TC; // SA 5 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 131 + sa[5].spi = 5; sa[5].ekid = 131; sa[5].sa_state = SA_KEYED; sa[5].est = 1; @@ -147,6 +156,7 @@ static int32 sadb_config(void) sa[5].arcw[0] = 5; sa[5].arc_len = (sa[5].arcw[0] * 2) + 1; // SA 6 - UNKEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: - + sa[6].spi = 6; sa[6].sa_state = SA_UNKEYED; sa[6].est = 1; sa[6].ast = 1; @@ -164,6 +174,7 @@ static int32 sadb_config(void) //itc_gcm128_init(&(sa[6].gcm_ctx), (unsigned char *)&(ek_ring[sa[6].ekid])); // SA 7 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 + sa[7].spi = 7; sa[7].ekid = 130; sa[7].sa_state = SA_KEYED; sa[7].est = 1; @@ -186,6 +197,7 @@ static int32 sadb_config(void) return status; // SA 8 - CLEAR MODE + sa[8].spi = 8; sa[8].sa_state = SA_OPERATIONAL; sa[8].est = 0; sa[8].ast = 0; @@ -239,6 +251,39 @@ static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_as return status; } +static int32 sadb_get_operational_sa_from_gvcid(uint8 tfvn,uint16 scid,uint16 vcid,uint8 mapid,SecurityAssociation_t** security_association) +{ + int32 status = OS_SUCCESS; + + for (int i=0; i < NUM_SA;i++) + { + if (sa[i].gvcid_tc_blk.tfvn == tfvn && sa[i].gvcid_tc_blk.scid == scid && sa[i].gvcid_tc_blk.vcid == vcid && sa[i].gvcid_tc_blk.mapid == mapid //gvcid + && sa[i].sa_state == SA_OPERATIONAL) + { + *security_association = &sa[i]; + + #ifdef TC_DEBUG + OS_printf("Operational SA found at index %d.\n", i); + #endif + + return status; + } + } + + // We only get here if no operational SA found + OS_printf(KRED "Error: No operational SA found! \n" RESET); + status = OS_ERROR; + + return status; +} +static int32 sadb_save_sa(SecurityAssociation_t* sa) +{ + int32 status = OS_SUCCESS; + //We could do a memory copy of the SA into the sa[NUM_SA] array at the given SPI, however, the inmemory code currently updates in place so no need for that. + // If we change the in-place update logic, we should update this function to actually update the SA. + return status; +} + /* ** Security Association Management Services */ diff --git a/fsw/src_mysql/sadb_routine_mariadb.template.c b/fsw/src_mysql/sadb_routine_mariadb.template.c index 9b5277b7..0ec689c3 100644 --- a/fsw/src_mysql/sadb_routine_mariadb.template.c +++ b/fsw/src_mysql/sadb_routine_mariadb.template.c @@ -16,6 +16,7 @@ #include "crypto_structs.h" #include "crypto_config.h" #include "crypto_error.h" +#include "crypto_print.h" #include #include @@ -28,6 +29,8 @@ static int32 sadb_init(void); static int32 sadb_close(void); // Security Association Interaction Functions static int32 sadb_get_sa_from_spi(uint16,SecurityAssociation_t**); +static int32 sadb_get_operational_sa_from_gvcid(uint8,uint16,uint16,uint8,SecurityAssociation_t**); +static int32 sadb_save_sa(SecurityAssociation_t* sa); // Security Association Utility Functions static int32 sadb_sa_start(TC_t* tc_frame); static int32 sadb_sa_expire(void); @@ -40,7 +43,14 @@ static int32 sadb_sa_delete(void); //MySQL local functions static int32 finish_with_error(MYSQL *con,int err); //MySQL Queries -const static char* SQL_SADB_GET_SA_BY_SPI = "SELECT * FROM security_associations WHERE sa_id='%d'"; +const static char* SQL_SADB_GET_SA_BY_SPI = "SELECT * FROM security_associations WHERE spi='%d';"; +const static char* SQL_SADB_GET_SA_BY_GVCID = "SELECT * FROM security_associations WHERE tfvn='%d' AND scid='%d' AND vcid='%d' AND mapid='%d';"; +const static char* SQL_SADB_UPDATE_IV_ARC_BY_SPI = "UPDATE security_associations "\ + "SET iv='%d', arc='%d' " \ + "WHERE spi='%d'AND tfvn='%d' AND scid='%d' AND vcid='%d' AND mapid='%d';"; + +// sadb_routine mariaDB private helper functions +static int32 parse_sa_from_mysql_query(char* query, SecurityAssociation_t** security_association); /* @@ -56,6 +66,8 @@ SadbRoutine get_sadb_routine_mariadb(void) sadb_routine.sadb_config = sadb_config; sadb_routine.sadb_init = sadb_init; sadb_routine.sadb_get_sa_from_spi = sadb_get_sa_from_spi; + sadb_routine.sadb_get_operational_sa_from_gvcid = sadb_get_operational_sa_from_gvcid; + sadb_routine.sadb_save_sa = sadb_save_sa; sadb_routine.sadb_sa_start = sadb_sa_start; sadb_routine.sadb_sa_expire = sadb_sa_expire; sadb_routine.sadb_sa_rekey = sadb_sa_rekey; @@ -98,14 +110,66 @@ static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_as { int32 status = OS_SUCCESS; - SecurityAssociation_t* sa = malloc(sizeof(SecurityAssociation_t)); - char spi_query[2048]; snprintf(spi_query, sizeof(spi_query),SQL_SADB_GET_SA_BY_SPI,spi); - if(mysql_query(con,spi_query)) { status = finish_with_error(con,SADB_QUERY_BY_SPI_FAILED); } + + status = parse_sa_from_mysql_query(&spi_query[0],security_association); + + return status; +} +static int32 sadb_get_operational_sa_from_gvcid(uint8 tfvn,uint16 scid,uint16 vcid,uint8 mapid,SecurityAssociation_t** security_association) +{ + int32 status = OS_SUCCESS; + + char gvcid_query[2048]; + snprintf(gvcid_query, sizeof(gvcid_query),SQL_SADB_GET_SA_BY_GVCID,tfvn,scid,vcid,mapid); + + status = parse_sa_from_mysql_query(&gvcid_query[0],security_association); + + return status; +} +static int32 sadb_save_sa(SecurityAssociation_t* sa) +{ + int32 status = OS_SUCCESS; + + char gvcid_query[2048]; + snprintf(gvcid_query, sizeof(gvcid_query),SQL_SADB_UPDATE_IV_ARC_BY_SPI,sa->iv,sa->arc,sa->spi,sa->gvcid_tc_blk.tfvn,sa->gvcid_tc_blk.scid,sa->gvcid_tc_blk.vcid,sa->gvcid_tc_blk.mapid); + + Crypto_saPrint(sa); + if(mysql_query(con,gvcid_query)) { + status = finish_with_error(con,SADB_QUERY_FAILED); return status; + } + // todo - if query fails, need to push failure message to error stack instead of just return code. + + //We free the allocated SA memory in the save function. + free(sa); + return status; +} +// Security Association Utility Functions +static int32 sadb_sa_start(TC_t* tc_frame){return OS_SUCCESS;} +static int32 sadb_sa_expire(void){return OS_SUCCESS;} +static int32 sadb_sa_rekey(void){return OS_SUCCESS;} +static int32 sadb_sa_status(char* ingest){return OS_SUCCESS;} +static int32 sadb_sa_create(void){return OS_SUCCESS;} +static int32 sadb_sa_setARSN(void){return OS_SUCCESS;} +static int32 sadb_sa_setARSNW(void){return OS_SUCCESS;} +static int32 sadb_sa_delete(void){return OS_SUCCESS;} + +// sadb_routine private helper functions +static int32 parse_sa_from_mysql_query(char* query, SecurityAssociation_t** security_association) +{ + int32 status = OS_SUCCESS; + SecurityAssociation_t* sa = malloc(sizeof(SecurityAssociation_t)); + + if(mysql_query(con,query)) { + status = finish_with_error(con,SADB_QUERY_FAILED); return status; + } + // todo - if query fails, need to push failure message to error stack instead of just return code. MYSQL_RES *result = mysql_store_result(con); - if(result == NULL) { status = finish_with_error(con,SADB_QUERY_BY_SPI_EMPTY_RESULTS); } + if(result == NULL) { + status = finish_with_error(con,SADB_QUERY_EMPTY_RESULTS); return status; + } int num_fields = mysql_num_fields(result); @@ -127,10 +191,10 @@ static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_as } } //Handle query results - int sa_id; + int spi; uint8 tmp_uint8; if(row[i]==NULL){continue;} //Don't do anything with NULL fields from MySQL query. - if(strcmp(field_names[i],"sa_id")==0){sa_id = atoi(row[i]);continue;} + if(strcmp(field_names[i],"spi")==0){sa->spi = atoi(row[i]);continue;} if(strcmp(field_names[i],"ekid")==0){sa->ekid=atoi(row[i]);continue;} if(strcmp(field_names[i],"akid")==0){sa->akid=atoi(row[i]);continue;} if(strcmp(field_names[i],"sa_state")==0){sa->sa_state=atoi(row[i]);continue;} @@ -148,37 +212,25 @@ static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_as if(strcmp(field_names[i],"ecs_len")==0){sa->ecs_len=atoi(row[i]);continue;} if(strcmp(field_names[i],"ecs")==0){tmp_uint8 = (uint8)atoi(row[i]); memcpy(&(sa->ecs),&tmp_uint8,sizeof(tmp_uint8));continue;} if(strcmp(field_names[i],"iv_len")==0){sa->iv_len=atoi(row[i]);continue;} - if(strcmp(field_names[i],"iv")==0){tmp_uint8 =(uint8) atoi(row[i]); memcpy(&(sa->iv),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"iv")==0){memcpy(&(sa->iv),&row[i],sizeof(row[i]));continue;} if(strcmp(field_names[i],"acs_len")==0){sa->acs_len=atoi(row[i]);continue;} if(strcmp(field_names[i],"acs")==0){sa->acs=atoi(row[i]);continue;} if(strcmp(field_names[i],"abm_len")==0){sa->abm_len=atoi(row[i]);continue;} if(strcmp(field_names[i],"abm")==0){tmp_uint8 = (uint8)atoi(row[i]);memcpy(&(sa->abm),&tmp_uint8,sizeof(tmp_uint8));continue;} if(strcmp(field_names[i],"arc_len")==0){sa->arc_len=atoi(row[i]);continue;} - if(strcmp(field_names[i],"arc")==0){tmp_uint8 = (uint8)atoi(row[i]);memcpy(&(sa->arc),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"arc")==0){memcpy(&(sa->arc),&row[i],sizeof(row[i]));continue;} if(strcmp(field_names[i],"arcw_len")==0){sa->arcw_len=atoi(row[i]);continue;} if(strcmp(field_names[i],"arcw")==0){tmp_uint8 = (uint8)atoi(row[i]);memcpy(&(sa->arcw),&tmp_uint8,sizeof(tmp_uint8));continue;} //printf("%s:%s ",field_names[i], row[i] ? row[i] : "NULL"); } - printf("\n"); + //printf("\n"); } *security_association = sa; mysql_free_result(result); - //set all the SA fields from the query results. - //*security_association.vcid = return status; } -// Security Association Utility Functions -static int32 sadb_sa_start(TC_t* tc_frame){return OS_SUCCESS;} -static int32 sadb_sa_expire(void){return OS_SUCCESS;} -static int32 sadb_sa_rekey(void){return OS_SUCCESS;} -static int32 sadb_sa_status(char* ingest){return OS_SUCCESS;} -static int32 sadb_sa_create(void){return OS_SUCCESS;} -static int32 sadb_sa_setARSN(void){return OS_SUCCESS;} -static int32 sadb_sa_setARSNW(void){return OS_SUCCESS;} -static int32 sadb_sa_delete(void){return OS_SUCCESS;} - static int32 finish_with_error(MYSQL *con, int err) { From 6ace730353c12b357d3ec067f9c8650e8f678b0f Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 17 Nov 2021 09:27:39 -0800 Subject: [PATCH 043/184] AKMC-113: Fix merge bug with tempSA reference --- fsw/src/sadb_routine_inmemory.template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c index 7cb67234..84479080 100644 --- a/fsw/src/sadb_routine_inmemory.template.c +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -250,7 +250,7 @@ static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_as *security_association = &sa[spi]; #ifdef SA_DEBUG OS_printf(KYEL "DEBUG - Printing local copy of SA Entry for current SPI.\n" RESET); - Crypto_saPrint(&temp_SA); + Crypto_saPrint(*security_association); #endif return status; } From 126966c96c3ee5d602f5016cd5c95308012c5049 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 17 Nov 2021 16:16:14 -0800 Subject: [PATCH 044/184] AKMC-113: Add SADB MariaDB code for working with MySQL BINARY fields --- .../create_sadb.sql | 10 +-- ...e_sadb_unit_test_security_associations.sql | 16 ++-- fsw/src_mysql/sadb_routine_mariadb.template.c | 83 +++++++++++++++---- 3 files changed, 78 insertions(+), 31 deletions(-) diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql index 7f93b27a..00c2b8d9 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql @@ -22,15 +22,15 @@ CREATE TABLE security_associations ,shplf_len SMALLINT ,stmacf_len SMALLINT ,ecs_len SMALLINT - ,ecs SMALLINT NOT NULL DEFAULT 0 + ,ecs BINARY(4) NOT NULL DEFAULT X'00000000' -- ECS_SIZE=4 ,iv_len SMALLINT NOT NULL DEFAULT 12 - ,iv BINARY(12) NOT NULL DEFAULT 0 -- IV_SIZE=12 + ,iv BINARY(12) NOT NULL DEFAULT X'000000000000000000000000' -- IV_SIZE=12 ,acs_len SMALLINT NOT NULL DEFAULT 0 ,acs SMALLINT NOT NULL DEFAULT 0 ,abm_len MEDIUMINT - ,abm SMALLINT + ,abm BINARY(20) NOT NULL DEFAULT X'1111111111111111111111111111111111111111' -- ABM_SIZE=20 ,arc_len SMALLINT NOT NULL DEFAULT 0 - ,arc BINARY(20) NOT NULL DEFAULT 0 -- ARC_LEN=20 , TBD why so large... + ,arc BINARY(20) NOT NULL DEFAULT X'0000000000000000000000000000000000000000' -- ARC_SIZE=20 , TBD why so large... ,arcw_len SMALLINT - ,arcw SMALLINT + ,arcw BINARY(1) NOT NULL DEFAULT X'00' -- ARCW_SIZE=1 ); \ No newline at end of file diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql index 024bf989..acd92c60 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql @@ -2,32 +2,32 @@ USE sadb; -- SA 1 - CLEAR MODE INSERT INTO security_associations (spi,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) -VALUES (1,3,0,0,1,0,1,5,0,3,0,0); +VALUES (1,3,0,0,1,X'0000000000000000000000000000000000000000',1,X'0101',0,3,0,0); -- SA 2 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 128 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) -VALUES (2,128,2,1,1,12,12,0,20,0,1,5,11); +VALUES (2,128,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11); -- SA 3 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 129 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,stmacf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) -VALUES (3,129,2,1,1,12,16,12,0,20,0,1,5,11); +VALUES (3,129,2,1,1,12,16,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11); -- SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) -VALUES (4,130,2,1,1,12,12,0,20,0,1,5,11,0,3,0,0); +VALUES (4,130,2,1,1,12,12,X'000000000000000000000001',20,X'0000000000000000000000000000000000000000',1,5,11,0,3,0,0); -- SA 5 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 131 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) -VALUES (5,131,2,1,1,12,12,0,20,0,1,5,11); +VALUES (5,131,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11); -- SA 6 - UNKEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: - INSERT INTO security_associations (spi,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) -VALUES (6,1,1,1,12,12,0,20,0,1,5,11); +VALUES (6,1,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11); -- SA 7 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) -VALUES (7,130,2,1,1,12,12,0,20,0,1,5,11,0,3,1,0); +VALUES (7,130,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11,0,3,1,0); -- SA 8 - CLEAR MODE INSERT INTO security_associations (spi,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) -VALUES (8,3,0,0,1,0,1,5,0,3,1,0); +VALUES (8,3,0,0,1,X'0000000000000000000000000000000000000000',1,5,0,3,1,0); diff --git a/fsw/src_mysql/sadb_routine_mariadb.template.c b/fsw/src_mysql/sadb_routine_mariadb.template.c index 0ec689c3..be6b447d 100644 --- a/fsw/src_mysql/sadb_routine_mariadb.template.c +++ b/fsw/src_mysql/sadb_routine_mariadb.template.c @@ -43,15 +43,18 @@ static int32 sadb_sa_delete(void); //MySQL local functions static int32 finish_with_error(MYSQL *con,int err); //MySQL Queries -const static char* SQL_SADB_GET_SA_BY_SPI = "SELECT * FROM security_associations WHERE spi='%d';"; -const static char* SQL_SADB_GET_SA_BY_GVCID = "SELECT * FROM security_associations WHERE tfvn='%d' AND scid='%d' AND vcid='%d' AND mapid='%d';"; -const static char* SQL_SADB_UPDATE_IV_ARC_BY_SPI = "UPDATE security_associations "\ - "SET iv='%d', arc='%d' " \ - "WHERE spi='%d'AND tfvn='%d' AND scid='%d' AND vcid='%d' AND mapid='%d';"; +const static char* SQL_SADB_GET_SA_BY_SPI = "SELECT spi,ekid,akid,sa_state,tfvn,scid,vcid,mapid,lpid,est,ast,shivf_len,shsnf_len,shplf_len,stmacf_len,ecs_len,HEX(ecs),iv_len,HEX(iv),acs_len,acs,abm_len,HEX(abm),arc_len,HEX(arc),arcw_len,HEX(arcw)" + " FROM security_associations WHERE spi='%d'"; +const static char* SQL_SADB_GET_SA_BY_GVCID = "SELECT spi,ekid,akid,sa_state,tfvn,scid,vcid,mapid,lpid,est,ast,shivf_len,shsnf_len,shplf_len,stmacf_len,ecs_len,HEX(ecs),iv_len,HEX(iv),acs_len,acs,abm_len,HEX(abm),arc_len,HEX(arc),arcw_len,HEX(arcw)" + " FROM security_associations WHERE tfvn='%d' AND scid='%d' AND vcid='%d' AND mapid='%d' AND sa_state='%d'"; +const static char* SQL_SADB_UPDATE_IV_ARC_BY_SPI = "UPDATE security_associations" + " SET iv=X'%s', arc=X'%s'" + " WHERE spi='%d'AND tfvn='%d' AND scid='%d' AND vcid='%d' AND mapid='%d'"; // sadb_routine mariaDB private helper functions static int32 parse_sa_from_mysql_query(char* query, SecurityAssociation_t** security_association); - +static int32 convert_hexstring_to_byte_array(char* hexstr, uint8* byte_array); +static char* convert_byte_array_to_hexstring(void* src_buffer, size_t buffer_length); /* ** Global Variables @@ -122,7 +125,7 @@ static int32 sadb_get_operational_sa_from_gvcid(uint8 tfvn,uint16 scid,uint16 vc int32 status = OS_SUCCESS; char gvcid_query[2048]; - snprintf(gvcid_query, sizeof(gvcid_query),SQL_SADB_GET_SA_BY_GVCID,tfvn,scid,vcid,mapid); + snprintf(gvcid_query, sizeof(gvcid_query),SQL_SADB_GET_SA_BY_GVCID,tfvn,scid,vcid,mapid,SA_OPERATIONAL); status = parse_sa_from_mysql_query(&gvcid_query[0],security_association); @@ -132,11 +135,15 @@ static int32 sadb_save_sa(SecurityAssociation_t* sa) { int32 status = OS_SUCCESS; - char gvcid_query[2048]; - snprintf(gvcid_query, sizeof(gvcid_query),SQL_SADB_UPDATE_IV_ARC_BY_SPI,sa->iv,sa->arc,sa->spi,sa->gvcid_tc_blk.tfvn,sa->gvcid_tc_blk.scid,sa->gvcid_tc_blk.vcid,sa->gvcid_tc_blk.mapid); + char update_sa_query[2048]; + snprintf(update_sa_query, sizeof(update_sa_query),SQL_SADB_UPDATE_IV_ARC_BY_SPI,convert_byte_array_to_hexstring(sa->iv,sa->shivf_len),convert_byte_array_to_hexstring(sa->arc,sa->shsnf_len),sa->spi,sa->gvcid_tc_blk.tfvn,sa->gvcid_tc_blk.scid,sa->gvcid_tc_blk.vcid,sa->gvcid_tc_blk.mapid); - Crypto_saPrint(sa); - if(mysql_query(con,gvcid_query)) { + #ifdef SA_DEBUG + fprintf(stderr,"MySQL Insert SA Query: %s \n", update_sa_query); + #endif + + //Crypto_saPrint(sa); + if(mysql_query(con,update_sa_query)) { status = finish_with_error(con,SADB_QUERY_FAILED); return status; } // todo - if query fails, need to push failure message to error stack instead of just return code. @@ -161,7 +168,11 @@ static int32 parse_sa_from_mysql_query(char* query, SecurityAssociation_t** secu int32 status = OS_SUCCESS; SecurityAssociation_t* sa = malloc(sizeof(SecurityAssociation_t)); - if(mysql_query(con,query)) { + #ifdef SA_DEBUG + fprintf(stderr,"MySQL Query: %s \n", query); + #endif + + if(mysql_real_query(con,query,strlen(query))) { //query should be NUL terminated! status = finish_with_error(con,SADB_QUERY_FAILED); return status; } // todo - if query fails, need to push failure message to error stack instead of just return code. @@ -210,17 +221,18 @@ static int32 parse_sa_from_mysql_query(char* query, SecurityAssociation_t** secu if(strcmp(field_names[i],"shplf_len")==0){sa->shplf_len=atoi(row[i]);continue;} if(strcmp(field_names[i],"stmacf_len")==0){sa->stmacf_len=atoi(row[i]);continue;} if(strcmp(field_names[i],"ecs_len")==0){sa->ecs_len=atoi(row[i]);continue;} - if(strcmp(field_names[i],"ecs")==0){tmp_uint8 = (uint8)atoi(row[i]); memcpy(&(sa->ecs),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"HEX(ecs)")==0){convert_hexstring_to_byte_array(row[i],sa->ecs);continue;} if(strcmp(field_names[i],"iv_len")==0){sa->iv_len=atoi(row[i]);continue;} - if(strcmp(field_names[i],"iv")==0){memcpy(&(sa->iv),&row[i],sizeof(row[i]));continue;} + //if(strcmp(field_names[i],"HEX(iv)")==0){memcpy(&(sa->iv),&row[i],IV_SIZE);continue;} + if(strcmp(field_names[i],"HEX(iv)")==0){convert_hexstring_to_byte_array(row[i],sa->iv);continue;} if(strcmp(field_names[i],"acs_len")==0){sa->acs_len=atoi(row[i]);continue;} if(strcmp(field_names[i],"acs")==0){sa->acs=atoi(row[i]);continue;} if(strcmp(field_names[i],"abm_len")==0){sa->abm_len=atoi(row[i]);continue;} - if(strcmp(field_names[i],"abm")==0){tmp_uint8 = (uint8)atoi(row[i]);memcpy(&(sa->abm),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"HEX(abm)")==0){convert_hexstring_to_byte_array(row[i],sa->abm);continue;} if(strcmp(field_names[i],"arc_len")==0){sa->arc_len=atoi(row[i]);continue;} - if(strcmp(field_names[i],"arc")==0){memcpy(&(sa->arc),&row[i],sizeof(row[i]));continue;} + if(strcmp(field_names[i],"HEX(arc)")==0){convert_hexstring_to_byte_array(row[i],sa->arc);continue;} if(strcmp(field_names[i],"arcw_len")==0){sa->arcw_len=atoi(row[i]);continue;} - if(strcmp(field_names[i],"arcw")==0){tmp_uint8 = (uint8)atoi(row[i]);memcpy(&(sa->arcw),&tmp_uint8,sizeof(tmp_uint8));continue;} + if(strcmp(field_names[i],"HEX(arcw)")==0){convert_hexstring_to_byte_array(row[i],sa->arcw);continue;} //printf("%s:%s ",field_names[i], row[i] ? row[i] : "NULL"); } //printf("\n"); @@ -231,10 +243,45 @@ static int32 parse_sa_from_mysql_query(char* query, SecurityAssociation_t** secu return status; } +static int32 convert_hexstring_to_byte_array(char* source_str, uint8* dest_buffer) +{ // https://stackoverflow.com/questions/3408706/hexadecimal-string-to-byte-array-in-c/56247335#56247335 + char *line = source_str; + char *data = line; + int offset; + uint8 read_byte; + uint8 data_len = 0; + + while (sscanf(data, " %02x%n", &read_byte, &offset) == 1) { + dest_buffer[data_len++] = read_byte; + data += offset; + } + return data_len; +} + +static char* convert_byte_array_to_hexstring(void* src_buffer, size_t buffer_length) +{ + if(buffer_length==0){ //Return empty string (with null char!) if buffer is empty + return ""; + } + + unsigned char* bytes = src_buffer; + unsigned char* hexstr = malloc(buffer_length*2+1); + + if(src_buffer == NULL) return NULL; + + for(size_t i = 0; i < buffer_length; i++){ + uint8 nib1 = (bytes[i] >> 4) & 0x0F; + uint8 nib2 = (bytes[i]) & 0x0F; + hexstr[i*2+0] = nib1 < 0xA ? '0' + nib1 : 'A' + nib1 - 0xA; + hexstr[i*2+1] = nib2 < 0xA ? '0' + nib2 : 'A' + nib2 - 0xA; + } + return hexstr; +} + static int32 finish_with_error(MYSQL *con, int err) { - fprintf(stderr, "%s\n", mysql_error(con)); + fprintf(stderr, "%s%s%s\n", KRED,mysql_error(con),RESET); // todo - if query fails, need to push failure message to error stack mysql_close(con); return err; } \ No newline at end of file From 18d892f12d983301720a546da59958030b71dddc Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 1 Dec 2021 14:56:22 -0800 Subject: [PATCH 045/184] AKMC-97: Add internal logic for dynamic CryptoLib configuration from downstream applications --- fsw/public_inc/crypto.h | 10 +- fsw/public_inc/crypto_config.h | 14 +- fsw/public_inc/crypto_config_structs.h | 78 +++++++ fsw/public_inc/crypto_error.h | 3 + fsw/src/crypto.c | 204 +++++++++++++----- fsw/src/sadb_routine_inmemory.template.c | 2 +- fsw/src_mysql/sadb_routine_mariadb.template.c | 4 +- 7 files changed, 246 insertions(+), 69 deletions(-) create mode 100644 fsw/public_inc/crypto_config_structs.h diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index 0efa38f4..f4c1f879 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -28,6 +28,7 @@ ivv-itc@lists.nasa.gov #endif #include "crypto_structs.h" +#include "crypto_config_structs.h" #define CRYPTO_LIB_MAJOR_VERSION 1 #define CRYPTO_LIB_MINOR_VERSION 2 @@ -38,7 +39,9 @@ ivv-itc@lists.nasa.gov ** Prototypes */ // Initialization -extern int32 Crypto_Init(void); +extern int32 Crypto_Init(void); //Initialize CryptoLib with defaults +extern int32 Crypto_Init_Main(CryptoConfig_t* config,SadbMariaDBConfig_t* sadb_mariadb_config); //Initialize CryptoLib with application specified defaults +extern int32 Crypto_Init_With_Props(char** configs,int32 num_configs); //Initialize CryptoLib with string properties per SIS // Telecommand (TC) extern int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ uint8 **pp_enc_frame, uint16 *p_enc_frame_len); @@ -61,5 +64,10 @@ extern crypto_key_t ek_ring[NUM_KEYS]; extern uint8 Crypto_Prep_Reply(char* ingest, uint8 appID); extern int32 Crypto_increment(uint8 *num, int length); +//Global configuration structs +extern CryptoConfig_t* crypto_config; +extern SadbMariaDBConfig_t* sadb_mariadb_config; +extern GvcidManagedParameters_t* gvcid_managed_parameters; +extern GvcidManagedParameters_t* current_managed_parameters; #endif \ No newline at end of file diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index ad24ed8d..367b313d 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -111,6 +111,7 @@ ivv-itc@lists.nasa.gov #define OCF_SIZE 4 #define MAC_SIZE 16 /* bytes */ #define FECF_SIZE 2 + #define SEGMENT_HDR_SIZE 1 #define ECS_SIZE 4 /* bytes */ #define ABM_SIZE 20 /* bytes */ #define ARC_SIZE 20 /* total messages */ @@ -164,7 +165,6 @@ ivv-itc@lists.nasa.gov // CCSDS PUS Defines #define TLV_DATA_SIZE 494 /* bytes */ - #define PUS_HDR 1 //(1=true,0=false) // TM Defines #define TM_FRAME_DATA_SIZE 1740 /* bytes */ @@ -172,16 +172,6 @@ ivv-itc@lists.nasa.gov #define TM_PAD_SIZE 2 /* bytes */ // TC Behavior Defines - #define TC_PROCESS_SDLS_PDUS 1 //(1=true,0=false) #define TC_SDLS_EP_VCID 4 //VCID which has SDLS PDUs (JPL uses VCIDs to determine TC type, there is no space packet layer with APIDs). Set to -1 if uses SP APIDs. - #define VCID_BITMASK 0b111111 //Some JPL missions do not use the entire CCSDS 6 bit field for VCID. - #define SEGMENTATION_HDR 1 //(1=true,0=false) - #define HAS_FECF 1 //(1=true,0=false) - -// MySQL - MariaDB Defines (will be dynamically loaded properties in the future) - #define MYSQL_USER "sadb_user" - #define MYSQL_PASS "sadb_password" - #define MYSQL_HOST "localhost" - #define MYSQL_DB "sadb" - #define MYSQL_PORT 0 + #endif \ No newline at end of file diff --git a/fsw/public_inc/crypto_config_structs.h b/fsw/public_inc/crypto_config_structs.h new file mode 100644 index 00000000..808ade46 --- /dev/null +++ b/fsw/public_inc/crypto_config_structs.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + +This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not +limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +any warranty that the software will be error free. + +In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +documentation or services provided hereunder + +ITC Team +NASA IV&V +ivv-itc@lists.nasa.gov +*/ +#ifndef _crypto_config_structs_h_ +#define _crypto_config_structs_h_ + +#include "crypto_config.h" + +#ifdef NOS3 //NOS3/cFS build is ready +#include "common_types.h" +#else //Assume build outside of NOS3/cFS infrastructure +#include "common_types_minimum.h" +#endif + +//main config enums +typedef enum { SADB_TYPE_INMEMORY, SADB_TYPE_MARIADB } SadbType; +//gvcid managed parameter enums +typedef enum { TC_NO_FECF, TC_HAS_FECF } TcFecfPresent; +typedef enum { TC_NO_SEGMENT_HDRS, TC_HAS_SEGMENT_HDRS } TcSegmentHdrsPresent; +typedef enum { CRYPTO_TC_CREATE_FECF_FALSE, CRYPTO_TC_CREATE_FECF_TRUE } TcCreateFecfBool; +typedef enum { TC_PROCESS_SDLS_PDUS_FALSE, TC_PROCESS_SDLS_PDUS_TRUE } TcProcessSdlsPdus; +typedef enum { TC_NO_PUS_HDR, TC_HAS_PUS_HDR } TcPusHdrPresent; +typedef enum { TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_SA_STATE_TRUE } TcIgnoreSaState; +typedef enum { TC_IGNORE_ANTI_REPLAY_FALSE, TC_IGNORE_ANTI_REPLAY_TRUE } TcIgnoreAntiReplay; + +/* +** Main Crypto Configuration Block +*/ +typedef struct +{ + SadbType sadb_type; + TcCreateFecfBool crypto_create_fecf; //Whether or not CryptoLib is expected to calculate TC FECFs and return payloads with the FECF + TcProcessSdlsPdus process_sdls_pdus; //Config to process SDLS extended procedure PDUs in CryptoLib + TcPusHdrPresent has_pus_hdr; + TcIgnoreSaState ignore_sa_state; //TODO - add logic that uses this configuration + TcIgnoreAntiReplay ignore_anti_replay; //TODO - add logic that uses this configuration + uint8 vcid_bitmask; +} CryptoConfig_t; +#define CRYPTO_CONFIG_SIZE (sizeof(CryptoConfig_t)) + +typedef struct _GvcidManagedParameters_t GvcidManagedParameters_t; +struct _GvcidManagedParameters_t{ + uint8 tfvn :4; // Transfer Frame Version Number + uint16 scid :10; //SpacecraftID + uint8 vcid :6; //Virtual Channel ID + TcFecfPresent has_fecf; + TcSegmentHdrsPresent has_segmentation_hdr; + GvcidManagedParameters_t* next; //Will be a list of managed parameters! +}; +#define GVCID_MANAGED_PARAMETERS_SIZE (sizeof(GvcidManagedParameters_t)) + +/* +** SaDB MariaDB Configuration Block +*/ +typedef struct +{ + char* mysql_username; + char* mysql_password; + char* mysql_hostname; + char* mysql_database; + uint16 mysql_port; +} SadbMariaDBConfig_t; +#define SADB_MARIADB_CONFIG_SIZE (sizeof(SadbMariaDBConfig_t)) + +#endif \ No newline at end of file diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h index 08f9a89c..238a5506 100644 --- a/fsw/public_inc/crypto_error.h +++ b/fsw/public_inc/crypto_error.h @@ -19,5 +19,8 @@ ivv-itc@lists.nasa.gov #include "sadb_mariadb_error.h" +#define SADB_INVALID_SADB_TYPE 201 +#define MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND 101 + #endif //_crypto_error_h_ diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 05281ed8..3afd439b 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -27,9 +27,11 @@ ivv-itc@lists.nasa.gov #include "itc_gcm128.h" #include "crypto_structs.h" +#include "crypto_config_structs.h" #include "crypto_print.h" #include "crypto_config.h" #include "crypto_events.h" +#include "crypto_error.h" @@ -86,6 +88,9 @@ static int32 Crypto_User_ModifyActiveTM(void); static int32 Crypto_User_ModifyVCID(void); // Determine Payload Data Unit static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); +// Managed Parameter Functions +static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, + GvcidManagedParameters_t** managed_parameters_out); /* ** Global Variables @@ -95,6 +100,10 @@ crypto_key_t ek_ring[NUM_KEYS] = {0}; //static crypto_key_t ak_ring[NUM_KEYS]; CCSDS_t sdls_frame; TM_t tm_frame; +CryptoConfig_t* crypto_config; +SadbMariaDBConfig_t* sadb_mariadb_config; +GvcidManagedParameters_t* gvcid_managed_parameters; +GvcidManagedParameters_t* current_managed_parameters; // OCF static uint8 ocf = 0; static SDLS_FSR_t report; @@ -112,18 +121,64 @@ static uint8 badFECF = 0; // CRC static uint32 crc32Table[256]; static uint16 crc16Table[256]; - /* ** Initialization Functions */ int32 Crypto_Init(void) -{ +{ + int32 status = OS_SUCCESS; + CryptoConfig_t* config_local = (CryptoConfig_t*) calloc(1, CRYPTO_CONFIG_SIZE); + config_local->sadb_type=SADB_TYPE_INMEMORY; + config_local->crypto_create_fecf=CRYPTO_TC_CREATE_FECF_TRUE; + config_local->process_sdls_pdus=TC_PROCESS_SDLS_PDUS_TRUE; + config_local->has_pus_hdr=TC_HAS_PUS_HDR; + config_local->vcid_bitmask=0x3F; + gvcid_managed_parameters = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); + + //initialize managed parameters as expected for unit tests + gvcid_managed_parameters->tfvn=0; + gvcid_managed_parameters->scid=0x0003; + gvcid_managed_parameters->vcid=0; + gvcid_managed_parameters->has_fecf=TC_HAS_FECF; + gvcid_managed_parameters->has_segmentation_hdr=TC_HAS_SEGMENT_HDRS; + gvcid_managed_parameters->next=NULL; + current_managed_parameters = gvcid_managed_parameters; + + SadbMariaDBConfig_t* sadb_mariadb_config_local = (SadbMariaDBConfig_t*)calloc(1, SADB_MARIADB_CONFIG_SIZE); + sadb_mariadb_config_local->mysql_username="sadb_user"; + sadb_mariadb_config_local->mysql_password="sadb_password"; + sadb_mariadb_config_local->mysql_hostname="localhost"; + sadb_mariadb_config_local->mysql_database="sadb"; + sadb_mariadb_config_local->mysql_port=0; + + //config->sadb_type=SADB_MARIADB_TYPE; + + status = Crypto_Init_Main(config_local,sadb_mariadb_config_local); + return status; +} +int32 Crypto_Init_With_Props(char** configs, int32 num_configs) +{ + int32 status = OS_SUCCESS; + CryptoConfig_t* config_local = (CryptoConfig_t*) calloc(1, CRYPTO_CONFIG_SIZE); + SadbMariaDBConfig_t* sadb_mariadb_config_local = (SadbMariaDBConfig_t*) calloc(1, SADB_MARIADB_CONFIG_SIZE); + + //Todo - Parse Gvcid Managed Parameters and CryptoLib config from input properties! + + status = Crypto_Init_Main(config_local,sadb_mariadb_config_local); + return status; +} +int32 Crypto_Init_Main(CryptoConfig_t* config_p,SadbMariaDBConfig_t* sadb_mariadb_config_p) +{ int32 status = OS_SUCCESS; - //TODO -- Make the routine that gets called variable based on configuration! - sadb_routine = get_sadb_routine_inmemory(); - //sadb_routine = get_sadb_routine_mariadb(); + //Set global vars to passed in config objects. + crypto_config = config_p; + sadb_mariadb_config = sadb_mariadb_config_p; + //Prepare SADB type from config + if (crypto_config->sadb_type == SADB_TYPE_INMEMORY){ sadb_routine = get_sadb_routine_inmemory(); } + else if (crypto_config->sadb_type == SADB_TYPE_MARIADB){ sadb_routine = get_sadb_routine_mariadb(); } + else { status = SADB_INVALID_SADB_TYPE; return status; } //TODO: Error stack // Initialize libgcrypt if (!gcry_check_version(GCRYPT_VERSION)) @@ -635,10 +690,10 @@ static void Crypto_Calc_CRC_Init_Table(void) static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame) // Returns the payload length of current tc_frame in BYTES! { - int seg_hdr = 0;if(SEGMENTATION_HDR){seg_hdr=1;} - int fecf = 0;if(HAS_FECF){fecf=FECF_SIZE;} + int seg_hdr = 0;if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){seg_hdr=1;} + int fecf = 0;if(current_managed_parameters->has_fecf==TC_HAS_FECF){fecf=FECF_SIZE;} int spi = 2; - int iv_size = IV_SIZE_TC; if(PUS_HDR){iv_size=IV_SIZE - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. + int iv_size = IV_SIZE_TC; if(crypto_config->has_pus_hdr==TC_HAS_PUS_HDR){iv_size=IV_SIZE - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. int tf_hdr = 5; return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (MAC_SIZE + FECF_SIZE) ); @@ -1689,13 +1744,13 @@ static int32 Crypto_User_BadIV(void) if (badIV == 0) { badIV = 1; - } + } else { badIV = 0; } - - return OS_SUCCESS; + + return OS_SUCCESS; } static int32 Crypto_User_BadFECF(void) @@ -2031,6 +2086,32 @@ static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) return status; } + +static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, + GvcidManagedParameters_t** managed_parameters_out) +{ + int32 status = OS_SUCCESS; + + if (managed_parameters_in == NULL) { return MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND; } + + if(managed_parameters_in->tfvn==tfvn && managed_parameters_in->scid==scid && managed_parameters_in->vcid==vcid){ + *managed_parameters_out = managed_parameters_in;//Found the managed parameters for that gvcid! + } else { status = MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND; } + + //Go through list of ManagedParameters until you find correct params for gvcid. + while(managed_parameters_in->next != NULL){ + managed_parameters_in = managed_parameters_in->next; + if(managed_parameters_in->tfvn==tfvn && managed_parameters_in->scid==scid && managed_parameters_in->vcid==vcid){ + *managed_parameters_out = managed_parameters_in; //Found the managed parameters for that gvcid! + status = OS_SUCCESS; + break; + } + } + + return status; +} + + int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ uint8 **pp_in_frame, uint16 *p_enc_frame_len) { @@ -2075,15 +2156,23 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len temp_tc_header.spare = ((uint8)p_in_frame[0] & 0x0C) >> 2; temp_tc_header.scid = ((uint8)p_in_frame[0] & 0x03) << 8; temp_tc_header.scid = temp_tc_header.scid | (uint8)p_in_frame[1]; - temp_tc_header.vcid = ((uint8)p_in_frame[2] & 0xFC) >> 2 & VCID_BITMASK; + temp_tc_header.vcid = ((uint8)p_in_frame[2] & 0xFC) >> 2 & crypto_config->vcid_bitmask; temp_tc_header.fl = ((uint8)p_in_frame[2] & 0x03) << 8; temp_tc_header.fl = temp_tc_header.fl | (uint8)p_in_frame[3]; temp_tc_header.fsn = (uint8)p_in_frame[4]; - //TODO -- Handle segmentation header logic (this is a per-VCID managed parameter!) - //If segmentation header for VCID, parse out MAP_ID - // probably need to augment crypto_structs.h to handle segmentation headers. + //Lookup-retrieve managed parameters for frame via gvcid: + status = Crypto_Get_Managed_Parameters_For_Gvcid(temp_tc_header.tfvn,temp_tc_header.scid,temp_tc_header.vcid,gvcid_managed_parameters,¤t_managed_parameters); + if(status != OS_SUCCESS) {return status;} //Unable to get necessary Managed Parameters for TC TF -- return with error. + + + uint8 segmentation_hdr = 0x00; uint8 map_id = 0; + if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ + segmentation_hdr = p_in_frame[5]; + map_id = segmentation_hdr & 0x3F; + } + // Check if command frame flag set if ((temp_tc_header.cc == 1) && (status == OS_SUCCESS)) @@ -2099,10 +2188,6 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len status = OS_ERROR; } - // TODO: If command frame flag not set, need to know SDLS parameters - // What is the best way to do this - copy in the entire SA for a channel? - // Expect these calls will return an error is the SA is not usable - // Will need to know lengths of various parameters from the SA DB if (status == OS_SUCCESS) { // Query SA DB for active SA / SDLS parameters @@ -2164,34 +2249,34 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len #endif // Determine length of buffer to be malloced - // TODO: Determine presence of FECF & TC_PAD_SIZE + // TODO: Determine TC_PAD_SIZE // TODO: Note: Currently assumes ciphertext output length is same as ciphertext input length switch(sa_service_type) { case SA_PLAINTEXT: - // Ingest length + segment header (1) + spi_index (2) + some variable length fields - *p_enc_frame_len = in_frame_length + 1 + 2 + sa_ptr->shplf_len; + // Ingest length + spi_index (2) + some variable length fields + *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shplf_len; case SA_AUTHENTICATION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size + stmacf_len - *p_enc_frame_len = in_frame_length + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ - sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len;; + *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; case SA_ENCRYPTION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size - *p_enc_frame_len = in_frame_length + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE; case SA_AUTHENTICATED_ENCRYPTION: - // Ingest length + segment header (1) + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size + stmacf_len - *p_enc_frame_len = in_frame_length + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; } #ifdef TC_DEBUG OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *p_enc_frame_len); OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); - OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded + //OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, sa_ptr->shivf_len); OS_printf(KYEL "\tshsnf_len\t = %d\n" RESET, sa_ptr->shsnf_len); @@ -2233,11 +2318,10 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len ** Start variable length fields */ uint16_t index = TC_FRAME_PRIMARYHEADER_SIZE; - - // Set Segment Header flags - // TODO: Determine segment header exists - *(p_new_enc_frame + index) = 0xFF; - index++; + + if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ + index++; //Add 1 byte to index because segmentation header used for this gvcid. + } /* ** Begin Security Header Fields @@ -2319,12 +2403,16 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len ** End Security Header Fields */ + uint8 fecf_len = FECF_SIZE; + if(current_managed_parameters->has_fecf==TC_NO_FECF) { fecf_len = 0; } + uint8 segment_hdr_len = SEGMENT_HDR_SIZE; + if(current_managed_parameters->has_segmentation_hdr==TC_NO_SEGMENT_HDRS) { segment_hdr_len = 0; } // Copy in original TF data - except FECF // Will be over-written if using encryption later - // TODO: This will change depending on how we handle segment header and FECF above, // and if it was present in the original TCTF //if FECF - tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - FECF_SIZE; + // Even though FECF is not part of apply_security payload, we still have to subtract the length from the in_frame_length since that includes FECF length & segment header length. + tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - segment_hdr_len - fecf_len; //if no FECF //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; CFE_PSP_MemCpy((p_new_enc_frame+index), (p_in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); @@ -2444,7 +2532,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len tmp_hd, &p_new_enc_frame[index], // ciphertext output tf_payload_len, // length of data - (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now + (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE + segment_hdr_len), // plaintext input tf_payload_len // in data length ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -2486,17 +2574,19 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len ** End Authentication / Encryption */ - // Set FECF Field if present - // TODO: Determine is FECF is even present - // on this particular channel - // Calc new fecf, don't include old fecf in length - #ifdef FECF_DEBUG + //Only calculate & insert FECF if CryptoLib is configured to do so & gvcid includes FECF. + if( crypto_config->crypto_create_fecf==CRYPTO_TC_CREATE_FECF_TRUE && + current_managed_parameters->has_fecf==TC_HAS_FECF) + { + // Set FECF Field if present + #ifdef FECF_DEBUG OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *p_enc_frame_len - 2); - #endif - new_fecf = Crypto_Calc_FECF(p_new_enc_frame, *p_enc_frame_len - 2); - *(p_new_enc_frame + *p_enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); - *(p_new_enc_frame + *p_enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); - index += 2; + #endif + new_fecf = Crypto_Calc_FECF(p_new_enc_frame, *p_enc_frame_len - 2); + *(p_new_enc_frame + *p_enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(p_new_enc_frame + *p_enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); + index += 2; + } #ifdef TC_DEBUG OS_printf(KYEL "Printing new TC Frame:\n\t"); @@ -2544,7 +2634,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro byte_idx++; tc_sdls_processed_frame->tc_header.scid = tc_sdls_processed_frame->tc_header.scid | (uint8)ingest[byte_idx]; byte_idx++; - tc_sdls_processed_frame->tc_header.vcid = (((uint8)ingest[byte_idx] & 0xFC) >> 2) & VCID_BITMASK; + tc_sdls_processed_frame->tc_header.vcid = (((uint8)ingest[byte_idx] & 0xFC) >> 2) & crypto_config->vcid_bitmask; tc_sdls_processed_frame->tc_header.fl = ((uint8)ingest[byte_idx] & 0x03) << 8; byte_idx++; tc_sdls_processed_frame->tc_header.fl = tc_sdls_processed_frame->tc_header.fl | (uint8)ingest[byte_idx]; @@ -2552,8 +2642,14 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro tc_sdls_processed_frame->tc_header.fsn = (uint8)ingest[byte_idx]; byte_idx++; + //Lookup-retrieve managed parameters for frame via gvcid: + status = Crypto_Get_Managed_Parameters_For_Gvcid(tc_sdls_processed_frame->tc_header.tfvn,tc_sdls_processed_frame->tc_header.scid, + tc_sdls_processed_frame->tc_header.vcid,gvcid_managed_parameters,¤t_managed_parameters); + + if(status != OS_SUCCESS) {return status;} //Unable to get necessary Managed Parameters for TC TF -- return with error. + // Security Header - if(SEGMENTATION_HDR){ + if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ tc_sdls_processed_frame->tc_sec_header.sh = (uint8)ingest[byte_idx]; byte_idx++; } @@ -2565,7 +2661,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro #endif // Checks - if (PUS_HDR && ((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) + if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR && ((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) { // User packet check only used for ESA Testing! } @@ -2916,13 +3012,13 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } - if(!TC_PROCESS_SDLS_PDUS) //If we don't want to process frame data for SDLS PDUs, only reverse security & return content. + if(crypto_config->process_sdls_pdus==TC_PROCESS_SDLS_PDUS_FALSE) //If we don't want to process frame data for SDLS PDUs, only reverse security & return content. { // CCSDS Pass-through #ifdef DEBUG OS_printf(KGRN "CCSDS Pass-through \n" RESET); #endif - if (PUS_HDR) { + if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR) { for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl - 11); x++) { ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; #ifdef CCSDS_DEBUG @@ -2942,7 +3038,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } else //Process SDLS PDU { - if (PUS_HDR) + if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR) { if ((tc_sdls_processed_frame->tc_pdu[0] == 0x18) && (tc_sdls_processed_frame->tc_pdu[1] == 0x80)) // Crypto Lib Application ID diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c index 84479080..9a96474a 100644 --- a/fsw/src/sadb_routine_inmemory.template.c +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -319,7 +319,7 @@ static int32 sadb_sa_start(TC_t* tc_frame) (sdls_frame.pdu.data[count + 2] >> 4); gvcid.vcid = (sdls_frame.pdu.data[count + 2] << 4) | (sdls_frame.pdu.data[count + 3] && 0x3F); - if(SEGMENTATION_HDR){gvcid.mapid = (sdls_frame.pdu.data[count + 3]);} + if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){gvcid.mapid = (sdls_frame.pdu.data[count + 3]);} else {gvcid.mapid=0;} // TC diff --git a/fsw/src_mysql/sadb_routine_mariadb.template.c b/fsw/src_mysql/sadb_routine_mariadb.template.c index be6b447d..11d5b367 100644 --- a/fsw/src_mysql/sadb_routine_mariadb.template.c +++ b/fsw/src_mysql/sadb_routine_mariadb.template.c @@ -94,7 +94,9 @@ static int32 sadb_init(void) //TODO - add mysql_options/mysql_get_ssl_cipher logic for mTLS connections. - if (mysql_real_connect(con, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, MYSQL_PORT, NULL, 0) == NULL) + if (mysql_real_connect(con, sadb_mariadb_config->mysql_hostname, sadb_mariadb_config->mysql_username, + sadb_mariadb_config->mysql_password, sadb_mariadb_config->mysql_database, + sadb_mariadb_config->mysql_port, NULL, 0) == NULL) { //0,NULL,0 are port number, unix socket, client flag status = finish_with_error(con,SADB_MARIADB_CONNECTION_FAILED); } From 96ad37ff00903f1db5036124c643e383d30380de Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 1 Dec 2021 17:38:55 -0800 Subject: [PATCH 046/184] AKMC-97: Managed Parameter function code cleanup --- fsw/src/crypto.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 3afd439b..820c8fb0 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -91,6 +91,7 @@ static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); // Managed Parameter Functions static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, GvcidManagedParameters_t** managed_parameters_out); +static void Crypto_Free_Managed_Parameters(GvcidManagedParameters_t* managed_parameters); /* ** Global Variables @@ -2090,26 +2091,28 @@ static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, GvcidManagedParameters_t** managed_parameters_out) { - int32 status = OS_SUCCESS; - - if (managed_parameters_in == NULL) { return MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND; } + int32 status = MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND; - if(managed_parameters_in->tfvn==tfvn && managed_parameters_in->scid==scid && managed_parameters_in->vcid==vcid){ - *managed_parameters_out = managed_parameters_in;//Found the managed parameters for that gvcid! - } else { status = MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND; } - - //Go through list of ManagedParameters until you find correct params for gvcid. - while(managed_parameters_in->next != NULL){ - managed_parameters_in = managed_parameters_in->next; + while(managed_parameters_in != NULL){ if(managed_parameters_in->tfvn==tfvn && managed_parameters_in->scid==scid && managed_parameters_in->vcid==vcid){ *managed_parameters_out = managed_parameters_in; //Found the managed parameters for that gvcid! status = OS_SUCCESS; break; + } else{ //Managed parameters for gvcid not found, set pointer to next managed parameter. + managed_parameters_in = managed_parameters_in->next; } } - return status; } +//Managed parameters are expected to live the duration of the program, this may not be necessary. +//TODO - If this function is useful, we need to add a Crypto Shutdown method that invokes this internal free. +static void Crypto_Free_Managed_Parameters(GvcidManagedParameters_t* managed_parameters) +{ + if(managed_parameters->next != NULL){ + Crypto_Free_Managed_Parameters(managed_parameters->next); + } + free(managed_parameters); +} int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ From 059d142ff9a7a3f319e723c42235e999294f831e Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Fri, 3 Dec 2021 14:14:57 -0500 Subject: [PATCH 047/184] #20 - Find and replace old ITC headers for 2022 update; --- CMakeLists.txt | 13 +++++------ fsw/CMakeLists.txt | 12 +++++------ fsw/crypto_tests/CMakeLists.txt | 13 +++++------ fsw/crypto_util/CMakeLists.txt | 12 +++++------ fsw/crypto_util/app/apply_security.c | 12 +++++------ fsw/crypto_util/app/crypto_sequence.c | 12 +++++------ fsw/crypto_util/app/process_security.c | 12 +++++------ fsw/crypto_util/app/ut_tc_apply.c | 12 +++++------ fsw/crypto_util/include/apply_security.h | 12 +++++------ fsw/crypto_util/include/crypto_sequence.h | 12 +++++------ fsw/crypto_util/include/process_security.h | 12 +++++------ fsw/crypto_util/include/shared_util.h | 12 +++++------ fsw/crypto_util/include/ut_tc_apply.h | 12 +++++------ fsw/crypto_util/src/shared_util.c | 12 +++++------ fsw/public_inc/crypto.h | 25 +++++++++++----------- fsw/public_inc/crypto_config.h | 24 ++++++++++----------- fsw/public_inc/crypto_error.h | 24 ++++++++++----------- fsw/public_inc/crypto_events.h | 24 ++++++++++----------- fsw/public_inc/crypto_print.h | 12 +++++------ fsw/public_inc/crypto_structs.h | 25 +++++++++++----------- fsw/public_inc/itc_aes128.h | 12 +++++------ fsw/public_inc/itc_gcm128.h | 12 +++++------ fsw/public_inc/sadb_mariadb_error.h | 24 ++++++++++----------- fsw/src/crypto.c | 24 ++++++++++----------- fsw/src/crypto_print.c | 25 +++++++++++----------- fsw/src/itc_aes128.c | 12 +++++------ fsw/src/itc_gcm128.c | 12 +++++------ unit_test/crypto_test.py | 16 ++++++++++++++ 28 files changed, 231 insertions(+), 210 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33723c59..3db5d4e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,19 @@ -# Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +# Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. # -# This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -# limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +# This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not +# limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness # for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or # any warranty that the software will be error free. # # In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -# arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +# arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, # contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -# documentation or services provided hereunder +# documentation or services provided hereunder. # # ITC Team # NASA IV&V -# ivv-itc@lists.nasa.gov +# jstar-development-team@mail.nasa.gov + #cmake_minimum_required(VERSION 2.6.4) cmake_minimum_required(VERSION 3.14.0) diff --git a/fsw/CMakeLists.txt b/fsw/CMakeLists.txt index f684cc64..2219b961 100644 --- a/fsw/CMakeLists.txt +++ b/fsw/CMakeLists.txt @@ -1,18 +1,18 @@ -# Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +# Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. # -# This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -# limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +# This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not +# limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness # for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or # any warranty that the software will be error free. # # In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -# arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +# arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, # contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -# documentation or services provided hereunder +# documentation or services provided hereunder. # # ITC Team # NASA IV&V -# ivv-itc@lists.nasa.gov +# jstar-development-team@mail.nasa.gov include_directories(public_inc) diff --git a/fsw/crypto_tests/CMakeLists.txt b/fsw/crypto_tests/CMakeLists.txt index a64cf4d9..b39ceb3d 100644 --- a/fsw/crypto_tests/CMakeLists.txt +++ b/fsw/crypto_tests/CMakeLists.txt @@ -1,18 +1,19 @@ -# Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +# Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. # -# This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -# limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +# This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not +# limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness # for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or # any warranty that the software will be error free. # # In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -# arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +# arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, # contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -# documentation or services provided hereunder +# documentation or services provided hereunder. # # ITC Team # NASA IV&V -# ivv-itc@lists.nasa.gov +# jstar-development-team@mail.nasa.gov + set(PROJECT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) add_test(NAME Process_Security diff --git a/fsw/crypto_util/CMakeLists.txt b/fsw/crypto_util/CMakeLists.txt index be1b77be..2ae68dd0 100644 --- a/fsw/crypto_util/CMakeLists.txt +++ b/fsw/crypto_util/CMakeLists.txt @@ -1,18 +1,18 @@ -# Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +# Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. # -# This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -# limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness +# This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not +# limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness # for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or # any warranty that the software will be error free. # # In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -# arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, +# arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, # contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -# documentation or services provided hereunder +# documentation or services provided hereunder. # # ITC Team # NASA IV&V -# ivv-itc@lists.nasa.gov +# jstar-development-team@mail.nasa.gov include_directories(include) include_directories(../crypto/public_inc) diff --git a/fsw/crypto_util/app/apply_security.c b/fsw/crypto_util/app/apply_security.c index ca34e508..a6226bbb 100644 --- a/fsw/crypto_util/app/apply_security.c +++ b/fsw/crypto_util/app/apply_security.c @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ /* diff --git a/fsw/crypto_util/app/crypto_sequence.c b/fsw/crypto_util/app/crypto_sequence.c index fd8f5dc3..0f86fe52 100644 --- a/fsw/crypto_util/app/crypto_sequence.c +++ b/fsw/crypto_util/app/crypto_sequence.c @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ diff --git a/fsw/crypto_util/app/process_security.c b/fsw/crypto_util/app/process_security.c index 37682c70..39a46dd5 100644 --- a/fsw/crypto_util/app/process_security.c +++ b/fsw/crypto_util/app/process_security.c @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c index 1143a7e0..0794dc2c 100644 --- a/fsw/crypto_util/app/ut_tc_apply.c +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ /* diff --git a/fsw/crypto_util/include/apply_security.h b/fsw/crypto_util/include/apply_security.h index 093fee15..a24d6642 100644 --- a/fsw/crypto_util/include/apply_security.h +++ b/fsw/crypto_util/include/apply_security.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef CRYPTOLIB_APPLY_SECURITY_H diff --git a/fsw/crypto_util/include/crypto_sequence.h b/fsw/crypto_util/include/crypto_sequence.h index 117c06dd..e35f63fd 100644 --- a/fsw/crypto_util/include/crypto_sequence.h +++ b/fsw/crypto_util/include/crypto_sequence.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef CRYPTOLIB_CRYPTO_SEQUENCE_H diff --git a/fsw/crypto_util/include/process_security.h b/fsw/crypto_util/include/process_security.h index 1a81bf24..f344c082 100644 --- a/fsw/crypto_util/include/process_security.h +++ b/fsw/crypto_util/include/process_security.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef CRYPTOLIB_PROCESS_SECURITY_H diff --git a/fsw/crypto_util/include/shared_util.h b/fsw/crypto_util/include/shared_util.h index f94a6a69..5fb0bfb0 100644 --- a/fsw/crypto_util/include/shared_util.h +++ b/fsw/crypto_util/include/shared_util.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef CRYPTOLIB_SHARED_UTIL_H diff --git a/fsw/crypto_util/include/ut_tc_apply.h b/fsw/crypto_util/include/ut_tc_apply.h index 449d76df..8e46bd4d 100644 --- a/fsw/crypto_util/include/ut_tc_apply.h +++ b/fsw/crypto_util/include/ut_tc_apply.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef CRYPTOLIB_UT_TC_APPLY_H diff --git a/fsw/crypto_util/src/shared_util.c b/fsw/crypto_util/src/shared_util.c index 91def234..9b4358c2 100644 --- a/fsw/crypto_util/src/shared_util.c +++ b/fsw/crypto_util/src/shared_util.c @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #include "shared_util.h" diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index 0efa38f4..894fc3fc 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -1,19 +1,20 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov */ + #ifndef _crypto_h_ #define _crypto_h_ diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index ad24ed8d..57332ec1 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov */ #ifndef _crypto_config_h_ #define _crypto_config_h_ diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h index 08f9a89c..a70190bd 100644 --- a/fsw/public_inc/crypto_error.h +++ b/fsw/public_inc/crypto_error.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov */ #ifndef _crypto_error_h_ #define _crypto_error_h_ diff --git a/fsw/public_inc/crypto_events.h b/fsw/public_inc/crypto_events.h index aacec8d6..d859dd4e 100644 --- a/fsw/public_inc/crypto_events.h +++ b/fsw/public_inc/crypto_events.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov */ #ifndef _crypto_events_h_ #define _crypto_events_h_ diff --git a/fsw/public_inc/crypto_print.h b/fsw/public_inc/crypto_print.h index 13daaeb2..4ef442a3 100644 --- a/fsw/public_inc/crypto_print.h +++ b/fsw/public_inc/crypto_print.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef _crypto_print_h_ diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index 59021a06..4208d0e2 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -1,19 +1,20 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov */ + #ifndef _crypto_structs_h_ #define _crypto_structs_h_ diff --git a/fsw/public_inc/itc_aes128.h b/fsw/public_inc/itc_aes128.h index 2df99943..20feda12 100644 --- a/fsw/public_inc/itc_aes128.h +++ b/fsw/public_inc/itc_aes128.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef ITC_AES128_H diff --git a/fsw/public_inc/itc_gcm128.h b/fsw/public_inc/itc_gcm128.h index c9800af1..c85fe8bd 100644 --- a/fsw/public_inc/itc_gcm128.h +++ b/fsw/public_inc/itc_gcm128.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef ITC_GCM128_H diff --git a/fsw/public_inc/sadb_mariadb_error.h b/fsw/public_inc/sadb_mariadb_error.h index eb2b4686..985a87ac 100644 --- a/fsw/public_inc/sadb_mariadb_error.h +++ b/fsw/public_inc/sadb_mariadb_error.h @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov */ #ifndef _sadb_mariadb_error_h_ diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 05281ed8..47fc65cf 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any0 way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov */ #ifndef _crypto_c_ #define _crypto_c_ diff --git a/fsw/src/crypto_print.c b/fsw/src/crypto_print.c index e4627014..d3ef2421 100644 --- a/fsw/src/crypto_print.c +++ b/fsw/src/crypto_print.c @@ -1,19 +1,20 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. -This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not -limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness -for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or -any warranty that the software will be error free. + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. -In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, -arising out of, resulting from, or in any0 way connected with the software or its documentation. Whether or not based upon warranty, -contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, -documentation or services provided hereunder + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. -ITC Team -NASA IV&V -ivv-itc@lists.nasa.gov + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov */ + #ifndef _crypto_print_c_ #define _crypto_print_c_ diff --git a/fsw/src/itc_aes128.c b/fsw/src/itc_aes128.c index 526e0f66..3fda3282 100644 --- a/fsw/src/itc_aes128.c +++ b/fsw/src/itc_aes128.c @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef ITC_AES128_C diff --git a/fsw/src/itc_gcm128.c b/fsw/src/itc_gcm128.c index 0a3d9135..66982fb8 100644 --- a/fsw/src/itc_gcm128.c +++ b/fsw/src/itc_gcm128.c @@ -1,18 +1,18 @@ -/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not - limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or any warranty that the software will be error free. In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder + documentation or services provided hereunder. ITC Team NASA IV&V - ivv-itc@lists.nasa.gov + jstar-development-team@mail.nasa.gov */ #ifndef ITC_GCM128_C diff --git a/unit_test/crypto_test.py b/unit_test/crypto_test.py index 0b8b2b14..ab86a0ed 100644 --- a/unit_test/crypto_test.py +++ b/unit_test/crypto_test.py @@ -1,3 +1,19 @@ +# Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. +# +# This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not +# limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness +# for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or +# any warranty that the software will be error free. +# +# In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, +# arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, +# contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, +# documentation or services provided hereunder. +# +# ITC Team +# NASA IV&V +# jstar-development-team@mail.nasa.gov + # # Connect to cFS via UDP to CI_Lab and TO_Lab to send and receive messages # used to verify the SDLS-EP protocol via Interoperability Testing From 5f59ffb64381309b6f78bb5b663ed9cc3bf4b1d6 Mon Sep 17 00:00:00 2001 From: "Lucas, John P" Date: Fri, 3 Dec 2021 14:15:18 -0500 Subject: [PATCH 048/184] #20 - Added filled out NOSA 1.3; --- LICENSE | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..adc436e7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,263 @@ +NASA OPEN SOURCE AGREEMENT VERSION 1.3 + +THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE, +REPRODUCTION, DISTRIBUTION, MODIFICATION AND REDISTRIBUTION OF CERTAIN +COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT +AS REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT +AGENCY"). THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT +AGENCY, IS AN INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT +DISTRIBUTIONS OR REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO +USES, REPRODUCES, DISTRIBUTES, MODIFIES OR REDISTRIBUTES THE SUBJECT +SOFTWARE, AS DEFINED HEREIN, OR ANY PART THEREOF, IS, BY THAT ACTION, +ACCEPTING IN FULL THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN +THIS AGREEMENT. + +Government Agency: NASA +Government Agency Original Software Designation: GSC-17776-1 +Government Agency Original Software Title: + Core Flight System Cryptography Library +User Registration Requested. Please Visit + https://github.com/nasa/CryptoLib +Government Agency Point of Contact for Original Software: + John.P.Lucas@nasa.gov + +1. DEFINITIONS + +A. "Contributor" means Government Agency, as the developer of the +Original Software, and any entity that makes a Modification. +B. "Covered Patents" mean patent claims licensable by a Contributor +that are necessarily infringed by the use or sale of its Modification +alone or when combined with the Subject Software. +C. "Display" means the showing of a copy of the Subject Software, +either directly or by means of an image, or any other device. +D. "Distribution" means conveyance or transfer of the Subject +Software, regardless of means, to another. +E. "Larger Work" means computer software that combines Subject +Software, or portions thereof, with software separate from the Subject +Software that is not governed by the terms of this Agreement. +F. "Modification" means any alteration of, including addition to or +deletion from, the substance or structure of either the Original +Software or Subject Software, and includes derivative works, as that +term is defined in the Copyright Statute, 17 USC 101. However, the +act of including Subject Software as part of a Larger Work does not in +and of itself constitute a Modification. +G. "Original Software" means the computer software first released +under this Agreement by Government Agency with Government Agency +designation GSC-17776-1 and entitled Core Flight System Cryptography +Library, including source code, object code and accompanying +documentation, if any. +H. "Recipient" means anyone who acquires the Subject Software under +this Agreement, including all Contributors. +I. "Redistribution" means Distribution of the Subject Software after a +Modification has been made. +J. "Reproduction" means the making of a counterpart, image or copy of +the Subject Software. +K. "Sale" means the exchange of the Subject Software for money or +equivalent value. +L. "Subject Software" means the Original Software, Modifications, or +any respective parts thereof. +M. "Use" means the application or employment of the Subject Software +for any purpose. + +2. GRANT OF RIGHTS + +A. Under Non-Patent Rights: Subject to the terms and conditions of +this Agreement, each Contributor, with respect to its own contribution +to the Subject Software, hereby grants to each Recipient a +non-exclusive, world-wide, royalty-free license to engage in the +following activities pertaining to the Subject Software: + +1. Use +2. Distribution +3. Reproduction +4. Modification +5. Redistribution +6. Display + +B. Under Patent Rights: Subject to the terms and conditions of this +Agreement, each Contributor, with respect to its own contribution to +the Subject Software, hereby grants to each Recipient under Covered +Patents a non-exclusive, world-wide, royalty-free license to engage in +the following activities pertaining to the Subject Software: + +1. Use +2. Distribution +3. Reproduction +4. Sale +5. Offer for Sale + +C. The rights granted under Paragraph B. also apply to the combination +of a Contributor's Modification and the Subject Software if, at the +time the Modification is added by the Contributor, the addition of +such Modification causes the combination to be covered by the Covered +Patents. It does not apply to any other combinations that include a +Modification. + +D. The rights granted in Paragraphs A. and B. allow the Recipient to +sublicense those same rights. Such sublicense must be under the same +terms and conditions of this Agreement. + +3. OBLIGATIONS OF RECIPIENT + +A. Distribution or Redistribution of the Subject Software must be made +under this Agreement except for additions covered under paragraph 3H. + +1. Whenever a Recipient distributes or redistributes the Subject + Software, a copy of this Agreement must be included with each copy + of the Subject Software; and +2. If Recipient distributes or redistributes the Subject Software in + any form other than source code, Recipient must also make the + source code freely available, and must provide with each copy of + the Subject Software information on how to obtain the source code + in a reasonable manner on or through a medium customarily used for + software exchange. + +B. Each Recipient must ensure that the following copyright notice +appears prominently in the Subject Software: + +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. + + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov +*/ + +C. Each Contributor must characterize its alteration of the Subject +Software as a Modification and must identify itself as the originator +of its Modification in a manner that reasonably allows subsequent +Recipients to identify the originator of the Modification. In +fulfillment of these requirements, Contributor must include a file +(e.g., a change log file) that describes the alterations made and the +date of the alterations, identifies Contributor as originator of the +alterations, and consents to characterization of the alterations as a +Modification, for example, by including a statement that the +Modification is derived, directly or indirectly, from Original +Software provided by Government Agency. Once consent is granted, it +may not thereafter be revoked. + +D. A Contributor may add its own copyright notice to the Subject +Software. Once a copyright notice has been added to the Subject +Software, a Recipient may not remove it without the express permission +of the Contributor who added the notice. + +E. A Recipient may not make any representation in the Subject Software +or in any promotional, advertising or other material that may be +construed as an endorsement by Government Agency or by any prior +Recipient of any product or service provided by Recipient, or that may +seek to obtain commercial advantage by the fact of Government Agency's +or a prior Recipient's participation in this Agreement. + +F. In an effort to track usage and maintain accurate records of the +Subject Software, each Recipient, upon receipt of the Subject +Software, is requested to register with Government Agency by visiting +the following website: https://github.com/nasa/CryptoLib. Recipient's +name and personal information shall be used for statistical purposes +only. Once a Recipient makes a Modification available, it is requested +that the Recipient inform Government Agency at the web site provided +above how to access the Modification. + +G. Each Contributor represents that that its Modification is believed +to be Contributor's original creation and does not violate any +existing agreements, regulations, statutes or rules, and further that +Contributor has sufficient rights to grant the rights conveyed by this +Agreement. + +H. A Recipient may choose to offer, and to charge a fee for, warranty, +support, indemnity and/or liability obligations to one or more other +Recipients of the Subject Software. A Recipient may do so, however, +only on its own behalf and not on behalf of Government Agency or any +other Recipient. Such a Recipient must make it absolutely clear that +any such warranty, support, indemnity and/or liability obligation is +offered by that Recipient alone. Further, such Recipient agrees to +indemnify Government Agency and every other Recipient for any +liability incurred by them as a result of warranty, support, indemnity +and/or liability offered by such Recipient. + +I. A Recipient may create a Larger Work by combining Subject Software +with separate software not governed by the terms of this agreement and +distribute the Larger Work as a single product. In such case, the +Recipient must make sure Subject Software, or portions thereof, +included in the Larger Work is subject to this Agreement. + +J. Notwithstanding any provisions contained herein, Recipient is +hereby put on notice that export of any goods or technical data from +the United States may require some form of export license from the +U.S. Government. Failure to obtain necessary export licenses may +result in criminal liability under U.S. laws. Government Agency +neither represents that a license shall not be required nor that, if +required, it shall be issued. Nothing granted herein provides any +such export license. + +4. DISCLAIMER OF WARRANTIES AND LIABILITIES; WAIVER AND INDEMNIFICATION + +A. No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY +WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, +INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE +WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM +INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR +FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO +THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, +CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT +OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY +OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE. +FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES +REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, +AND DISTRIBUTES IT "AS IS." + +B. Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS +AGAINST THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND +SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF +THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, +EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM +PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT +SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED +STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY +PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE +REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL +TERMINATION OF THIS AGREEMENT. + + +5. GENERAL TERMS + +A. Termination: This Agreement and the rights granted hereunder will +terminate automatically if a Recipient fails to comply with these +terms and conditions, and fails to cure such noncompliance within +thirty (30) days of becoming aware of such noncompliance. Upon +termination, a Recipient agrees to immediately cease use and +distribution of the Subject Software. All sublicenses to the Subject +Software properly granted by the breaching Recipient shall survive any +such termination of this Agreement. + +B. Severability: If any provision of this Agreement is invalid or +unenforceable under applicable law, it shall not affect the validity +or enforceability of the remainder of the terms of this Agreement. + +C. Applicable Law: This Agreement shall be subject to United States +federal law only for all purposes, including, but not limited to, +determining the validity of this Agreement, the meaning of its +provisions and the rights, obligations and remedies of the parties. + +D. Entire Understanding: This Agreement constitutes the entire +understanding and agreement of the parties relating to release of the +Subject Software and may not be superseded, modified or amended except +by further written agreement duly executed by the parties. + +E. Binding Authority: By accepting and using the Subject Software +under this Agreement, a Recipient affirms its authority to bind the +Recipient to all terms and conditions of this Agreement and that that +Recipient hereby agrees to all terms and conditions herein. + +F. Point of Contact: Any Recipient contact with Government Agency is +to be directed to the designated representative as follows: + John.P.Lucas@nasa.gov \ No newline at end of file From 47e3e562a2af9a847b7af266f46e77917473cdab Mon Sep 17 00:00:00 2001 From: dccutrig <91623137+dccutrig@users.noreply.github.com> Date: Mon, 6 Dec 2021 17:24:24 -0500 Subject: [PATCH 049/184] Ut tc apply enctests (#21) * Rebasing to collab_main, Bug Fixes, additional tests * Added Dat files, and minor ut fixes - still faulting atm * UT/EVT refactoring * Fixing CMake & Refactoring - broken validation * Fixing another CMake * Bug Fixes, UT Fixed with new layout, TODO: Find FECF Issue * WIP * Updates to error codes and unit tests * WIP - AES-GCM test vector working * WIP - improving NIST KAT * WIP - Troubleshooting commit * Revert "WIP - Troubleshooting commit" This reverts commit e24dac9297982250c28c5ff22688a8880d95e62b. * Initial UT/Validation tests working * WIP UT modify ek_ring from hex string * Key Functionality * Test Cleanup * Adding more NIST AES-GCM 256 encryption test vectors * Added NIST authentication tag test * WIP: FECF Issues * Fixed IV_SIZE, FECF_CALC, Added DEC Tests, TODO: AUT Dec + Test, more FECF Fix, MAC Test, Remove Dat Files * Fixed Unit Tests, Cleaning up Tests, Renamed et_xxx to et_dt_xxx, TODO: Finish removing dat files, finish validation tests * renamed c/h files * WIP: AUTH Decryption * WIP: All Tests working but MAC Only AUTH Apply/Process * Encryption and decryption tests completed * Cleanup for CR 12/6 * Revert "Cleanup for CR 12/6" This reverts commit 50506d6bb67c29f3fd510f713b7a8ab623f23d7d. * Cleanup after CR for merge Co-authored-by: Robert Brown --- .gitignore | 1 + CMakeLists.txt | 5 + fsw/crypto_tests/CMakeLists.txt | 14 +- fsw/crypto_tests/data/raw_tc_sdls_ping.txt | 1 - .../data/raw_tc_sdls_ping_bad_scid.dat | 0 .../data/raw_tc_sdls_ping_bad_scid.txt | 1 - .../data/raw_tc_sdls_ping_bad_vcid.dat | 0 .../data/raw_tc_sdls_ping_bad_vcid.txt | 1 - fsw/crypto_util/CMakeLists.txt | 30 +- fsw/crypto_util/app/et_dt_validation.c | 999 ++++++++++++++++++ fsw/crypto_util/app/ut_tc_apply.c | 104 +- fsw/crypto_util/include/et_dt_validation.h | 34 + fsw/crypto_util/include/shared_util.h | 3 +- fsw/crypto_util/src/shared_util.c | 23 + fsw/public_inc/crypto_config.h | 4 +- fsw/public_inc/crypto_error.h | 11 + fsw/public_inc/crypto_structs.h | 2 +- fsw/public_inc/sadb_routine.h | 4 + fsw/src/crypto.c | 717 +++++++++++-- fsw/src/sadb_routine_inmemory.template.c | 115 +- python/encryption_test.py | 77 ++ 21 files changed, 1983 insertions(+), 163 deletions(-) delete mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping.txt delete mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat delete mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.txt delete mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat delete mode 100644 fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.txt create mode 100644 fsw/crypto_util/app/et_dt_validation.c create mode 100644 fsw/crypto_util/include/et_dt_validation.h create mode 100644 python/encryption_test.py diff --git a/.gitignore b/.gitignore index f881e3a8..bf2d36d9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ build venv *.dat .vscode +__pycache__ #CMake.gitignore CMakeLists.txt.user diff --git a/CMakeLists.txt b/CMakeLists.txt index 3db5d4e7..b3283955 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,12 +23,17 @@ set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") OPTION(DEBUG "Debug" OFF) # Disabled by default, enable with: -DDEBUG=ON OPTION(MYSQL "Mysql" OFF) # Disabled by default, enable with: -DMYSQL=ON +OPTION(ENCTEST "Encryption-Tests" OFF) # Disabled by default, enable with: -DENCTEST=ON IF(DEBUG) ADD_DEFINITIONS(-DDEBUG -DOCF_DEBUG -DFECF_DEBUG -DSA_DEBUG -DPDU_DEBUG -DCCSDS_DEBUG -DTC_DEBUG -DMAC_DEBUG -DTM_DEBUG) add_compile_options(-ggdb) ENDIF(DEBUG) +IF(ENCTEST) + ADD_DEFINITIONS(-DENCTEST) +ENDIF(ENCTEST) + if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) include(CTest) enable_testing() diff --git a/fsw/crypto_tests/CMakeLists.txt b/fsw/crypto_tests/CMakeLists.txt index b39ceb3d..50d609fb 100644 --- a/fsw/crypto_tests/CMakeLists.txt +++ b/fsw/crypto_tests/CMakeLists.txt @@ -16,10 +16,16 @@ set(PROJECT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -add_test(NAME Process_Security - COMMAND ${PROJECT_BINARY_DIR}/bin/process_security tc ${PROJECT_TEST_DIR}/data/tc4.1.dat - WORKING_DIRECTORY ${PROJECT_TEST_DIR}) +# add_test(NAME Process_Security +# COMMAND ${PROJECT_BINARY_DIR}/bin/process_security tc ${PROJECT_TEST_DIR}/data/tc4.1.dat +# WORKING_DIRECTORY ${PROJECT_TEST_DIR}) add_test(NAME UT_TC_APPLY COMMAND ${PROJECT_BINARY_DIR}/bin/ut_tc_apply - WORKING_DIRECTORY ${PROJECT_TEST_DIR}) \ No newline at end of file + WORKING_DIRECTORY ${PROJECT_TEST_DIR}) + +if(${ENCTEST}) + add_test(NAME ET_DT_VALIDATION + COMMAND ${PROJECT_BINARY_DIR}/bin/et_dt_validation + WORKING_DIRECTORY ${PROJECT_TEST_DIR}) +endif() diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping.txt b/fsw/crypto_tests/data/raw_tc_sdls_ping.txt deleted file mode 100644 index 896e7b31..00000000 --- a/fsw/crypto_tests/data/raw_tc_sdls_ping.txt +++ /dev/null @@ -1 +0,0 @@ -20030015001880d2c70008197f0b00310000b1fe3128 \ No newline at end of file diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat deleted file mode 100644 index e69de29b..00000000 diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.txt b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.txt deleted file mode 100644 index ba2549ba..00000000 --- a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.txt +++ /dev/null @@ -1 +0,0 @@ -20010015001880d2c70008197f0b00310000b1fe3128 \ No newline at end of file diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat deleted file mode 100644 index e69de29b..00000000 diff --git a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.txt b/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.txt deleted file mode 100644 index 64b27cb1..00000000 --- a/fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.txt +++ /dev/null @@ -1 +0,0 @@ -20032015001880d2c70008197f0b00310000b1fe3128 \ No newline at end of file diff --git a/fsw/crypto_util/CMakeLists.txt b/fsw/crypto_util/CMakeLists.txt index 2ae68dd0..0dfc1734 100644 --- a/fsw/crypto_util/CMakeLists.txt +++ b/fsw/crypto_util/CMakeLists.txt @@ -14,28 +14,40 @@ # NASA IV&V # jstar-development-team@mail.nasa.gov + + include_directories(include) -include_directories(../crypto/public_inc) +include_directories(../crypto/public_inc) + +if(ENCTEST) + find_package (Python3 REQUIRED COMPONENTS Interpreter Development) +endif(ENCTEST) aux_source_directory(src UTIL_SRC_FILES) -aux_source_directory(app APP_SRC_FILES) +aux_source_directory(app APP_SRC_FILES) file( GLOB SOURCE_FILES app/*.c ) foreach(SOURCE_PATH ${SOURCE_FILES}) - get_filename_component(EXECUTABLE_NAME ${SOURCE_PATH} NAME_WE) - add_executable(${EXECUTABLE_NAME} ${SOURCE_PATH}) + if((NOT ${ENCTEST}) AND ${EXECUTABLE_NAME} STREQUAL et_dt_validation) + continue() + else() + add_executable(${EXECUTABLE_NAME} ${SOURCE_PATH}) + target_sources(${EXECUTABLE_NAME} PRIVATE src/shared_util.c) + target_link_libraries(${EXECUTABLE_NAME} LINK_PUBLIC Crypto) + endif() - target_sources(${EXECUTABLE_NAME} PRIVATE src/shared_util.c) - target_link_libraries(${EXECUTABLE_NAME} LINK_PUBLIC Crypto) + if(${ENCTEST} AND ${EXECUTABLE_NAME} STREQUAL et_dt_validation) + target_link_libraries(${EXECUTABLE_NAME} PUBLIC ${Python3_LIBRARIES}) + target_include_directories(${EXECUTABLE_NAME} PUBLIC ${Python3_INCLUDE_DIRS}) + endif() add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_BINARY_DIR}/bin/${EXECUTABLE_NAME} COMMAND ${CMAKE_COMMAND} -E remove $ COMMENT "Created ${PROJECT_BINARY_DIR}/bin/${EXECUTABLE_NAME}" ) -endforeach(SOURCE_PATH ${SOURCE_FILES}) - -target_include_directories (Crypto PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +endforeach(SOURCE_PATH ${SOURCE_FILES}) +target_include_directories (Crypto PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/fsw/crypto_util/app/et_dt_validation.c b/fsw/crypto_util/app/et_dt_validation.c new file mode 100644 index 00000000..94686030 --- /dev/null +++ b/fsw/crypto_util/app/et_dt_validation.c @@ -0,0 +1,999 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +/* + * Unit Tests that macke use of TC_ApplySecurity function on the data. + */ + +#include "et_dt_validation.h" +#include "utest.h" +#include + +#include "sadb_routine.h" +#include "crypto_error.h" + + +// Setup for some Unit Tests using a Python Script to Verify validiy of frames +PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pArgs, *pClass, *pInstance; +int EndPython() +{ + Py_XDECREF(pInstance); + Py_XDECREF(pValue); + Py_XDECREF(pModule); + Py_XDECREF(pName); + Py_Finalize(); +} + +void python_auth_encryption(char* data, char* key, char* iv, char* header, char* bitmask, uint8** expected, long* expected_length) +{ + Py_Initialize(); + PyRun_SimpleString("import sys\nsys.path.append('../../python')"); + + pName = PyUnicode_FromString("encryption_test"); + pModule = PyImport_Import(pName); + if(pModule == NULL) + { + printf("ERROR, NO MODULE FOUND\n"); + EndPython(); + return; + } + + pDict = PyModule_GetDict(pModule); + pClass = PyDict_GetItemString(pDict, "Encryption"); + + if (PyCallable_Check(pClass)) + { + pInstance = PyObject_CallObject(pClass, NULL); + } + else + { + printf("ERROR, NO CLASS INSTANCE FOUND\n"); + EndPython(); + return; + } + + pValue = PyObject_CallMethod(pInstance, "encrypt", "sssss", data, key, iv, header, bitmask); + + pValue = PyObject_CallMethod(pInstance, "get_len", NULL); + long temp_length = PyLong_AsLong(pValue); + *expected_length = temp_length; + pValue = PyObject_CallMethod(pInstance, "get_results", NULL); + char* temp_expected = PyBytes_AsString(pValue); + *expected= (uint8*)malloc(sizeof(uint8) * (int)*expected_length); + memcpy(*expected, temp_expected, (int)*expected_length); + return; +} + +// Test by utilizing python cryptography library +UTEST(ET_VALIDATION, AUTH_ENCRYPTION_TEST) +{ + //Setup & Initialize CryptoLib + Crypto_Init(); + + uint8* expected = NULL; + long expected_length = 0; + + char *activate_sa4_h = "2003002000ff000100001880d2c9000e197f0b001b0004000400003040d95ea61a"; + char *enc_test_ping_h = "20030415001880d2ca0008197f0b0031000039c5a111"; + + uint8 *activate_sa4_b, *enc_test_ping_b = NULL; + int activate_sa4_len, enc_test_ping_len = 0; + + hex_conversion(activate_sa4_h, &activate_sa4_b, &activate_sa4_len); + hex_conversion(enc_test_ping_h, &enc_test_ping_b, &enc_test_ping_len); + + SecurityAssociation_t* test_association = NULL; + test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); + + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + int32 return_val = -1; + + TC_t *tc_sdls_processed_frame; + tc_sdls_processed_frame = malloc(sizeof(uint8) * TC_SIZE); + memset(tc_sdls_processed_frame, 0, (sizeof(uint8) * TC_SIZE)); + + // Ensure that Process Security can activate SA 4 + Crypto_TC_ProcessSecurity(activate_sa4_b, &activate_sa4_len, tc_sdls_processed_frame); + + // Expose SA 1 for testing + expose_sadb_get_sa_from_spi(1,&test_association); + + // Deactive SA 1 + test_association->sa_state = SA_NONE; + + // Expose SA 4 for testing + expose_sadb_get_sa_from_spi(4, &test_association); + test_association->arc_len = 0; + test_association->gvcid_tc_blk.vcid=1; + test_association->iv[11] = 1; + test_association->ast = 1; + test_association->est = 1; + Crypto_TC_ApplySecurity(enc_test_ping_b, enc_test_ping_len, &ptr_enc_frame, &enc_frame_len); + + // Get Truth Baseline + python_auth_encryption("1880d2ca0008197f0b0031000039c5", "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210", "000000000000000000000001", "2003043400FF0004", "00", &expected, &expected_length); + + for(int i = 0; i < expected_length; i++) + { + //printf("[%d]: %02x -> %02x \n", i, expected[i], ptr_enc_frame[i]); + ASSERT_EQ(expected[i], ptr_enc_frame[i]); + } + + free(activate_sa4_b); + free(enc_test_ping_b); + free(ptr_enc_frame); + free(expected); + free(tc_sdls_processed_frame); + EndPython(); +} + +UTEST(DT_VALIDATION, AUTH_DECRYPTION_TEST) +{ + //Setup & Initialize CryptoLib + Crypto_Init(); + + char *activate_sa4_h = "2003002000ff000100001880d2c9000e197f0b001b0004000400003040d95ea61a"; + char *dec_test_ping_h = "2003043400FF00040000000000000000000000017E1D8EEA8D45CEBA17888E0CDCD747DC78E5F372F997F2A63AA5DFC168395DC987"; + char *enc_test_ping_h = "1880d2ca0008197f0b0031000039c5"; + + uint8 *activate_sa4_b, *dec_test_ping_b, *enc_test_ping_b = NULL; + int activate_sa4_len, dec_test_ping_len, enc_test_ping_len = 0; + + hex_conversion(activate_sa4_h, &activate_sa4_b, &activate_sa4_len); + hex_conversion(dec_test_ping_h, &dec_test_ping_b, &dec_test_ping_len); + hex_conversion(enc_test_ping_h, &enc_test_ping_b, &enc_test_ping_len); + + SecurityAssociation_t* test_association = NULL; + test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); + + int32 return_val = -1; + + TC_t *tc_sdls_processed_frame; + tc_sdls_processed_frame = malloc(sizeof(uint8) * TC_SIZE); + memset(tc_sdls_processed_frame, 0, (sizeof(uint8) * TC_SIZE)); + + // Ensure that Process Security can activate SA 4 + Crypto_TC_ProcessSecurity(activate_sa4_b, &activate_sa4_len, tc_sdls_processed_frame); + + // Expose SA 1 for testing + expose_sadb_get_sa_from_spi(1,&test_association); + + // Deactive SA 1 + test_association->sa_state = SA_NONE; + + // Expose SA 4 for testing + expose_sadb_get_sa_from_spi(4, &test_association); + test_association->arc_len = 0; + test_association->gvcid_tc_blk.vcid=1; + test_association->iv[11] = 1; + test_association->ast = 1; + test_association->est = 1; + + Crypto_TC_ProcessSecurity(dec_test_ping_b, &dec_test_ping_len, tc_sdls_processed_frame); + + for(int i = 0; i < tc_sdls_processed_frame->tc_pdu_len; i++) + { + ASSERT_EQ(enc_test_ping_b[i], tc_sdls_processed_frame->tc_pdu[i]); + } + + free(activate_sa4_b); + free(dec_test_ping_b); + free(tc_sdls_processed_frame); + EndPython(); +} + +// AES-GCM 256 Test Vectors +// Reference: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/gcmtestvectors.zip +UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) +{ + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + // Setup & Initialize CryptoLib + Crypto_Init(); + // NIST supplied vectors + // NOTE: Added Transfer Frame header to the plaintext + char *buffer_nist_key_h = "ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8"; + char *buffer_nist_pt_h = "2003001100722ee47da4b77424733546c2d400c4e51069"; + char *buffer_nist_iv_h = "b6ac8e4963f49207ffd6374c"; + char *buffer_nist_ct_h = "1224dfefb72a20d49e09256908874979"; + uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; + int buffer_nist_pt_len, buffer_nist_iv_len, buffer_nist_ct_len, buffer_nist_key_len = 0; + + // Expose/setup SAs for testing + SecurityAssociation_t* test_association = NULL; + test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); + // Deactivate SA 1 + expose_sadb_get_sa_from_spi(1,&test_association); + test_association->sa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_ct_h, &buffer_nist_ct_b, &buffer_nist_ct_len); + + Crypto_TC_ApplySecurity(buffer_nist_pt_b, buffer_nist_pt_len, &ptr_enc_frame, &enc_frame_len); + // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) + // Calc payload index: total length - pt length + uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + for (int i=0; isa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv, buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input encryptedtext + hex_conversion(buffer_nist_et_h, &buffer_nist_et_b, &buffer_nist_et_len); + + Crypto_TC_ProcessSecurity(buffer_nist_et_b, &buffer_nist_et_len, tc_nist_processed_frame); + + for(int i = 0; i < tc_nist_processed_frame->tc_pdu_len; i++) + { + ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); + } + + free(ptr_enc_frame); + free(buffer_nist_pt_b); + free(buffer_nist_iv_b); + free(buffer_nist_et_b); + free(buffer_nist_key_b); +} + +UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_1) +{ + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + // Setup & Initialize CryptoLib + Crypto_Init(); + // NIST supplied vectors + // NOTE: Added Transfer Frame header to the plaintext + char *buffer_nist_key_h = "e9ccd6eef27f740d1d5c70b187734e11e76a8ac0ad1702ff02180c5c1c9e5399"; + char *buffer_nist_pt_h = "2003001100419635e6e12b257a8ecae411f94480ffa02a"; + char *buffer_nist_iv_h = "1af2613c4184dbd101fcedce"; + char *buffer_nist_ct_h = "9cd21f414f1f54d5f6f58b1f2f77e5b6"; + uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; + int buffer_nist_pt_len, buffer_nist_iv_len, buffer_nist_ct_len, buffer_nist_key_len = 0; + + // Expose/setup SAs for testing + SecurityAssociation_t* test_association = NULL; + test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); + // Deactivate SA 1 + expose_sadb_get_sa_from_spi(1,&test_association); + test_association->sa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_ct_h, &buffer_nist_ct_b, &buffer_nist_ct_len); + + Crypto_TC_ApplySecurity(buffer_nist_pt_b, buffer_nist_pt_len, &ptr_enc_frame, &enc_frame_len); + // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) + // Calc payload index: total length - pt length + uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + for (int i=0; isa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_et_h, &buffer_nist_et_b, &buffer_nist_et_len); + + Crypto_TC_ProcessSecurity(buffer_nist_et_b, &buffer_nist_et_len, tc_nist_processed_frame); + + for(int i = 0; i < tc_nist_processed_frame->tc_pdu_len; i++) + { + ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); + } + + free(ptr_enc_frame); + free(buffer_nist_pt_b); + free(buffer_nist_iv_b); + free(buffer_nist_et_b); + free(buffer_nist_key_b); +} + +UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_2) +{ + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + // Setup & Initialize CryptoLib + Crypto_Init(); + // NIST supplied vectors + // NOTE: Added Transfer Frame header to the plaintext + char *buffer_nist_key_h = "7ecc9dcb3d5b413cadc3af7b7812758bd869295f8aaf611ba9935de76bd87013"; + char *buffer_nist_pt_h = "200300110073d4d7984ce422ac983797c0526ac6f9ba60"; + char *buffer_nist_iv_h = "6805be41e983717bf6781052"; + char *buffer_nist_ct_h = "487211dd440f4d09d00bc5c3158a822c"; + uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; + int buffer_nist_pt_len, buffer_nist_iv_len, buffer_nist_ct_len, buffer_nist_key_len = 0; + + // Expose/setup SAs for testing + SecurityAssociation_t* test_association = NULL; + test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); + // Deactivate SA 1 + expose_sadb_get_sa_from_spi(1,&test_association); + test_association->sa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_ct_h, &buffer_nist_ct_b, &buffer_nist_ct_len); + + Crypto_TC_ApplySecurity(buffer_nist_pt_b, buffer_nist_pt_len, &ptr_enc_frame, &enc_frame_len); + // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) + // Calc payload index: total length - pt length + uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + for (int i=0; isa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_et_h, &buffer_nist_et_b, &buffer_nist_et_len); + + Crypto_TC_ProcessSecurity(buffer_nist_et_b, &buffer_nist_et_len, tc_nist_processed_frame); + + for(int i = 0; i < tc_nist_processed_frame->tc_pdu_len; i++) + { + ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); + } + + free(ptr_enc_frame); + free(buffer_nist_pt_b); + free(buffer_nist_iv_b); + free(buffer_nist_et_b); + free(buffer_nist_key_b); +} + +UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_3) +{ + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + // Setup & Initialize CryptoLib + Crypto_Init(); + // NIST supplied vectors + // NOTE: Added Transfer Frame header to the plaintext + char *buffer_nist_key_h = "a881373e248615e3d6576f5a5fb68883515ae72d6a2938e3a6f0b8dcb639c9c0"; + char *buffer_nist_pt_h = "200300110007d1dc9930e710b1ebe533c81f671101ba60"; + char *buffer_nist_iv_h = "f0b744f157087df4e41818a9"; + char *buffer_nist_ct_h = "b65a2878b9dddbd4a0204dae6a6a6fc0"; + uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; + int buffer_nist_pt_len, buffer_nist_iv_len, buffer_nist_ct_len, buffer_nist_key_len = 0; + + // Expose/setup SAs for testing + SecurityAssociation_t* test_association = NULL; + test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); + // Deactivate SA 1 + expose_sadb_get_sa_from_spi(1,&test_association); + test_association->sa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_ct_h, &buffer_nist_ct_b, &buffer_nist_ct_len); + + Crypto_TC_ApplySecurity(buffer_nist_pt_b, buffer_nist_pt_len, &ptr_enc_frame, &enc_frame_len); + // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) + // Calc payload index: total length - pt length + uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + for (int i=0; isa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_et_h, &buffer_nist_et_b, &buffer_nist_et_len); + + Crypto_TC_ProcessSecurity(buffer_nist_et_b, &buffer_nist_et_len, tc_nist_processed_frame); + + for(int i = 0; i < tc_nist_processed_frame->tc_pdu_len; i++) + { + ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); + } + + free(ptr_enc_frame); + free(buffer_nist_pt_b); + free(buffer_nist_iv_b); + free(buffer_nist_et_b); + free(buffer_nist_key_b); +} + +UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_4) +{ + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + // Setup & Initialize CryptoLib + Crypto_Init(); + // NIST supplied vectors + // NOTE: Added Transfer Frame header to the plaintext + char *buffer_nist_key_h = "84c90349539c2a7989cb24dfae5e4182382ae94ba717d385977017f74f0d87d6"; + char *buffer_nist_pt_h = "200300110031c4e1d0ccece6b7a999bfc31f38559ab87b"; + char *buffer_nist_iv_h = "eeddeaf4355c826dfd153393"; + char *buffer_nist_ct_h = "5c6cfbdd06c19445ecf500c21aeca173"; + uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; + int buffer_nist_pt_len, buffer_nist_iv_len, buffer_nist_ct_len, buffer_nist_key_len = 0; + + // Expose/setup SAs for testing + SecurityAssociation_t* test_association = NULL; + test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); + // Deactivate SA 1 + expose_sadb_get_sa_from_spi(1,&test_association); + test_association->sa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_ct_h, &buffer_nist_ct_b, &buffer_nist_ct_len); + + Crypto_TC_ApplySecurity(buffer_nist_pt_b, buffer_nist_pt_len, &ptr_enc_frame, &enc_frame_len); + // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) + // Calc payload index: total length - pt length + uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + for (int i=0; isa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->arc_len = 0; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input ciphertext + hex_conversion(buffer_nist_et_h, &buffer_nist_et_b, &buffer_nist_et_len); + + Crypto_TC_ProcessSecurity(buffer_nist_et_b, &buffer_nist_et_len, tc_nist_processed_frame); + + for(int i = 0; i < tc_nist_processed_frame->tc_pdu_len; i++) + { + ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); + } + + free(ptr_enc_frame); + free(buffer_nist_pt_b); + free(buffer_nist_iv_b); + free(buffer_nist_et_b); + free(buffer_nist_key_b); +} + +// Spot check of MAC tags assuming no plaintext payload +// Accomplished by a multi-step process: +// 1) Ensure a valid implementation - Utilize Cyberchef's AES Encrypt to re-create a NIST test vector with AAD +// 2) Generate Truth data - Use same CyberChef settings on a created TF +// 3) Validate Cryptolib output with CyberChef output +// Reference 1: https://gchq.github.io/CyberChef/#recipe=AES_Encrypt(%7B'option':'Hex','string':''%7D,%7B'option':'Hex','string':''%7D,'GCM','Hex','Hex',%7B'option':'Hex','string':''%7D) +// Reference 2: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/gcmtestvectors.zip + +// Bit Mask of zeros +// Bit-mask of zeros in this test for a total length of: +// Header (5) + Segment Hdr (1) + SPI (2) + IV (12) +// This means zero input to the MAC, which precedes the TF FECF +UTEST(NIST_ENC_MAC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) +{ + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + // Setup & Initialize CryptoLib + Crypto_Init(); + // NIST supplied vectors + // NOTE: Added Transfer Frame header to the plaintext + char *buffer_nist_key_h = "78dc4e0aaf52d935c3c01eea57428f00ca1fd475f5da86a49c8dd73d68c8e223"; + char *buffer_nist_pt_h = "200300040028C2"; // Empty Transfer frame + char *buffer_nist_iv_h = "d79cf22d504cc793c3fb6c8a"; + char *buffer_nist_aad_h = "b96baa8c1c75a671bfb2d08d06be5f36"; // Zeroed out by abm + char *buffer_cyber_chef_mac_h = "79238ca36970658073f5d59d7aa874ef"; + uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_key_b, *buffer_nist_aad_b, *buffer_cyber_chef_mac_b = NULL; + int buffer_nist_pt_len, buffer_nist_iv_len, buffer_nist_key_len, buffer_nist_aad_len, buffer_cyber_chef_mac_len = 0; + + // Expose/setup SAs for testing + SecurityAssociation_t* test_association = NULL; + test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); + // Deactivate SA 1 + expose_sadb_get_sa_from_spi(1,&test_association); + test_association->sa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->ast = 1; + test_association->est = 0; + test_association->arc_len = 0; + test_association->shivf_len = 12; + test_association->abm_len = 20; + test_association->stmacf_len = 16; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input aad + hex_conversion(buffer_nist_aad_h, &buffer_nist_aad_b, &buffer_nist_aad_len); + // Convert input mac + hex_conversion(buffer_cyber_chef_mac_h, &buffer_cyber_chef_mac_b, &buffer_cyber_chef_mac_len); + + Crypto_TC_ApplySecurity(buffer_nist_pt_b, buffer_nist_pt_len, &ptr_enc_frame, &enc_frame_len); + // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) + // Calc payload index: total length - pt length + uint16 enc_data_idx = enc_frame_len - buffer_cyber_chef_mac_len - 2; + for (int i=0; isa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->ast = 1; + test_association->est = 0; + test_association->arc_len = 0; + test_association->shivf_len = 12; + test_association->abm_len = 20; + memset(test_association->abm, 0xFF, (test_association->abm_len*sizeof(unsigned char))); // Bitmask + test_association->stmacf_len = 16; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(&test_association->iv[0], buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input mac + hex_conversion(buffer_cyber_chef_mac_h, &buffer_cyber_chef_mac_b, &buffer_cyber_chef_mac_len); + + Crypto_TC_ApplySecurity(buffer_nist_pt_b, buffer_nist_pt_len, &ptr_enc_frame, &enc_frame_len); + + // Note: For comparison, primarily interested in the MAC + // Calc payload index: total length - pt length + uint16 enc_data_idx = enc_frame_len - buffer_cyber_chef_mac_len - 2; + for (int i=0; isa_state = SA_NONE; + // Activate SA 9 + expose_sadb_get_sa_from_spi(9, &test_association); + test_association->ast = 1; + test_association->est = 0; + test_association->arc_len = 0; + test_association->abm_len = 20; + memset(test_association->abm, 0xFF, (test_association->abm_len*sizeof(unsigned char))); + test_association->shivf_len = 12; + test_association->stmacf_len = 16; + test_association->sa_state = SA_OPERATIONAL; + + // Insert key into keyring of SA 9 + hex_conversion(buffer_nist_key_h, &buffer_nist_key_b, &buffer_nist_key_len); + memcpy(ek_ring[test_association->ekid].value, buffer_nist_key_b, buffer_nist_key_len); + + // Convert input plaintext + // TODO: Account for length of header and FECF (5+2) + hex_conversion(buffer_nist_pt_h, &buffer_nist_pt_b, &buffer_nist_pt_len); + // Convert/Set input IV + hex_conversion(buffer_nist_iv_h, &buffer_nist_iv_b, &buffer_nist_iv_len); + memcpy(test_association->iv, buffer_nist_iv_b, buffer_nist_iv_len); + // Convert input mac + hex_conversion(buffer_cyber_chef_mac_h, &buffer_cyber_chef_mac_b, &buffer_cyber_chef_mac_len); + // Convert mac frame + hex_conversion(buffer_nist_mac_frame_h, &buffer_nist_mac_frame_b, &buffer_nist_mac_frame_len); + + Crypto_TC_ProcessSecurity(buffer_nist_mac_frame_b, &buffer_nist_mac_frame_len, tc_nist_processed_frame); + + // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) + // Calc payload index: total length - pt length + #ifdef DEBUG + printf("Expected MAC: "); + for (int i=0; itc_pdu_len; i++) + { + printf("%02x ", buffer_cyber_chef_mac_b[i]); + } + printf("\nReceived MAC: "); + for (int i=0; itc_pdu_len; i++) + { + printf("%02x ", tc_nist_processed_frame->tc_sec_trailer.mac[i]); + } + printf("\n"); + #endif + + // Verify the MAC + for (int i=0; i < tc_nist_processed_frame->tc_pdu_len; i++) + { + ASSERT_EQ(tc_nist_processed_frame->tc_sec_trailer.mac[i], buffer_cyber_chef_mac_b[i]); + } + for (int i=0; i < tc_nist_processed_frame->tc_pdu_len; i++) + // Verify the PDU Data is present and not stomped + { + ASSERT_EQ(tc_nist_processed_frame->tc_pdu[i], buffer_nist_pt_b[i]); + } + free(buffer_nist_iv_b); + free(buffer_nist_key_b); + free(buffer_cyber_chef_mac_b); + free(buffer_nist_mac_frame_b); + free(buffer_nist_cp_b); +} + +UTEST_MAIN(); diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c index 0794dc2c..f0f9d627 100644 --- a/fsw/crypto_util/app/ut_tc_apply.c +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -20,6 +20,8 @@ */ #include "ut_tc_apply.h" #include "utest.h" +#include "crypto.h" +#include "crypto_error.h" // TODO: Should this be set up with a set of tests, or continue to Crypto_Init() each time. For now I think the current setup is the best path. @@ -32,85 +34,83 @@ UTEST(TC_APPLY_SECURITY, NO_CRYPTO_INIT) { // No Crypto_Init(); long buffer_size = 0; - char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping.dat", &buffer_size); - uint16 buffer_size_i = (uint16) buffer_size; + char *raw_tc_sdls_ping_h = "20030015001880d2c70008197f0b00310000b1fe3128"; + uint8 *raw_tc_sdls_ping_b = NULL; + int raw_tc_sdls_ping_len = 0; + + hex_conversion(raw_tc_sdls_ping_h, &raw_tc_sdls_ping_b, &raw_tc_sdls_ping_len); uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; - int32 return_val = -1; - - return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); + int32 return_val = CRYPTO_LIB_ERROR; - ASSERT_EQ(-1, return_val); - free(buffer); - free(ptr_enc_frame); + return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(CRYPTO_LIB_ERR_NO_INIT, return_val); + free(raw_tc_sdls_ping_b); } -// Nominal Test. This should read a raw_tc_sdls_ping.dat file, continue down the "happy path", and return OS_SUCCESS +// Nominal Test. This should read a raw_tc_sdls_ping.dat file, continue down the "happy path", and return CRYPTO_LIB_SUCCESS UTEST(TC_APPLY_SECURITY, HAPPY_PATH) { //Setup & Initialize CryptoLib Crypto_Init(); - long buffer_size =0; - char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping.dat", &buffer_size); - uint16 buffer_size_i = (uint16) buffer_size; + char *raw_tc_sdls_ping_h = "20030015001880d2c70008197f0b00310000b1fe3128"; + uint8 *raw_tc_sdls_ping_b = NULL; + int raw_tc_sdls_ping_len = 0; + + hex_conversion(raw_tc_sdls_ping_h, &raw_tc_sdls_ping_b, &raw_tc_sdls_ping_len); uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; - int32 return_val = -1; + int32 return_val = CRYPTO_LIB_ERROR; - return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(0, return_val); - free(buffer); + return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val); + free(raw_tc_sdls_ping_b); free(ptr_enc_frame); - //Need Crypto_ReInit()?; } -// Bad Space Craft ID. This should pass the flawed .dat file, and return OS_ERROR +// Bad Space Craft ID. This should pass the flawed .dat file, and return CRYPTO_LIB_ERR_INVALID_SCID UTEST(TC_APPLY_SECURITY, BAD_SPACE_CRAFT_ID) { //Setup & Initialize CryptoLib Crypto_Init(); - long buffer_size = 0; - char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping_bad_scid.dat", &buffer_size); - uint16 buffer_size_i = (uint16) buffer_size; + char *raw_tc_sdls_ping_bad_scid_h = "20010015001880d2c70008197f0b00310000b1fe3128"; + uint8 *raw_tc_sdls_ping_bad_scid_b = NULL; + int raw_tc_sdls_ping_bad_scid_len = 0; + + hex_conversion(raw_tc_sdls_ping_bad_scid_h, &raw_tc_sdls_ping_bad_scid_b, &raw_tc_sdls_ping_bad_scid_len); uint8 *ptr_enc_frame = NULL; - uint16 enc_frame_len = 0; - int32 return_val = -1; + uint16 enc_frame_len = 0; - return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(-1, return_val); - free(buffer); - free(ptr_enc_frame); - //Need Crypto_ReInit(); + uint32 return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_bad_scid_b, raw_tc_sdls_ping_bad_scid_len, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(CRYPTO_LIB_ERR_INVALID_SCID, return_val); + free(raw_tc_sdls_ping_bad_scid_b); + free(ptr_enc_frame); } -// TODO: This does not report the correct error. It returns the correctly, but complains of an incorrect SCID -// This should return OS_ERROR UTEST(TC_APPLY_SECURITY, BAD_VIRTUAL_CHANNEL_ID) { //Setup & Initialize CryptoLib Crypto_Init(); - long buffer_size = 0; - char *buffer = c_read_file("../../fsw/crypto_tests/data/raw_tc_sdls_ping_bad_vcid.dat", &buffer_size); - uint16 buffer_size_i = (uint16) buffer_size; + char *raw_tc_sdls_ping_bad_vcid_h = "20032015001880d2c70008197f0b00310000b1fe3128"; + uint8 *raw_tc_sdls_ping_bad_vcid_b = NULL; + int raw_tc_sdls_ping_bad_vcid_len = 0; + + hex_conversion(raw_tc_sdls_ping_bad_vcid_h, &raw_tc_sdls_ping_bad_vcid_b, &raw_tc_sdls_ping_bad_vcid_len); uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; - int32 return_val = -1; + int32 return_val = CRYPTO_LIB_ERROR; - return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(0, return_val); //TODO: Having this fail until it is fixed in code. - free(buffer); - free(ptr_enc_frame); - //Need Crypto_ReInit(); + return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_bad_vcid_b, raw_tc_sdls_ping_bad_vcid_len, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(CRYPTO_LIB_ERR_INVALID_VCID, return_val); + free(raw_tc_sdls_ping_bad_vcid_b); + free(ptr_enc_frame); } -// Encryption Test HERE - - // This test should test how to handle a null buffer being passed into the ApplySecurity Function. // Currently this functionality isn't handled properly, and casues a seg-fault. // TODO: We need to determine how this would return, as it will help in other test cases. @@ -129,31 +129,13 @@ UTEST(TC_APPLY_SECURITY, NULL_BUFFER) return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(-1, return_val); - free(buffer); - free(ptr_enc_frame); - //Need Crypto_ReInit(); + ASSERT_EQ(CRYPTO_LIB_ERR_NULL_BUFFER, return_val); } //TODO: /* What should be returned if something goes wrong with Control Command Flag? Should a NULL pointer be returned....The original pointer? We need to decide on this functionality and write a test for this - - We should probably have more error codes than OS_SUCCESS and OS_ERROR - - Some way to modify and test the SA? - - Authentication Tests - When Ready / Complete? - - Encryption Tests - When Ready / Complete? - - Authenticated Encryption Tests - When Ready / Complete */ - - UTEST_MAIN(); diff --git a/fsw/crypto_util/include/et_dt_validation.h b/fsw/crypto_util/include/et_dt_validation.h new file mode 100644 index 00000000..358a1562 --- /dev/null +++ b/fsw/crypto_util/include/et_dt_validation.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2009 - 2017 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any, kind either express, implied, or statutory, including, but not + limited to, any warranty that the software will conform to, specifications any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation. Whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder + + ITC Team + NASA IV&V + ivv-itc@lists.nasa.gov +*/ + +#ifndef CRYPTOLIB_ET_DT_VALIDATION_H +#define CRYPTOLIB_ET_DT_VALIDATION_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "crypto.h" +#include "shared_util.h" +#include + +#ifdef __cplusplus +} /* Close scope of 'extern "C"' declaration which encloses file. */ +#endif + +#endif //CRYPTOLIB_ET_DT_VALIDATION_H \ No newline at end of file diff --git a/fsw/crypto_util/include/shared_util.h b/fsw/crypto_util/include/shared_util.h index 5fb0bfb0..9137f55e 100644 --- a/fsw/crypto_util/include/shared_util.h +++ b/fsw/crypto_util/include/shared_util.h @@ -27,7 +27,6 @@ extern "C" { #include #include - #include "osapi_minimum.h" char * c_read_file(const char * f_name, long * f_size); @@ -35,6 +34,8 @@ char * c_read_file(const char * f_name, long * f_size); void debug_printf(const char* format, ...); void debug_hexprintf(const char* bin_data,int size_bin_data); +void hex_conversion(char *buffer_h, uint8 **buffer_b, int *buffer_b_length); +int convert_hexstring_to_byte_array(char* source_str, uint8* dest_buffer); #ifdef __cplusplus } /* Close scope of 'extern "C"' declaration which encloses file. */ diff --git a/fsw/crypto_util/src/shared_util.c b/fsw/crypto_util/src/shared_util.c index 9b4358c2..ac4da7c4 100644 --- a/fsw/crypto_util/src/shared_util.c +++ b/fsw/crypto_util/src/shared_util.c @@ -57,6 +57,29 @@ char * c_read_file(const char * f_name, long * f_size) { } +int convert_hexstring_to_byte_array(char* source_str, uint8* dest_buffer) +{ + char *line = source_str; + char *data = line; + int offset; + int read_byte; + int data_len = 0; + + while (sscanf(data, " %02x%n", &read_byte, &offset) == 1) + { + dest_buffer[data_len++] = read_byte; + data += offset; + } + return data_len; +} + +void hex_conversion(char *buffer_h, uint8 **buffer_b, int *buffer_b_length) +{ + // Convert input plaintext + *buffer_b = (uint8*)malloc((strlen(buffer_h) / 2) * sizeof(uint8)); + *buffer_b_length = convert_hexstring_to_byte_array(buffer_h, *buffer_b); +} + #ifdef DEBUG void debug_printf(const char *format, ...) { diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index 57332ec1..6220ff9d 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -106,13 +106,13 @@ #define NUM_KEYS 256 #define DISABLED 0 #define ENABLED 1 - #define IV_SIZE 12 /* TM IV size bytes */ + #define IV_SIZE 16 /* TM IV size bytes */ #define IV_SIZE_TC 4 /* TC IV size bytes */ #define OCF_SIZE 4 #define MAC_SIZE 16 /* bytes */ #define FECF_SIZE 2 #define ECS_SIZE 4 /* bytes */ - #define ABM_SIZE 20 /* bytes */ + #define ABM_SIZE 1024 //20 /* bytes */ #define ARC_SIZE 20 /* total messages */ #define ARCW_SIZE 1 /* bytes */ #define SN_SIZE 0 diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h index a70190bd..06097c1e 100644 --- a/fsw/public_inc/crypto_error.h +++ b/fsw/public_inc/crypto_error.h @@ -19,5 +19,16 @@ #include "sadb_mariadb_error.h" +#define CRYPTO_LIB_SUCCESS (0) +#define CRYPTO_LIB_ERROR (-1) +#define CRYPTO_LIB_ERR_NO_INIT (-2) +#define CRYPTO_LIB_ERR_INVALID_TFVN (-3) +#define CRYPTO_LIB_ERR_INVALID_SCID (-4) +#define CRYPTO_LIB_ERR_INVALID_VCID (-5) +#define CRYPTO_LIB_ERR_INVALID_MAPID (-6) +#define CRYPTO_LIB_ERR_INVALID_CC_FLAG (-7) +#define CRYPTO_LIB_ERR_NO_OPERATIONAL_SA (-8) +#define CRYPTO_LIB_ERR_NULL_BUFFER (-9) +#define CRYPTO_LIB_ERR_UT_BYTE_MISMATCH (-10) #endif //_crypto_error_h_ diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index 4208d0e2..138bd5ff 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -69,7 +69,7 @@ typedef struct uint8 ecs_len :8; // Encryption Cipher Suite Length uint8 ecs[ECS_SIZE]; // Encryption Cipher Suite (algorithm / mode ID) uint8 iv_len :8; // Initialization Vector Length - uint8 iv[IV_SIZE]; // Initialization Vector + uint8 iv[16]; // Initialization Vector uint8 acs_len :8; // Authentication Cipher Suite Length uint8 acs :8; // Authentication Cipher Suite (algorithm / mode ID) uint16 abm_len :16; // Authentication Bit Mask Length diff --git a/fsw/public_inc/sadb_routine.h b/fsw/public_inc/sadb_routine.h index 838ecb04..528f5b99 100644 --- a/fsw/public_inc/sadb_routine.h +++ b/fsw/public_inc/sadb_routine.h @@ -47,6 +47,10 @@ typedef struct { } SadbRoutineStruct, *SadbRoutine; +#ifdef ENCTEST +int32 expose_sadb_get_sa_from_spi(uint16, SecurityAssociation_t**); +#endif + SadbRoutine get_sadb_routine_mariadb(void); SadbRoutine get_sadb_routine_inmemory(void); SadbRoutine init_parse_sadb_routine(char *); diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 47fc65cf..64bde762 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -23,13 +23,14 @@ #include "crypto.h" #include "sadb_routine.h" -#include "itc_aes128.h" -#include "itc_gcm128.h" +// #include "itc_aes128.h" +// #include "itc_gcm128.h" #include "crypto_structs.h" #include "crypto_print.h" #include "crypto_config.h" #include "crypto_events.h" +#include "crypto_error.h" @@ -49,7 +50,7 @@ static SadbRoutine sadb_routine = NULL; ** Static Prototypes */ // Assisting Functions -static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame); +static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame, SecurityAssociation_t *sa_ptr); static int32 Crypto_Get_tmLength(int len); static void Crypto_TM_updatePDU(char* ingest, int len_ingest); static void Crypto_TM_updateOCF(void); @@ -526,6 +527,77 @@ static void Crypto_Local_Config(void) ek_ring[134].value[30] = 0x32; ek_ring[134].value[31] = 0x10; ek_ring[134].key_state = KEY_DEACTIVATED; + + // 135 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE + ek_ring[135].value[0] = 0x00; + ek_ring[135].value[1] = 0x00; + ek_ring[135].value[2] = 0x00; + ek_ring[135].value[3] = 0x00; + ek_ring[135].value[4] = 0x00; + ek_ring[135].value[5] = 0x00; + ek_ring[135].value[6] = 0x00; + ek_ring[135].value[7] = 0x00; + ek_ring[135].value[8] = 0x00; + ek_ring[135].value[9] = 0x00; + ek_ring[135].value[10] = 0x00; + ek_ring[135].value[11] = 0x00; + ek_ring[135].value[12] = 0x00; + ek_ring[135].value[13] = 0x00; + ek_ring[135].value[14] = 0x00; + ek_ring[135].value[15] = 0x00; + ek_ring[135].value[16] = 0x00; + ek_ring[135].value[17] = 0x00; + ek_ring[135].value[18] = 0x00; + ek_ring[135].value[19] = 0x00; + ek_ring[135].value[20] = 0x00; + ek_ring[135].value[21] = 0x00; + ek_ring[135].value[22] = 0x00; + ek_ring[135].value[23] = 0x00; + ek_ring[135].value[24] = 0x00; + ek_ring[135].value[25] = 0x00; + ek_ring[135].value[26] = 0x00; + ek_ring[135].value[27] = 0x00; + ek_ring[135].value[28] = 0x00; + ek_ring[135].value[29] = 0x00; + ek_ring[135].value[30] = 0x00; + ek_ring[135].value[31] = 0x00; + ek_ring[135].key_state = KEY_DEACTIVATED; + + // 136 - ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8 + // Reference: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/gcmtestvectors.zip + ek_ring[136].value[0] = 0xff; + ek_ring[136].value[1] = 0x9f; + ek_ring[136].value[2] = 0x92; + ek_ring[136].value[3] = 0x84; + ek_ring[136].value[4] = 0xcf; + ek_ring[136].value[5] = 0x59; + ek_ring[136].value[6] = 0x9e; + ek_ring[136].value[7] = 0xac; + ek_ring[136].value[8] = 0x3b; + ek_ring[136].value[9] = 0x11; + ek_ring[136].value[10] = 0x99; + ek_ring[136].value[11] = 0x05; + ek_ring[136].value[12] = 0xa7; + ek_ring[136].value[13] = 0xd1; + ek_ring[136].value[14] = 0x88; + ek_ring[136].value[15] = 0x51; + ek_ring[136].value[16] = 0xe7; + ek_ring[136].value[17] = 0xe3; + ek_ring[136].value[18] = 0x74; + ek_ring[136].value[19] = 0xcf; + ek_ring[136].value[20] = 0x63; + ek_ring[136].value[21] = 0xae; + ek_ring[136].value[22] = 0xa0; + ek_ring[136].value[23] = 0x43; + ek_ring[136].value[24] = 0x58; + ek_ring[136].value[25] = 0x58; + ek_ring[136].value[26] = 0x6b; + ek_ring[136].value[27] = 0x0f; + ek_ring[136].value[28] = 0x75; + ek_ring[136].value[29] = 0x76; + ek_ring[136].value[30] = 0x70; + ek_ring[136].value[31] = 0xf9; + ek_ring[135].key_state = KEY_DEACTIVATED; } static void Crypto_Local_Init(void) @@ -632,18 +704,29 @@ static void Crypto_Calc_CRC_Init_Table(void) /* ** Assisting Functions */ -static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame) +static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame, SecurityAssociation_t *sa_ptr) // Returns the payload length of current tc_frame in BYTES! { + int tf_hdr = 5; int seg_hdr = 0;if(SEGMENTATION_HDR){seg_hdr=1;} - int fecf = 0;if(HAS_FECF){fecf=FECF_SIZE;} int spi = 2; - int iv_size = IV_SIZE_TC; if(PUS_HDR){iv_size=IV_SIZE - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. - int tf_hdr = 5; + int iv_size = sa_ptr->shivf_len; if(PUS_HDR){iv_size=sa_ptr->shivf_len - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. + int mac_size = sa_ptr->stmacf_len; + int fecf = 0;if(HAS_FECF){fecf=FECF_SIZE;} + + #ifdef TC_DEBUG + OS_printf("Get_tcPayloadLength Debug [byte lengths]:\n"); + OS_printf("\thdr.fl\t%d\n", tc_frame->tc_header.fl); + OS_printf("\ttf_hdr\t%d\n",tf_hdr); + OS_printf("\tSeg hdr\t%d\t\n",seg_hdr); + OS_printf("\tspi \t%d\n",spi); + OS_printf("\tiv_size\t%d\n",iv_size); + OS_printf("\tmac\t%d\n",mac_size); + OS_printf("\tfecf \t%d\n",fecf); + OS_printf("\tTOTAL LENGTH: %d\n", (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + FECF_SIZE))); + #endif - return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (MAC_SIZE + FECF_SIZE) ); - //return (tc_frame->tc_header.fl - (5 + 2 + IV_SIZE ) - (MAC_SIZE + FECF_SIZE) ); - //TFHDR=5bytes, SegHdr=1byte,SPI=2bytes,SeqNum=4bytes,MAC=16bytes,FECF=2bytes -- should be 30 bytes max, above calculation seems incorrect. + return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + FECF_SIZE) ); } static int32 Crypto_Get_tmLength(int len) @@ -975,7 +1058,7 @@ static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest) uint8 bit; uint8 c15; - for (int i = 0; i <= len_ingest; i++) + for (int i = 0; i < len_ingest; i++) { // Byte Logic for (int j = 0; j < 8; j++) { // Bit Logic @@ -988,7 +1071,6 @@ static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest) } } } - // Check if Testing if (badFECF == 1) { @@ -2053,9 +2135,9 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len if (p_in_frame == NULL) { - status = OS_ERROR; + status = CRYPTO_LIB_ERR_NULL_BUFFER; OS_printf(KRED "Error: Input Buffer NULL! \n" RESET); - return status; //Just return here, nothing can be done. + return status; // Just return here, nothing can be done. } #ifdef DEBUG @@ -2096,7 +2178,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len #ifdef TC_DEBUG OS_printf(KYEL "DEBUG - Received Control/Command frame - nothing to do.\n" RESET); #endif - status = OS_ERROR; + status = CRYPTO_LIB_ERR_INVALID_CC_FLAG; } // TODO: If command frame flag not set, need to know SDLS parameters @@ -2106,7 +2188,16 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len if (status == OS_SUCCESS) { // Query SA DB for active SA / SDLS parameters - status = sadb_routine->sadb_get_operational_sa_from_gvcid(temp_tc_header.tfvn, temp_tc_header.scid, temp_tc_header.vcid, map_id,&sa_ptr); + if(sadb_routine == NULL) //This should not happen, but tested here for safety + { + OS_printf(KRED "ERROR: SA DB Not initalized! -- CRYPTO_LIB_ERR_NO_INIT, Will Exit\n" RESET); + status = CRYPTO_LIB_ERR_NO_INIT; + } + else + { + status = sadb_routine->sadb_get_operational_sa_from_gvcid(temp_tc_header.tfvn, temp_tc_header.scid, temp_tc_header.vcid, map_id,&sa_ptr); + } + // If unable to get operational SA, can return if (status != OS_SUCCESS) @@ -2250,18 +2341,10 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len // Set initialization vector if specified if ((sa_service_type == SA_AUTHENTICATION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION) || (sa_service_type == SA_ENCRYPTION)) { #ifdef SA_DEBUG - OS_printf(KYEL "Old IV value was:\n\t"); - for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} - OS_printf("\n" RESET); - #endif - #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); - #endif - #ifdef SA_DEBUG - OS_printf(KYEL "New IV value is:\n\t"); + OS_printf(KYEL "Using IV value:\n\t"); for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} OS_printf("\n" RESET); #endif @@ -2396,23 +2479,24 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len if ((sa_service_type == SA_AUTHENTICATION) || \ (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) { + uint8 bit_masked_data[sa_ptr->abm_len]; for (int y = 0; y < sa_ptr->abm_len; y++) { - aad[y] = p_in_frame[y] & sa_ptr->abm[y]; + bit_masked_data[y] = p_new_enc_frame[y] & sa_ptr->abm[y]; } #ifdef MAC_DEBUG OS_printf(KYEL "Preparing AAD:\n"); OS_printf("\tUsing ABM Length of %d\n\t", sa_ptr->abm_len); for (int y = 0; y < sa_ptr->abm_len; y++) { - OS_printf("%02x", aad[y]); + OS_printf("%02x", bit_masked_data[y]); } OS_printf("\n" RESET); #endif gcry_error = gcry_cipher_authenticate( tmp_hd, - &(aad[0]), // additional authenticated data + bit_masked_data, // additional authenticated data sa_ptr->abm_len // length of AAD ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -2447,12 +2531,24 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE), // plaintext input TODO: Determine if Segment header exists, assuming yes (+1) for now tf_payload_len // in data length ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); status = OS_ERROR; return status; } + + #ifdef TC_DEBUG + OS_printf("Encrypted bytes output_loc is %d\n", index); + OS_printf("tf_payload_len is %d\n", tf_payload_len); + OS_printf(KYEL "Printing TC Frame after encryption:\n\t"); + for(int i=0; i < *p_enc_frame_len; i++) + { + OS_printf("%02X", *(p_new_enc_frame + i)); + } + OS_printf("\n"); + #endif } if ((sa_service_type == SA_AUTHENTICATION) || \ @@ -2482,6 +2578,15 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len gcry_cipher_close(tmp_hd); } } + + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); + #ifdef SA_DEBUG + OS_printf(KYEL "Next IV value is:\n\t"); + for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} + OS_printf("\n" RESET); + #endif + #endif /* ** End Authentication / Encryption */ @@ -2594,7 +2699,6 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } } - if ((report.lspiu > NUM_SA) && (status == OS_SUCCESS)) { report.ispif = 1; @@ -2656,33 +2760,201 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro status = OS_ERROR; //Error -- unable to get SA from SPI. return status; } + if((sa_ptr->est == 1) && (sa_ptr->ast == 0)) + { + // Encryption Only + #ifdef DEBUG + OS_printf(KBLU "ENCRYPTED TC Received!\n" RESET); + #endif + + #ifdef TC_DEBUG + OS_printf("IV: \n"); + #endif + for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) + { + tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; + #ifdef TC_DEBUG + OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); + #endif + } + byte_idx += sa_ptr->shivf_len; + report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; + + #ifdef DEBUG + OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); + OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); + #endif + + // Check IV is in ARCW + if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != CRYPTO_LIB_SUCCESS ) + { + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV not in window! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { + if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == CRYPTO_LIB_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value + for (int i = 0; i < (sa_ptr->shivf_len); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } + } + } + + if ( status != CRYPTO_LIB_SUCCESS ) + { // Exit + *len_ingest = 0; + return status; + } + + tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); + printf("PDU LENGTH: %d\n", tc_sdls_processed_frame->tc_pdu_len); + x = x + tc_sdls_processed_frame->tc_pdu_len; + + #ifdef TC_DEBUG + OS_printf("TC: \n"); + for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) + { + OS_printf("\t ingest[%d] = 0x%02x \n", temp, (uint8)ingest[temp+20]); + } + #endif + + // FECF + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); + Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 1),tc_sdls_processed_frame); + + // Initialize the key + //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[sa_ptr->ekid]); + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef DEBUG + OS_printf("Key ID = %d, 0x", sa_ptr->ekid); + for(int y = 0; y < KEY_SIZE; y++) + { + OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); + } + OS_printf("\n"); + #endif + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[sa_ptr->ekid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(sa_ptr->iv[0]), + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + gcry_error = gcry_cipher_decrypt( + tmp_hd, + &(tc_sdls_processed_frame->tc_pdu[0]), // plaintext output + tc_sdls_processed_frame->tc_pdu_len, // length of data + &(ingest[20]), // ciphertext input + tc_sdls_processed_frame->tc_pdu_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_cipher_close(tmp_hd); + + // Increment the IV for next time + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); + #endif + } // Determine mode via SPI - if ((sa_ptr->est == 1) && + else if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) - { // Authenticated Encryption + { // Authenticated/Encrypted #ifdef DEBUG - OS_printf(KBLU "ENCRYPTED TC Received!\n" RESET); + OS_printf(KBLU "Authenticated/Encrypted TC Received!\n" RESET); #endif #ifdef TC_DEBUG OS_printf("IV: \n"); #endif - for (x = byte_idx; x < (byte_idx + IV_SIZE); x++) + for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) { tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; #ifdef TC_DEBUG OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); #endif } - byte_idx += IV_SIZE; - report.snval = tc_sdls_processed_frame->tc_sec_header.iv[IV_SIZE-1]; + byte_idx += sa_ptr->shivf_len; + report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; #ifdef DEBUG - OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", IV_SIZE-1, tc_sdls_processed_frame->tc_sec_header.iv[IV_SIZE-1]); - OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, IV_SIZE-1, sa_ptr->iv[IV_SIZE-1]); + OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); + OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); #endif // Check IV is in ARCW - if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, IV_SIZE, + if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) { report.af = 1; @@ -2706,7 +2978,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } else { - if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, IV_SIZE) == OS_SUCCESS ) + if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) { // Replay - IV value lower than expected report.af = 1; report.bsnf = 1; @@ -2729,7 +3001,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } else { // Adjust expected IV to acceptable received value - for (int i = 0; i < (IV_SIZE); i++) + for (int i = 0; i < (sa_ptr->shivf_len); i++) { sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; } @@ -2742,7 +3014,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro return status; } - tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame); + tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); x = x + tc_sdls_processed_frame->tc_pdu_len; @@ -2765,11 +3037,11 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro OS_printf("\t mac[%d] = 0x%02x\n", y-x, tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); #endif } - x = x + MAC_SIZE; + x = x + sa_ptr->stmacf_len; // FECF tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); - Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 2),tc_sdls_processed_frame); + Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 1),tc_sdls_processed_frame); // Initialize the key //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[sa_ptr->ekid]); @@ -2796,7 +3068,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro #endif gcry_error = gcry_cipher_setkey( tmp_hd, - &(ek_ring[sa_ptr->ekid].value[0]), + ek_ring[sa_ptr->ekid].value, KEY_SIZE ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -2807,7 +3079,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } gcry_error = gcry_cipher_setiv( tmp_hd, - &(sa_ptr->iv[0]), + sa_ptr->iv, sa_ptr->iv_len ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) @@ -2820,9 +3092,11 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro OS_printf("AAD = 0x"); #endif // Prepare additional authenticated data (AAD) + + uint8 aad[sa_ptr->abm_len]; for (y = 0; y < sa_ptr->abm_len; y++) { - ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); + aad[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); #ifdef MAC_DEBUG OS_printf("%02x", (uint8) ingest[y]); #endif @@ -2831,12 +3105,26 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro OS_printf("\n"); #endif + gcry_error = gcry_cipher_authenticate( + tmp_hd, + aad, // additional authenticated data + sa_ptr->abm_len // length of AAD + ); + + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_decrypt( tmp_hd, - &(tc_sdls_processed_frame->tc_pdu[0]), // plaintext output - tc_sdls_processed_frame->tc_pdu_len, // length of data - &(ingest[20]), // ciphertext input - tc_sdls_processed_frame->tc_pdu_len // in data length + tc_sdls_processed_frame->tc_pdu, // plaintext output + tc_sdls_processed_frame->tc_pdu_len, // length of data + &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input + tc_sdls_processed_frame->tc_pdu_len // in data length ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { @@ -2846,14 +3134,15 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } gcry_error = gcry_cipher_checktag( tmp_hd, - &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag input - MAC_SIZE // tag size + tc_sdls_processed_frame->tc_sec_trailer.mac, // tag input + sa_ptr->stmacf_len // tag size ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - OS_printf("Actual MAC = 0x"); + OS_printf("Calculated MAC = 0x"); for (int z = 0; z < MAC_SIZE; z++) { OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); @@ -2862,8 +3151,8 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro gcry_error = gcry_cipher_gettag( tmp_hd, - &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output - MAC_SIZE // tag size + &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output + MAC_SIZE // tag size ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { @@ -2887,8 +3176,299 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro // Increment the IV for next time #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, IV_SIZE); + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); #endif + } + else if((sa_ptr->ast == 1) && (sa_ptr->est == 0)) + { + // Authentication only + #ifdef DEBUG + OS_printf(KBLU "Authenticated TC Received!\n" RESET); + #endif + #ifdef TC_DEBUG + OS_printf(KYEL "IV: \n\t"); + #endif + for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) + { + tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; + #ifdef TC_DEBUG + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); + #endif + } + #ifdef TC_DEBUG + OS_printf("\n"RESET); + #endif + byte_idx += sa_ptr->shivf_len; + report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; + + #ifdef DEBUG + OS_printf("\ttc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); + OS_printf("\tsa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); + #endif + + // Check IV is in ARCW + if (Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) + { + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV not in window! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { + if (Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value + for (int i = 0; i < (sa_ptr->shivf_len); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } + } + } + if ( status == OS_ERROR ) + { // Exit + *len_ingest = 0; + return status; + } + tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); + + // Copy pdu data from ingest into memory + for(int i=0; itc_pdu_len; i++) + { + tc_sdls_processed_frame->tc_pdu[i] = ingest[x]; + x++; + } + + // x = x + tc_sdls_processed_frame->tc_pdu_len; + + #ifdef TC_DEBUG + OS_printf("tc_pdu_len is: %d\n", tc_sdls_processed_frame->tc_pdu_len); + OS_printf("TC PDU ingest Payload: \n\t"); + for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) + { + OS_printf("%02x", (uint8)ingest[temp+20]); + } + OS_printf("\n"); + #endif + + // Security Trailer + #ifdef TC_DEBUG + OS_printf("MAC: \n\t"); + #endif + for (y = x; y < (x + sa_ptr->stmacf_len); y++) + { + tc_sdls_processed_frame->tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; + #ifdef TC_DEBUG + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); + #endif + } + #ifdef TC_DEBUG + OS_printf("\n"); + #endif + x = x + sa_ptr->stmacf_len; + + // FECF + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); + Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl-1),tc_sdls_processed_frame); + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef DEBUG + OS_printf("Key ID = %d, 0x", sa_ptr->ekid); + for(int y = 0; y < KEY_SIZE; y++) + { + OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); + } + OS_printf("\n"); + #endif + gcry_error = gcry_cipher_setkey( + tmp_hd, + ek_ring[sa_ptr->ekid].value, + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + sa_ptr->iv, + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef MAC_DEBUG + OS_printf("AAD = 0x"); + #endif + // Prepare additional authenticated data (AAD) + for (y = 0; y < sa_ptr->abm_len; y++) + { + ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); + #ifdef DEBUG + OS_printf("%02x", (uint8) ingest[y]); + #endif + } + #ifdef DEBUG + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_authenticate( + tmp_hd, + ingest, // additional authenticated data + sa_ptr->abm_len // length of AAD + ); + + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + status = OS_ERROR; + return status; + } + // printf("PDU LEN: %d\n", tc_sdls_processed_frame->tc_pdu_len); + // gcry_error = gcry_cipher_decrypt( + // tmp_hd, + // tc_sdls_processed_frame->tc_pdu, // plaintext output + // tc_sdls_processed_frame->tc_pdu_len, // length of data + // &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input + // tc_sdls_processed_frame->tc_pdu_len // in data length + // ); + // if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + // { + // OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + // status = OS_ERROR; + // return status; + // } + char *garbage_buff = malloc(tc_sdls_processed_frame->tc_pdu_len * sizeof(unsigned char)); + + gcry_error = gcry_cipher_encrypt( + tmp_hd, + // tc_sdls_processed_frame->tc_pdu, // plaintext output + garbage_buff, + tc_sdls_processed_frame->tc_pdu_len, // length of data + &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input + tc_sdls_processed_frame->tc_pdu_len // in data length + ); + free(garbage_buff); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_gettag( + tmp_hd, + &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output + sa_ptr->stmacf_len // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_gettag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + + #ifdef MAC_DEBUG + OS_printf("TC_Process Expected MAC = 0x"); + for (int z = 0; z < sa_ptr->stmacf_len ; z++) + { + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[z]); + } + OS_printf("\n"); + OS_printf("TC_Process Actual MAC = 0x"); + for (int z = 0; z < sa_ptr->stmacf_len ; z++) + { + OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); + } + OS_printf("\n"); + #endif + + #ifdef DEBUG + OS_printf("Using PDU length of: %d\n", tc_sdls_processed_frame->tc_pdu_len); + OS_printf("Printing entire frame sans header in memory:\n\t0x"); + // for(int i=0; itc_header); i++) + // { + // OS_printf("%02x", tc_sdls_processed_frame->tc_header[i]); + // } + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.sh); + OS_printf("%04x", tc_sdls_processed_frame->tc_sec_header.spi); + for(int i=0; iiv_len; i++) + { + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.iv[i]); + } + for(int i=0; itc_pdu_len; i++) + { + OS_printf("%02x", tc_sdls_processed_frame->tc_pdu[i]); + } + for(int i=0; istmacf_len; i++) + { + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[i]); + } + OS_printf("%04x\n", tc_sdls_processed_frame->tc_sec_trailer.fecf); + #endif + + status = OS_ERROR; + report.bmacf = 1; + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + return status; + gcry_cipher_close(tmp_hd); + + // Increment the IV for next time + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); + #endif + } else { // Clear @@ -2896,24 +3476,24 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro OS_printf(KBLU "CLEAR TC Received!\n" RESET); #endif - for (y = 10; y <= (tc_sdls_processed_frame->tc_header.fl - 2); y++) //tfhdr+seghdr+sechdr=5+1+6=12 + for (y = 10; y <= (tc_sdls_processed_frame->tc_header.fl -1); y++) //tfhdr+seghdr+sechdr=5+1+6=12 { tc_sdls_processed_frame->tc_pdu[y - 10] = (uint8)ingest[y]; } // FECF tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[y] << 8) | ((uint8)ingest[y+1]); - Crypto_FECF((int) tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 2),tc_sdls_processed_frame); + Crypto_FECF((int) tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl),tc_sdls_processed_frame); } #ifdef TC_DEBUG Crypto_tcPrint(tc_sdls_processed_frame); #endif - // Zero ingest - for (x = 0; x < *len_ingest; x++) - { - ingest[x] = 0; - } + // // Zero ingest + // for (x = 0; x < *len_ingest; x++) + // { + // ingest[x] = 0; + // } if(!TC_PROCESS_SDLS_PDUS) //If we don't want to process frame data for SDLS PDUs, only reverse security & return content. @@ -3017,6 +3597,13 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } }//End Process SDLS PDU + // Zero ingest + memset(ingest, 0, *len_ingest); + // for (x = 0; x < *len_ingest; x++) + // { + // ingest[x] = 0; + // } + #ifdef OCF_DEBUG Crypto_fsrPrint(&report); #endif @@ -3031,7 +3618,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) // Accepts CCSDS message in ingest, and packs into TM before encryption { - int32 status = ITC_GCM128_SUCCESS; + int32 status = CRYPTO_LIB_SUCCESS; int count = 0; int pdu_loc = 0; int pdu_len = *len_ingest - TM_MIN_SIZE; diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c index 84479080..5ac25635 100644 --- a/fsw/src/sadb_routine_inmemory.template.c +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -16,6 +16,7 @@ #include "crypto_structs.h" #include "crypto_print.h" #include "crypto.h" +#include "crypto_error.h" // Security Association Initialization Functions static int32 sadb_config(void); @@ -123,8 +124,8 @@ static int32 sadb_config(void) sa[4].ast = 1; sa[4].shivf_len = 12; sa[4].stmacf_len = 16; - sa[4].iv_len = IV_SIZE; - sa[4].iv[IV_SIZE-1] = 0; + sa[4].iv_len = 12; + sa[4].iv[11] = 0; sa[4].abm_len = 0x14; // 20 for (int i = 0; i < sa[4].abm_len; i++) { // Zero AAD bit mask @@ -183,22 +184,21 @@ static int32 sadb_config(void) sa[7].iv_len = IV_SIZE; sa[7].iv[IV_SIZE-1] = 0; sa[7].abm_len = 0x14; // 20 - for (int i = 0; i < sa[4].abm_len; i++) + for (int i = 0; i < sa[7].abm_len; i++) { // Zero AAD bit mask - sa[4].abm[i] = 0x00; + sa[7].abm[i] = 0x00; } sa[7].arcw_len = 1; sa[7].arcw[0] = 5; - sa[7].arc_len = (sa[4].arcw[0] * 2) + 1; + sa[7].arc_len = (sa[7].arcw[0] * 2) + 1; sa[7].gvcid_tc_blk.tfvn = 0; sa[7].gvcid_tc_blk.scid = SCID & 0x3FF; sa[7].gvcid_tc_blk.vcid = 1; sa[7].gvcid_tc_blk.mapid = TYPE_TC; - return status; // SA 8 - CLEAR MODE sa[8].spi = 8; - sa[8].sa_state = SA_OPERATIONAL; + sa[8].sa_state = SA_NONE; sa[8].est = 0; sa[8].ast = 0; sa[8].arc_len = 1; @@ -209,6 +209,29 @@ static int32 sadb_config(void) sa[8].gvcid_tc_blk.vcid = 1; sa[8].gvcid_tc_blk.mapid = TYPE_TC; + // SA 9 - Validation Tests + sa[9].spi = 9; + sa[9].ekid = 136; + sa[9].sa_state = SA_KEYED; + sa[9].est = 1; + sa[9].ast = 0; + sa[9].shivf_len = 12; + sa[9].iv_len = 12; + sa[9].iv[12] = 0; + sa[9].abm_len = 0x14; // 20 + for (int i = 0; i < sa[9].abm_len; i++) + { // Zero AAD bit mask + sa[9].abm[i] = 0x00; + } + sa[9].arcw_len = 1; + sa[9].arcw[0] = 5; + sa[9].arc_len = (sa[9].arcw[0] * 2) + 1; + sa[9].gvcid_tc_blk.tfvn = 0; + sa[9].gvcid_tc_blk.scid = SCID & 0x3FF; + sa[9].gvcid_tc_blk.vcid = 0; + sa[9].gvcid_tc_blk.mapid = TYPE_TC; + + return status; } static int32 sadb_init(void) @@ -240,6 +263,12 @@ static int32 sadb_close(void) return OS_SUCCESS; } +#ifdef ENCTEST +int32 expose_sadb_get_sa_from_spi(uint16 spi, SecurityAssociation_t** security_association) +{ + sadb_get_sa_from_spi(spi, security_association); +} +#endif /* ** Security Association Interaction Functions @@ -257,29 +286,81 @@ static int32 sadb_get_sa_from_spi(uint16 spi,SecurityAssociation_t** security_as static int32 sadb_get_operational_sa_from_gvcid(uint8 tfvn,uint16 scid,uint16 vcid,uint8 mapid,SecurityAssociation_t** security_association) { - int32 status = OS_SUCCESS; + int32 status = CRYPTO_LIB_ERROR; - for (int i=0; i < NUM_SA;i++) + for (int i=0; i<10; i++) { - if (sa[i].gvcid_tc_blk.tfvn == tfvn && sa[i].gvcid_tc_blk.scid == scid && sa[i].gvcid_tc_blk.vcid == vcid && sa[i].gvcid_tc_blk.mapid == mapid //gvcid - && sa[i].sa_state == SA_OPERATIONAL) + if ((sa[i].gvcid_tc_blk.tfvn == tfvn) && (sa[i].gvcid_tc_blk.scid == scid) && (sa[i].gvcid_tc_blk.vcid == vcid) && (sa[i].gvcid_tc_blk.mapid == mapid && sa[i].sa_state == SA_OPERATIONAL)) { *security_association = &sa[i]; - #ifdef TC_DEBUG - OS_printf("Operational SA found at index %d.\n", i); + #ifdef SA_DEBUG + OS_printf("Valid operational SA found at index %d.\n", i); #endif - return status; + status = CRYPTO_LIB_SUCCESS; + break; } } - // We only get here if no operational SA found - OS_printf(KRED "Error: No operational SA found! \n" RESET); - status = OS_ERROR; + // If not a success, attempt to generate a meaningful error code + if (status != CRYPTO_LIB_SUCCESS) + { + #ifdef SA_DEBUG + OS_printf(KRED "Error - Making best attempt at a useful error code:\n\t" RESET); + #endif + + for (int i=0; i len(data)- 1 and offset+length > len(data): + return 0 + crc = 0xFFFF + for i in range(0, length): + crc ^= data[offset + i] << 8 + for j in range(0,8): + if (crc & 0x8000) > 0: + crc =(crc << 1) ^ 0x1021 + else: + crc = crc << 1 + return crc & 0xFFFF + +class Encryption: + def __init__(self): + self.results = 0x00 + self.length = 0.0 + def encrypt(self, data, key, iv, header, bitmask): + hex_header = header + iv + bitmask_b = bytes.fromhex(bitmask) + header_b = bytes.fromhex(hex_header) + key_b = bytes.fromhex(key) + iv_b = bytes.fromhex(iv) + data_b = bytes.fromhex(data) + + cipher = AES.new(key_b, AES.MODE_GCM, nonce=iv_b) + + if len(bitmask) > 1: + zeroed_header = '' + zeroed_header_b = bytes.fromhex(zeroed_header) + + L = [header_b[i:i+1] for i in range (len(header_b))] + + for pieces in L: + value_i = int.from_bytes(pieces, byteorder="big") & int.from_bytes(bitmask_b, byteorder="big") + value_b = value_i.to_bytes(max(len(pieces), len(bitmask_b)), byteorder="big") + zeroed_header_b += value_b + cipher.update(zeroed_header_b) + #cipher.update(header_b) + ciphertext, tag = cipher.encrypt_and_digest(data_b) + print("Cipher: ", ciphertext.hex()) + print("Tag: ", tag.hex()) + + final_val = header_b + ciphertext + tag + + check_sum = crc16(bytearray(final_val), 0, len(final_val)) + final_val += check_sum.to_bytes(2, byteorder = "big") + + # Padding for Later + # while (len(final_val.hex()) %8) != 0: + # final_val += bytes.fromhex("00") + + final_val_len = (len(final_val.hex()) / 2) + self.results = final_val + self.length = final_val_len + #print(self.results, self.length) + + def get_len(self): + #print(self.length) + return self.length + + def get_results(self): + #print(self.results.hex()) + return self.results + +if __name__ == '__main__': + something=Encryption() + something.encrypt("1880d2ca0008197f0b0031000039c5", "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210", "000000000000000000000001", "2003043400FF0004", "00") + something.get_len() + something.get_results() + + From ef566b6853a90a3ca8fd98ac7af095836ba723fa Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Tue, 7 Dec 2021 13:48:11 -0800 Subject: [PATCH 050/184] AKMC-97: Managed Parameter interface rework for better integration with downstream apps --- fsw/public_inc/crypto.h | 12 +++- fsw/public_inc/crypto_error.h | 8 ++- fsw/public_inc/crypto_structs.h | 3 +- fsw/src/crypto.c | 124 ++++++++++++++++++++------------ 4 files changed, 97 insertions(+), 50 deletions(-) diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index f4c1f879..0657747a 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -38,10 +38,16 @@ ivv-itc@lists.nasa.gov /* ** Prototypes */ + +// Crypto Library Configuration functions +extern int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 process_sdls_pdus, uint8 has_pus_hdr, uint8 ignore_sa_state, uint8 ignore_anti_replay, uint8 vcid_bitmask); +extern int32 Crypto_Config_MariaDB(char* mysql_username, char* mysql_password, char* mysql_hostname, char* mysql_database, uint16 mysql_port); +extern int32 Crypto_Config_Add_Gvcid_Managed_Parameter(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr); + // Initialization -extern int32 Crypto_Init(void); //Initialize CryptoLib with defaults -extern int32 Crypto_Init_Main(CryptoConfig_t* config,SadbMariaDBConfig_t* sadb_mariadb_config); //Initialize CryptoLib with application specified defaults -extern int32 Crypto_Init_With_Props(char** configs,int32 num_configs); //Initialize CryptoLib with string properties per SIS +extern int32 Crypto_Init(void); //Initialize CryptoLib After Configuration Calls +extern int32 Crypto_Init_With_Configs(CryptoConfig_t* crypto_config_p,GvcidManagedParameters_t* gvcid_managed_parameters_p,SadbMariaDBConfig_t* sadb_mariadb_config_p); //Initialize CryptoLib With Application Defined Configuration +extern int32 Crypto_Init_Unit_Test(void); //Initialize CryptoLib with unit test default Configurations // Telecommand (TC) extern int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ uint8 **pp_enc_frame, uint16 *p_enc_frame_len); diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h index 238a5506..b4bac24d 100644 --- a/fsw/public_inc/crypto_error.h +++ b/fsw/public_inc/crypto_error.h @@ -19,8 +19,12 @@ ivv-itc@lists.nasa.gov #include "sadb_mariadb_error.h" -#define SADB_INVALID_SADB_TYPE 201 -#define MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND 101 +#define SADB_INVALID_SADB_TYPE 201 +#define CRYPTO_CONFIGURATION_NOT_COMPLETE 101 +#define CRYPTO_MANAGED_PARAM_CONFIGURATION_NOT_COMPLETE 102 +#define CRYPTO_MARIADB_CONFIGURATION_NOT_COMPLETE 103 +#define MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND 104 + #endif //_crypto_error_h_ diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index 59021a06..8f8f54a2 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -232,7 +232,8 @@ typedef struct /* ** Telecommand (TC) Definitions */ -typedef struct __attribute__ ((packed)) +//typedef struct __attribute__ ((packed)) //__attribute__ ((packed)) is not easily supported in CFFI python. Only add when CFFI properly supports packed & nonpacked structs. +typedef struct { uint8 tfvn :2; // Transfer Frame Version Number uint8 bypass :1; // Bypass diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 820c8fb0..fdaa405f 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -101,10 +101,10 @@ crypto_key_t ek_ring[NUM_KEYS] = {0}; //static crypto_key_t ak_ring[NUM_KEYS]; CCSDS_t sdls_frame; TM_t tm_frame; -CryptoConfig_t* crypto_config; -SadbMariaDBConfig_t* sadb_mariadb_config; -GvcidManagedParameters_t* gvcid_managed_parameters; -GvcidManagedParameters_t* current_managed_parameters; +CryptoConfig_t* crypto_config = NULL; +SadbMariaDBConfig_t* sadb_mariadb_config = NULL; +GvcidManagedParameters_t* gvcid_managed_parameters = NULL; +GvcidManagedParameters_t* current_managed_parameters = NULL; // OCF static uint8 ocf = 0; static SDLS_FSR_t report; @@ -125,60 +125,50 @@ static uint16 crc16Table[256]; /* ** Initialization Functions */ -int32 Crypto_Init(void) +int32 Crypto_Init_Unit_Test(void) { int32 status = OS_SUCCESS; - CryptoConfig_t* config_local = (CryptoConfig_t*) calloc(1, CRYPTO_CONFIG_SIZE); - config_local->sadb_type=SADB_TYPE_INMEMORY; - config_local->crypto_create_fecf=CRYPTO_TC_CREATE_FECF_TRUE; - config_local->process_sdls_pdus=TC_PROCESS_SDLS_PDUS_TRUE; - config_local->has_pus_hdr=TC_HAS_PUS_HDR; - config_local->vcid_bitmask=0x3F; - gvcid_managed_parameters = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); - - //initialize managed parameters as expected for unit tests - gvcid_managed_parameters->tfvn=0; - gvcid_managed_parameters->scid=0x0003; - gvcid_managed_parameters->vcid=0; - gvcid_managed_parameters->has_fecf=TC_HAS_FECF; - gvcid_managed_parameters->has_segmentation_hdr=TC_HAS_SEGMENT_HDRS; - gvcid_managed_parameters->next=NULL; - current_managed_parameters = gvcid_managed_parameters; - - SadbMariaDBConfig_t* sadb_mariadb_config_local = (SadbMariaDBConfig_t*)calloc(1, SADB_MARIADB_CONFIG_SIZE); - sadb_mariadb_config_local->mysql_username="sadb_user"; - sadb_mariadb_config_local->mysql_password="sadb_password"; - sadb_mariadb_config_local->mysql_hostname="localhost"; - sadb_mariadb_config_local->mysql_database="sadb"; - sadb_mariadb_config_local->mysql_port=0; - - //config->sadb_type=SADB_MARIADB_TYPE; - - status = Crypto_Init_Main(config_local,sadb_mariadb_config_local); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE,0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); + status = Crypto_Init(); return status; } -int32 Crypto_Init_With_Props(char** configs, int32 num_configs) +int32 Crypto_Init_With_Configs(CryptoConfig_t* crypto_config_p,GvcidManagedParameters_t* gvcid_managed_parameters_p,SadbMariaDBConfig_t* sadb_mariadb_config_p) { int32 status = OS_SUCCESS; - CryptoConfig_t* config_local = (CryptoConfig_t*) calloc(1, CRYPTO_CONFIG_SIZE); - SadbMariaDBConfig_t* sadb_mariadb_config_local = (SadbMariaDBConfig_t*) calloc(1, SADB_MARIADB_CONFIG_SIZE); - - //Todo - Parse Gvcid Managed Parameters and CryptoLib config from input properties! - - status = Crypto_Init_Main(config_local,sadb_mariadb_config_local); + crypto_config = crypto_config_p; + gvcid_managed_parameters = gvcid_managed_parameters_p; + sadb_mariadb_config = sadb_mariadb_config_p; + status = Crypto_Init(); return status; } -int32 Crypto_Init_Main(CryptoConfig_t* config_p,SadbMariaDBConfig_t* sadb_mariadb_config_p) + +int32 Crypto_Init(void) { int32 status = OS_SUCCESS; - //Set global vars to passed in config objects. - crypto_config = config_p; - sadb_mariadb_config = sadb_mariadb_config_p; + if(crypto_config==NULL){ + status = CRYPTO_CONFIGURATION_NOT_COMPLETE; + OS_printf(KRED "ERROR: CryptoLib must be configured before intializing!\n" RESET); + return status; //No configuration set -- return! + } + if(gvcid_managed_parameters==NULL){ + status = CRYPTO_MANAGED_PARAM_CONFIGURATION_NOT_COMPLETE; + OS_printf(KRED "ERROR: CryptoLib Managed Parameters must be configured before intializing!\n" RESET); + return status; //No Managed Parameter configuration set -- return! + } + //Prepare SADB type from config if (crypto_config->sadb_type == SADB_TYPE_INMEMORY){ sadb_routine = get_sadb_routine_inmemory(); } - else if (crypto_config->sadb_type == SADB_TYPE_MARIADB){ sadb_routine = get_sadb_routine_mariadb(); } + else if (crypto_config->sadb_type == SADB_TYPE_MARIADB){ + if(sadb_mariadb_config == NULL){ + status = CRYPTO_MARIADB_CONFIGURATION_NOT_COMPLETE; + OS_printf(KRED "ERROR: CryptoLib MariaDB must be configured before intializing!\n" RESET); + return status; //MariaDB connection specified but no configuration exists, return! + } + sadb_routine = get_sadb_routine_mariadb(); + } else { status = SADB_INVALID_SADB_TYPE; return status; } //TODO: Error stack // Initialize libgcrypt @@ -215,6 +205,52 @@ int32 Crypto_Init_Main(CryptoConfig_t* config_p,SadbMariaDBConfig_t* sadb_mariad return status; } +int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 process_sdls_pdus, uint8 has_pus_hdr, uint8 ignore_sa_state, uint8 ignore_anti_replay, uint8 vcid_bitmask) +{ + int32 status = OS_SUCCESS; + crypto_config = (CryptoConfig_t*) calloc(1, CRYPTO_CONFIG_SIZE); + crypto_config->sadb_type=sadb_type; + crypto_config->crypto_create_fecf=crypto_create_fecf; + crypto_config->process_sdls_pdus=process_sdls_pdus; + crypto_config->has_pus_hdr=has_pus_hdr; + crypto_config->ignore_sa_state=ignore_sa_state; + crypto_config->ignore_anti_replay=ignore_anti_replay; + crypto_config->vcid_bitmask=vcid_bitmask; + return status; +} +int32 Crypto_Config_MariaDB(char* mysql_username, char* mysql_password, char* mysql_hostname, char* mysql_database, uint16 mysql_port) +{ + int32 status = OS_SUCCESS; + sadb_mariadb_config = (SadbMariaDBConfig_t*)calloc(1, SADB_MARIADB_CONFIG_SIZE); + sadb_mariadb_config->mysql_username=mysql_username; + sadb_mariadb_config->mysql_password=mysql_password; + sadb_mariadb_config->mysql_hostname=mysql_hostname; + sadb_mariadb_config->mysql_database=mysql_database; + sadb_mariadb_config->mysql_port=mysql_port; + return status; +} +int32 Crypto_Config_Add_Gvcid_Managed_Parameter(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr) +{ + int32 status = OS_SUCCESS; + GvcidManagedParameters_t* gvcid_managed_parameters_local = gvcid_managed_parameters; + + while(gvcid_managed_parameters_local != NULL){ + gvcid_managed_parameters_local = gvcid_managed_parameters_local->next; + } + gvcid_managed_parameters_local = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); + gvcid_managed_parameters_local->tfvn=tfvn; + gvcid_managed_parameters_local->scid=scid; + gvcid_managed_parameters_local->vcid=vcid; + gvcid_managed_parameters_local->has_fecf=has_fecf; + gvcid_managed_parameters_local->has_segmentation_hdr=has_segmentation_hdr; + gvcid_managed_parameters_local->next=NULL; + + if(gvcid_managed_parameters==NULL) + gvcid_managed_parameters = gvcid_managed_parameters_local; + + return status; +} + static void Crypto_Local_Config(void) { // Initial TM configuration From 5c822c96cedcc0b188edcb8ec0b866f93ba88742 Mon Sep 17 00:00:00 2001 From: Robert Brown <91291114+rjbrown2@users.noreply.github.com> Date: Tue, 7 Dec 2021 17:12:25 -0500 Subject: [PATCH 051/184] CI additions, and minor fixes (#24) * CI additions, and minor fixes * Modified CI to work on collab_main branch * CI Fixes * CI Cleanup Authored-by: Robert Brown --- .github/workflows/build.yml | 32 +++++++++++++++++++++ .github/workflows/utest.yml | 38 ++++++++++++++++++++++++ .github/workflows/validation.yml | 40 ++++++++++++++++++++++++++ README.md | 8 +++++- fsw/crypto_util/app/et_dt_validation.c | 2 +- fsw/public_inc/crypto_structs.h | 2 +- 6 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/utest.yml create mode 100644 .github/workflows/validation.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..4a960f60 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,32 @@ +name: Build + +on: + push: + branches: [ collab_main ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: DEBUG + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. + # You can convert this to a matrix build if you need cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install Dependencies + run: sudo apt-get install -y libgpg-error-dev libgcrypt20-dev + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Build + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + diff --git a/.github/workflows/utest.yml b/.github/workflows/utest.yml new file mode 100644 index 00000000..51677f00 --- /dev/null +++ b/.github/workflows/utest.yml @@ -0,0 +1,38 @@ +name: Unit Tests + +on: + push: + branches: [ collab_main ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: DEBUG + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. + # You can convert this to a matrix build if you need cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install Dependencies + run: sudo apt-get install -y libgpg-error-dev libgcrypt20-dev + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Build + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Test + working-directory: ${{github.workspace}}/build + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ${{github.workspace}}/build/bin/ut_tc_apply + diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml new file mode 100644 index 00000000..58178d2b --- /dev/null +++ b/.github/workflows/validation.yml @@ -0,0 +1,40 @@ +name: Validation Tests + +on: + push: + branches: [ collab_main ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: DEBUG + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. + # You can convert this to a matrix build if you need cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install Dependencies + run: sudo apt-get install -y libgpg-error-dev libgcrypt20-dev python3 + + - name: Install Python Libraries + run: sudo pip install pycryptodome + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENCTEST=1 + + - name: Build + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Test + working-directory: ${{github.workspace}}/build + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ${{github.workspace}}/build/bin/et_dt_validation \ No newline at end of file diff --git a/README.md b/README.md index d57cbe92..601cf169 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ +![Build](https://github.com/nasa/CryptoLib/actions/workflows/build.yml/badge.svg) ![Unit Tests](https://github.com/nasa/CryptoLib/actions/workflows/utest.yml/badge.svg) ![Validation Tests](https://github.com/nasa/CryptoLib/actions/workflows/validation.yml/badge.svg) + # CryptoLib Provide a software-only solution using the CCSDS Space Data Link Security Protocol - Extended Procedures (SDLS-EP) to secure communications between a spacecraft running the core Flight System (cFS) and a ground station. In order to build crypto the following must be installed assuming Ubuntu 18.04 LTS: -* `sudo apt install libgpg-error-dev:i386 libgcrypt20-dev:i386` +* `sudo apt install libgpg-error-dev libgcrypt20-dev` + + +More information about building and usage of CryptoLib can be found within the repository Wiki: +https://github.com/nasa/CryptoLib/wiki diff --git a/fsw/crypto_util/app/et_dt_validation.c b/fsw/crypto_util/app/et_dt_validation.c index 94686030..c905e39e 100644 --- a/fsw/crypto_util/app/et_dt_validation.c +++ b/fsw/crypto_util/app/et_dt_validation.c @@ -894,7 +894,7 @@ UTEST(NIST_ENC_MAC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_1) uint16 enc_data_idx = enc_frame_len - buffer_cyber_chef_mac_len - 2; for (int i=0; i Date: Tue, 7 Dec 2021 17:19:16 -0500 Subject: [PATCH 052/184] Update build.yml Fixed build.yml --- .github/workflows/build.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4a960f60..5a53488f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,4 +29,9 @@ jobs: - name: Build # Build your program with the given configuration run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - + + - name: Test + working-directory: ${{github.workspace}}/build + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest -C ${{env.BUILD_TYPE}} From adb084dd79793cd683e26e0d0c8b041619902583 Mon Sep 17 00:00:00 2001 From: Robert Brown <91291114+rjbrown2@users.noreply.github.com> Date: Tue, 7 Dec 2021 17:23:08 -0500 Subject: [PATCH 053/184] Update crypto.c Removed PDU Length Print statement that was missed. --- fsw/src/crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 64bde762..078e1482 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2847,7 +2847,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); - printf("PDU LENGTH: %d\n", tc_sdls_processed_frame->tc_pdu_len); + x = x + tc_sdls_processed_frame->tc_pdu_len; #ifdef TC_DEBUG @@ -4027,4 +4027,4 @@ int32 Crypto_ProcessSecurity(char* ingest, int* len_ingest) return status; } -#endif \ No newline at end of file +#endif From c053c451a95e6b7ebe8c14f1f36064566835f8f6 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Tue, 7 Dec 2021 19:03:03 -0800 Subject: [PATCH 054/184] AKMC-97: More Managed Parameter code refinement and fixes --- fsw/public_inc/crypto_print.h | 1 + fsw/src/crypto.c | 43 ++++++++++++++++++++++++----------- fsw/src/crypto_print.c | 13 +++++++++++ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/fsw/public_inc/crypto_print.h b/fsw/public_inc/crypto_print.h index 13daaeb2..823098f3 100644 --- a/fsw/public_inc/crypto_print.h +++ b/fsw/public_inc/crypto_print.h @@ -36,4 +36,5 @@ void Crypto_ccsdsPrint(CCSDS_t* sdls_frame); void Crypto_saPrint(SecurityAssociation_t* sa); void Crypto_hexprint(void *c, size_t n); void Crypto_binprint(void *c, size_t n); +void Crypto_mpPrint(GvcidManagedParameters_t* managed_parameters); #endif diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index fdaa405f..476a4418 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -91,6 +91,7 @@ static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); // Managed Parameter Functions static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, GvcidManagedParameters_t** managed_parameters_out); +static int32 crypto_config_add_gvcid_managed_parameter_recursion(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr,GvcidManagedParameters_t* managed_parameter); static void Crypto_Free_Managed_Parameters(GvcidManagedParameters_t* managed_parameters); /* @@ -158,6 +159,9 @@ int32 Crypto_Init(void) return status; //No Managed Parameter configuration set -- return! } + #ifdef TC_DEBUG + Crypto_mpPrint(gvcid_managed_parameters); + #endif //Prepare SADB type from config if (crypto_config->sadb_type == SADB_TYPE_INMEMORY){ sadb_routine = get_sadb_routine_inmemory(); } @@ -232,23 +236,36 @@ int32 Crypto_Config_MariaDB(char* mysql_username, char* mysql_password, char* my int32 Crypto_Config_Add_Gvcid_Managed_Parameter(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr) { int32 status = OS_SUCCESS; - GvcidManagedParameters_t* gvcid_managed_parameters_local = gvcid_managed_parameters; - while(gvcid_managed_parameters_local != NULL){ - gvcid_managed_parameters_local = gvcid_managed_parameters_local->next; + if(gvcid_managed_parameters==NULL){//case: Global Root Node not Set + gvcid_managed_parameters = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); + gvcid_managed_parameters->tfvn=tfvn; + gvcid_managed_parameters->scid=scid; + gvcid_managed_parameters->vcid=vcid; + gvcid_managed_parameters->has_fecf=has_fecf; + gvcid_managed_parameters->has_segmentation_hdr=has_segmentation_hdr; + gvcid_managed_parameters->next=NULL; + return status; + } else { //Recurse through nodes and add at end + return crypto_config_add_gvcid_managed_parameter_recursion(tfvn, scid, vcid, has_fecf, has_segmentation_hdr,gvcid_managed_parameters); } - gvcid_managed_parameters_local = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); - gvcid_managed_parameters_local->tfvn=tfvn; - gvcid_managed_parameters_local->scid=scid; - gvcid_managed_parameters_local->vcid=vcid; - gvcid_managed_parameters_local->has_fecf=has_fecf; - gvcid_managed_parameters_local->has_segmentation_hdr=has_segmentation_hdr; - gvcid_managed_parameters_local->next=NULL; - if(gvcid_managed_parameters==NULL) - gvcid_managed_parameters = gvcid_managed_parameters_local; +} - return status; +static int32 crypto_config_add_gvcid_managed_parameter_recursion(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr,GvcidManagedParameters_t* managed_parameter) +{ + if(managed_parameter->next!=NULL){ + return crypto_config_add_gvcid_managed_parameter_recursion(tfvn, scid, vcid, has_fecf, has_segmentation_hdr,managed_parameter->next); + } else { + managed_parameter->next = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); + managed_parameter->next->tfvn = tfvn; + managed_parameter->next->scid = scid; + managed_parameter->next->vcid = vcid; + managed_parameter->next->has_fecf = has_fecf; + managed_parameter->next->has_segmentation_hdr = has_segmentation_hdr; + managed_parameter->next->next = NULL; + return OS_SUCCESS; + } } static void Crypto_Local_Config(void) diff --git a/fsw/src/crypto_print.c b/fsw/src/crypto_print.c index e4627014..2ca4ee84 100644 --- a/fsw/src/crypto_print.c +++ b/fsw/src/crypto_print.c @@ -231,4 +231,17 @@ void Crypto_binprint(void *c, size_t n) printf("\n"); } +void Crypto_mpPrint(GvcidManagedParameters_t* managed_parameters) +//Prints the currently configured Managed Parameters +{ + while(managed_parameters != NULL){ + OS_printf("Managed Parameter: \n"); + OS_printf("\t tfvn: %d", managed_parameters->tfvn); + OS_printf("\t scid: %d", managed_parameters->scid); + OS_printf("\t vcid: %d", managed_parameters->vcid); + OS_printf("\t has_fecf: %d", managed_parameters->has_fecf); + OS_printf("\t has_segmentation_headers: %d\n", managed_parameters->has_segmentation_hdr); + managed_parameters = managed_parameters->next; + } +} #endif \ No newline at end of file From 1c1696d82aea07b286e7731a396dd1a2763d5058 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 8 Dec 2021 16:13:31 -0800 Subject: [PATCH 055/184] Fix unit tests failures with managed parameter changes --- fsw/crypto_util/app/ut_tc_apply.c | 289 +- fsw/public_inc/crypto.h | 10 +- fsw/public_inc/crypto_error.h | 83 +- fsw/public_inc/crypto_print.h | 2 +- fsw/src/crypto.c | 8396 +++++++++++++++-------------- fsw/src/crypto_print.c | 8 +- 6 files changed, 4419 insertions(+), 4369 deletions(-) diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c index f0f9d627..88982a44 100644 --- a/fsw/crypto_util/app/ut_tc_apply.c +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -1,141 +1,148 @@ -/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - - This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not - limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness - for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or - any warranty that the software will be error free. - - In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, - contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder. - - ITC Team - NASA IV&V - jstar-development-team@mail.nasa.gov -*/ - -/* - * Unit Tests that macke use of TC_ApplySecurity function on the data. - */ -#include "ut_tc_apply.h" -#include "utest.h" -#include "crypto.h" -#include "crypto_error.h" - -// TODO: Should this be set up with a set of tests, or continue to Crypto_Init() each time. For now I think the current setup is the best path. - -// Inactive SA Database -// TODO: Should this return or continue to function as currently written when SA is not initalized? -// TODO: I don't believe Crypto Init is cleaned up between each test. I am fairly certain that the init persists between tests. - -// TODO: Need to cherry-pick Crypto_reInit functionality to use between each of these tests -UTEST(TC_APPLY_SECURITY, NO_CRYPTO_INIT) -{ - // No Crypto_Init(); - long buffer_size = 0; - char *raw_tc_sdls_ping_h = "20030015001880d2c70008197f0b00310000b1fe3128"; - uint8 *raw_tc_sdls_ping_b = NULL; - int raw_tc_sdls_ping_len = 0; - - hex_conversion(raw_tc_sdls_ping_h, &raw_tc_sdls_ping_b, &raw_tc_sdls_ping_len); - - uint8 *ptr_enc_frame = NULL; - uint16 enc_frame_len = 0; - int32 return_val = CRYPTO_LIB_ERROR; - - return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(CRYPTO_LIB_ERR_NO_INIT, return_val); - free(raw_tc_sdls_ping_b); -} - -// Nominal Test. This should read a raw_tc_sdls_ping.dat file, continue down the "happy path", and return CRYPTO_LIB_SUCCESS -UTEST(TC_APPLY_SECURITY, HAPPY_PATH) -{ - //Setup & Initialize CryptoLib - Crypto_Init(); - char *raw_tc_sdls_ping_h = "20030015001880d2c70008197f0b00310000b1fe3128"; - uint8 *raw_tc_sdls_ping_b = NULL; - int raw_tc_sdls_ping_len = 0; - - hex_conversion(raw_tc_sdls_ping_h, &raw_tc_sdls_ping_b, &raw_tc_sdls_ping_len); - - uint8 *ptr_enc_frame = NULL; - uint16 enc_frame_len = 0; - - int32 return_val = CRYPTO_LIB_ERROR; - - return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val); - free(raw_tc_sdls_ping_b); - free(ptr_enc_frame); -} - -// Bad Space Craft ID. This should pass the flawed .dat file, and return CRYPTO_LIB_ERR_INVALID_SCID -UTEST(TC_APPLY_SECURITY, BAD_SPACE_CRAFT_ID) -{ - //Setup & Initialize CryptoLib - Crypto_Init(); - char *raw_tc_sdls_ping_bad_scid_h = "20010015001880d2c70008197f0b00310000b1fe3128"; - uint8 *raw_tc_sdls_ping_bad_scid_b = NULL; - int raw_tc_sdls_ping_bad_scid_len = 0; - - hex_conversion(raw_tc_sdls_ping_bad_scid_h, &raw_tc_sdls_ping_bad_scid_b, &raw_tc_sdls_ping_bad_scid_len); - - uint8 *ptr_enc_frame = NULL; - uint16 enc_frame_len = 0; - - uint32 return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_bad_scid_b, raw_tc_sdls_ping_bad_scid_len, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(CRYPTO_LIB_ERR_INVALID_SCID, return_val); - free(raw_tc_sdls_ping_bad_scid_b); - free(ptr_enc_frame); -} - -UTEST(TC_APPLY_SECURITY, BAD_VIRTUAL_CHANNEL_ID) -{ - //Setup & Initialize CryptoLib - Crypto_Init(); - char *raw_tc_sdls_ping_bad_vcid_h = "20032015001880d2c70008197f0b00310000b1fe3128"; - uint8 *raw_tc_sdls_ping_bad_vcid_b = NULL; - int raw_tc_sdls_ping_bad_vcid_len = 0; - - hex_conversion(raw_tc_sdls_ping_bad_vcid_h, &raw_tc_sdls_ping_bad_vcid_b, &raw_tc_sdls_ping_bad_vcid_len); - - uint8 *ptr_enc_frame = NULL; - uint16 enc_frame_len = 0; - int32 return_val = CRYPTO_LIB_ERROR; - - return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_bad_vcid_b, raw_tc_sdls_ping_bad_vcid_len, &ptr_enc_frame, &enc_frame_len); - ASSERT_EQ(CRYPTO_LIB_ERR_INVALID_VCID, return_val); - free(raw_tc_sdls_ping_bad_vcid_b); - free(ptr_enc_frame); -} - -// This test should test how to handle a null buffer being passed into the ApplySecurity Function. -// Currently this functionality isn't handled properly, and casues a seg-fault. -// TODO: We need to determine how this would return, as it will help in other test cases. -// Should this return the original buffer, a null pointer, OS_ERROR, etc? -UTEST(TC_APPLY_SECURITY, NULL_BUFFER) -{ - //Setup & Initialize CryptoLib - Crypto_Init(); - long buffer_size = 0; - char *buffer = NULL; - uint16 buffer_size_i = (uint16) buffer_size; - - uint8 *ptr_enc_frame = NULL; - uint16 enc_frame_len = 0; - int32 return_val = -1; - - return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); - - ASSERT_EQ(CRYPTO_LIB_ERR_NULL_BUFFER, return_val); -} - -//TODO: -/* What should be returned if something goes wrong with Control Command Flag? - Should a NULL pointer be returned....The original pointer? - We need to decide on this functionality and write a test for this -*/ - -UTEST_MAIN(); +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. + + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov +*/ + +/* + * Unit Tests that macke use of TC_ApplySecurity function on the data. + */ +#include "ut_tc_apply.h" +#include "utest.h" +#include "crypto.h" +#include "crypto_error.h" + +// TODO: Should this be set up with a set of tests, or continue to Crypto_Init() each time. For now I think the current setup is the best path. + +// Inactive SA Database +// TODO: Should this return or continue to function as currently written when SA is not initalized? +// TODO: I don't believe Crypto Init is cleaned up between each test. I am fairly certain that the init persists between tests. + +// TODO: Need to cherry-pick Crypto_reInit functionality to use between each of these tests +UTEST(TC_APPLY_SECURITY, NO_CRYPTO_INIT) +{ + // No Crypto_Init(), but we still Configure It; + long buffer_size = 0; + char *raw_tc_sdls_ping_h = "20030015001880d2c70008197f0b00310000b1fe3128"; + uint8 *raw_tc_sdls_ping_b = NULL; + int raw_tc_sdls_ping_len = 0; + + hex_conversion(raw_tc_sdls_ping_h, &raw_tc_sdls_ping_b, &raw_tc_sdls_ping_len); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE,0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); + + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + int32 return_val = CRYPTO_LIB_ERROR; + + return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len); + ASSERT_EQ(CRYPTO_LIB_ERR_NO_INIT, return_val); + free(raw_tc_sdls_ping_b); + Crypto_Shutdown(); +} + +// Nominal Test. This should read a raw_tc_sdls_ping.dat file, continue down the "happy path", and return CRYPTO_LIB_SUCCESS +UTEST(TC_APPLY_SECURITY, HAPPY_PATH) +{ + //Setup & Initialize CryptoLib + Crypto_Init_Unit_Test(); + char *raw_tc_sdls_ping_h = "20030015000080d2c70008197f0b00310000b1fe3128"; + uint8 *raw_tc_sdls_ping_b = NULL; + int raw_tc_sdls_ping_len = 0; + + hex_conversion(raw_tc_sdls_ping_h, &raw_tc_sdls_ping_b, &raw_tc_sdls_ping_len); + + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + + int32 return_val = CRYPTO_LIB_ERROR; + + return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_b, raw_tc_sdls_ping_len, &ptr_enc_frame, &enc_frame_len); + Crypto_Shutdown(); + free(raw_tc_sdls_ping_b); + free(ptr_enc_frame); + ASSERT_EQ(CRYPTO_LIB_SUCCESS, return_val); +} + +// Bad Space Craft ID. This should pass the flawed .dat file, and return MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND +UTEST(TC_APPLY_SECURITY, BAD_SPACE_CRAFT_ID) +{ + //Setup & Initialize CryptoLib + Crypto_Init_Unit_Test(); + char *raw_tc_sdls_ping_bad_scid_h = "20010015000080d2c70008197f0b00310000b1fe3128"; + uint8 *raw_tc_sdls_ping_bad_scid_b = NULL; + int raw_tc_sdls_ping_bad_scid_len = 0; + + hex_conversion(raw_tc_sdls_ping_bad_scid_h, &raw_tc_sdls_ping_bad_scid_b, &raw_tc_sdls_ping_bad_scid_len); + + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + + uint32 return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_bad_scid_b, raw_tc_sdls_ping_bad_scid_len, &ptr_enc_frame, &enc_frame_len); + free(raw_tc_sdls_ping_bad_scid_b); + free(ptr_enc_frame); + Crypto_Shutdown(); + ASSERT_EQ(MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND, return_val); +} + +UTEST(TC_APPLY_SECURITY, BAD_VIRTUAL_CHANNEL_ID) +{ + //Setup & Initialize CryptoLib + Crypto_Init_Unit_Test(); + char *raw_tc_sdls_ping_bad_vcid_h = "20032015000080d2c70008197f0b00310000b1fe3128"; + uint8 *raw_tc_sdls_ping_bad_vcid_b = NULL; + int raw_tc_sdls_ping_bad_vcid_len = 0; + + hex_conversion(raw_tc_sdls_ping_bad_vcid_h, &raw_tc_sdls_ping_bad_vcid_b, &raw_tc_sdls_ping_bad_vcid_len); + + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + int32 return_val = CRYPTO_LIB_ERROR; + + return_val = Crypto_TC_ApplySecurity(raw_tc_sdls_ping_bad_vcid_b, raw_tc_sdls_ping_bad_vcid_len, &ptr_enc_frame, &enc_frame_len); + free(raw_tc_sdls_ping_bad_vcid_b); + free(ptr_enc_frame); + Crypto_Shutdown(); + ASSERT_EQ(MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND, return_val); +} + +// This test should test how to handle a null buffer being passed into the ApplySecurity Function. +// Currently this functionality isn't handled properly, and casues a seg-fault. +// TODO: We need to determine how this would return, as it will help in other test cases. +// Should this return the original buffer, a null pointer, OS_ERROR, etc? +UTEST(TC_APPLY_SECURITY, NULL_BUFFER) +{ + //Setup & Initialize CryptoLib + Crypto_Init_Unit_Test(); + long buffer_size = 0; + char *buffer = NULL; + uint16 buffer_size_i = (uint16) buffer_size; + + uint8 *ptr_enc_frame = NULL; + uint16 enc_frame_len = 0; + int32 return_val = -1; + + return_val = Crypto_TC_ApplySecurity(buffer, buffer_size_i, &ptr_enc_frame, &enc_frame_len); + + Crypto_Shutdown(); + ASSERT_EQ(CRYPTO_LIB_ERR_NULL_BUFFER, return_val); +} + +//TODO: +/* What should be returned if something goes wrong with Control Command Flag? + Should a NULL pointer be returned....The original pointer? + We need to decide on this functionality and write a test for this +*/ + +UTEST_MAIN(); diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index af64223d..0117b747 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -46,9 +46,13 @@ extern int32 Crypto_Config_MariaDB(char* mysql_username, char* mysql_password, c extern int32 Crypto_Config_Add_Gvcid_Managed_Parameter(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr); // Initialization -extern int32 Crypto_Init(void); //Initialize CryptoLib After Configuration Calls -extern int32 Crypto_Init_With_Configs(CryptoConfig_t* crypto_config_p,GvcidManagedParameters_t* gvcid_managed_parameters_p,SadbMariaDBConfig_t* sadb_mariadb_config_p); //Initialize CryptoLib With Application Defined Configuration -extern int32 Crypto_Init_Unit_Test(void); //Initialize CryptoLib with unit test default Configurations +extern int32 Crypto_Init(void); // Initialize CryptoLib After Configuration Calls +extern int32 Crypto_Init_With_Configs(CryptoConfig_t* crypto_config_p,GvcidManagedParameters_t* gvcid_managed_parameters_p,SadbMariaDBConfig_t* sadb_mariadb_config_p); // Initialize CryptoLib With Application Defined Configuration +extern int32 Crypto_Init_Unit_Test(void); // Initialize CryptoLib with unit test default Configurations + +// Cleanup +extern int32 Crypto_Shutdown(void); // Free all allocated memory + // Telecommand (TC) extern int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ uint8 **pp_enc_frame, uint16 *p_enc_frame_len); diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h index 85e4df45..9432242b 100644 --- a/fsw/public_inc/crypto_error.h +++ b/fsw/public_inc/crypto_error.h @@ -1,41 +1,42 @@ -/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - - This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not - limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness - for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or - any warranty that the software will be error free. - - In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, - contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder. - - ITC Team - NASA IV&V - jstar-development-team@mail.nasa.gov -*/ -#ifndef _crypto_error_h_ -#define _crypto_error_h_ - -#include "sadb_mariadb_error.h" - -#define SADB_INVALID_SADB_TYPE 201 -#define CRYPTO_CONFIGURATION_NOT_COMPLETE 101 -#define CRYPTO_MANAGED_PARAM_CONFIGURATION_NOT_COMPLETE 102 -#define CRYPTO_MARIADB_CONFIGURATION_NOT_COMPLETE 103 -#define MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND 104 - - -#define CRYPTO_LIB_SUCCESS (0) -#define CRYPTO_LIB_ERROR (-1) -#define CRYPTO_LIB_ERR_NO_INIT (-2) -#define CRYPTO_LIB_ERR_INVALID_TFVN (-3) -#define CRYPTO_LIB_ERR_INVALID_SCID (-4) -#define CRYPTO_LIB_ERR_INVALID_VCID (-5) -#define CRYPTO_LIB_ERR_INVALID_MAPID (-6) -#define CRYPTO_LIB_ERR_INVALID_CC_FLAG (-7) -#define CRYPTO_LIB_ERR_NO_OPERATIONAL_SA (-8) -#define CRYPTO_LIB_ERR_NULL_BUFFER (-9) -#define CRYPTO_LIB_ERR_UT_BYTE_MISMATCH (-10) - -#endif //_crypto_error_h_ +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. + + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov +*/ +#ifndef _crypto_error_h_ +#define _crypto_error_h_ + +#include "sadb_mariadb_error.h" + +#define SADB_INVALID_SADB_TYPE 201 +#define CRYPTO_CONFIGURATION_NOT_COMPLETE 101 +#define CRYPTO_MANAGED_PARAM_CONFIGURATION_NOT_COMPLETE 102 +#define CRYPTO_MARIADB_CONFIGURATION_NOT_COMPLETE 103 +#define MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND 104 + + +#define CRYPTO_LIB_SUCCESS (0) +#define CRYPTO_LIB_ERROR (-1) +#define CRYPTO_LIB_ERR_NO_INIT (-2) +#define CRYPTO_LIB_ERR_INVALID_TFVN (-3) +#define CRYPTO_LIB_ERR_INVALID_SCID (-4) +#define CRYPTO_LIB_ERR_INVALID_VCID (-5) +#define CRYPTO_LIB_ERR_INVALID_MAPID (-6) +#define CRYPTO_LIB_ERR_INVALID_CC_FLAG (-7) +#define CRYPTO_LIB_ERR_NO_OPERATIONAL_SA (-8) +#define CRYPTO_LIB_ERR_NULL_BUFFER (-9) +#define CRYPTO_LIB_ERR_UT_BYTE_MISMATCH (-10) +#define CRYPTO_LIB_ERR_NO_CONFIG (-11) + +#endif //_crypto_error_h_ diff --git a/fsw/public_inc/crypto_print.h b/fsw/public_inc/crypto_print.h index 91d35751..01bcc607 100644 --- a/fsw/public_inc/crypto_print.h +++ b/fsw/public_inc/crypto_print.h @@ -36,5 +36,5 @@ void Crypto_ccsdsPrint(CCSDS_t* sdls_frame); void Crypto_saPrint(SecurityAssociation_t* sa); void Crypto_hexprint(void *c, size_t n); void Crypto_binprint(void *c, size_t n); -void Crypto_mpPrint(GvcidManagedParameters_t* managed_parameters); +void Crypto_mpPrint(GvcidManagedParameters_t* managed_parameters,uint8 print_children); #endif diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 0f263fda..c302540c 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -1,4181 +1,4217 @@ -/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. - - This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not - limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness - for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or - any warranty that the software will be error free. - - In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, - arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, - contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, - documentation or services provided hereunder. - - ITC Team - NASA IV&V - jstar-development-team@mail.nasa.gov -*/ -#ifndef _crypto_c_ -#define _crypto_c_ - -/* -** Includes -*/ -#include "crypto.h" -#include "sadb_routine.h" - -// #include "itc_aes128.h" -// #include "itc_gcm128.h" - -#include "crypto_structs.h" -#include "crypto_config_structs.h" -#include "crypto_print.h" -#include "crypto_config.h" -#include "crypto_events.h" -#include "crypto_error.h" - - - -#include - - -/* -** Static Library Declaration -*/ -#ifdef BUILD_STATIC - CFS_MODULE_DECLARE_LIB(crypto); -#endif - -static SadbRoutine sadb_routine = NULL; - -/* -** Static Prototypes -*/ -// Assisting Functions -static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame, SecurityAssociation_t *sa_ptr); -static int32 Crypto_Get_tmLength(int len); -static void Crypto_TM_updatePDU(char* ingest, int len_ingest); -static void Crypto_TM_updateOCF(void); -static void Crypto_Local_Config(void); -static void Crypto_Local_Init(void); -//static int32 Crypto_gcm_err(int gcm_err); -static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window); -static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length); -static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame); -static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest); -static void Crypto_Calc_CRC_Init_Table(void); -static uint16 Crypto_Calc_CRC16(char* data, int size); -// Key Management Functions -static int32 Crypto_Key_OTAR(void); -static int32 Crypto_Key_update(uint8 state); -static int32 Crypto_Key_inventory(char*); -static int32 Crypto_Key_verify(char*,TC_t* tc_frame); -// Security Monitoring & Control Procedure -static int32 Crypto_MC_ping(char* ingest); -static int32 Crypto_MC_status(char* ingest); -static int32 Crypto_MC_dump(char* ingest); -static int32 Crypto_MC_erase(char* ingest); -static int32 Crypto_MC_selftest(char* ingest); -static int32 Crypto_SA_readARSN(char* ingest); -static int32 Crypto_MC_resetalarm(void); -// User Functions -static int32 Crypto_User_IdleTrigger(char* ingest); -static int32 Crypto_User_BadSPI(void); -static int32 Crypto_User_BadIV(void); -static int32 Crypto_User_BadMAC(void); -static int32 Crypto_User_BadFECF(void); -static int32 Crypto_User_ModifyKey(void); -static int32 Crypto_User_ModifyActiveTM(void); -static int32 Crypto_User_ModifyVCID(void); -// Determine Payload Data Unit -static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); -// Managed Parameter Functions -static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, - GvcidManagedParameters_t** managed_parameters_out); -static int32 crypto_config_add_gvcid_managed_parameter_recursion(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr,GvcidManagedParameters_t* managed_parameter); -static void Crypto_Free_Managed_Parameters(GvcidManagedParameters_t* managed_parameters); - -/* -** Global Variables -*/ -// Security -crypto_key_t ek_ring[NUM_KEYS] = {0}; -//static crypto_key_t ak_ring[NUM_KEYS]; -CCSDS_t sdls_frame; -TM_t tm_frame; -CryptoConfig_t* crypto_config = NULL; -SadbMariaDBConfig_t* sadb_mariadb_config = NULL; -GvcidManagedParameters_t* gvcid_managed_parameters = NULL; -GvcidManagedParameters_t* current_managed_parameters = NULL; -// OCF -static uint8 ocf = 0; -static SDLS_FSR_t report; -static TM_FrameCLCW_t clcw; -// Flags -static SDLS_MC_LOG_RPLY_t log_summary; -static SDLS_MC_DUMP_BLK_RPLY_t log; -static uint8 log_count = 0; -static uint16 tm_offset = 0; -// ESA Testing - 0 = disabled, 1 = enabled -static uint8 badSPI = 0; -static uint8 badIV = 0; -static uint8 badMAC = 0; -static uint8 badFECF = 0; -// CRC -static uint32 crc32Table[256]; -static uint16 crc16Table[256]; -/* -** Initialization Functions -*/ -int32 Crypto_Init_Unit_Test(void) -{ - int32 status = OS_SUCCESS; - Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE,0x3F); - Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); - status = Crypto_Init(); - return status; -} -int32 Crypto_Init_With_Configs(CryptoConfig_t* crypto_config_p,GvcidManagedParameters_t* gvcid_managed_parameters_p,SadbMariaDBConfig_t* sadb_mariadb_config_p) -{ - int32 status = OS_SUCCESS; - crypto_config = crypto_config_p; - gvcid_managed_parameters = gvcid_managed_parameters_p; - sadb_mariadb_config = sadb_mariadb_config_p; - status = Crypto_Init(); - return status; -} - -int32 Crypto_Init(void) -{ - int32 status = OS_SUCCESS; - - if(crypto_config==NULL){ - status = CRYPTO_CONFIGURATION_NOT_COMPLETE; - OS_printf(KRED "ERROR: CryptoLib must be configured before intializing!\n" RESET); - return status; //No configuration set -- return! - } - if(gvcid_managed_parameters==NULL){ - status = CRYPTO_MANAGED_PARAM_CONFIGURATION_NOT_COMPLETE; - OS_printf(KRED "ERROR: CryptoLib Managed Parameters must be configured before intializing!\n" RESET); - return status; //No Managed Parameter configuration set -- return! - } - - #ifdef TC_DEBUG - Crypto_mpPrint(gvcid_managed_parameters); - #endif - - //Prepare SADB type from config - if (crypto_config->sadb_type == SADB_TYPE_INMEMORY){ sadb_routine = get_sadb_routine_inmemory(); } - else if (crypto_config->sadb_type == SADB_TYPE_MARIADB){ - if(sadb_mariadb_config == NULL){ - status = CRYPTO_MARIADB_CONFIGURATION_NOT_COMPLETE; - OS_printf(KRED "ERROR: CryptoLib MariaDB must be configured before intializing!\n" RESET); - return status; //MariaDB connection specified but no configuration exists, return! - } - sadb_routine = get_sadb_routine_mariadb(); - } - else { status = SADB_INVALID_SADB_TYPE; return status; } //TODO: Error stack - - // Initialize libgcrypt - if (!gcry_check_version(GCRYPT_VERSION)) - { - fprintf(stderr, "Gcrypt Version: %s",GCRYPT_VERSION); - OS_printf(KRED "\tERROR: gcrypt version mismatch! \n" RESET); - } - if (gcry_control(GCRYCTL_SELFTEST) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcrypt self test failed\n" RESET); - } - gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); - - // Init Security Associations - status = sadb_routine->sadb_init(); - status = sadb_routine->sadb_config(); - - Crypto_Local_Init(); - Crypto_Local_Config(); - - // TODO - Add error checking - - // Init table for CRC calculations - Crypto_Calc_CRC_Init_Table(); - - // cFS Standard Initialized Message - OS_printf (KBLU "Crypto Lib Intialized. Version %d.%d.%d.%d\n" RESET, - CRYPTO_LIB_MAJOR_VERSION, - CRYPTO_LIB_MINOR_VERSION, - CRYPTO_LIB_REVISION, - CRYPTO_LIB_MISSION_REV); - - return status; -} - -int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 process_sdls_pdus, uint8 has_pus_hdr, uint8 ignore_sa_state, uint8 ignore_anti_replay, uint8 vcid_bitmask) -{ - int32 status = OS_SUCCESS; - crypto_config = (CryptoConfig_t*) calloc(1, CRYPTO_CONFIG_SIZE); - crypto_config->sadb_type=sadb_type; - crypto_config->crypto_create_fecf=crypto_create_fecf; - crypto_config->process_sdls_pdus=process_sdls_pdus; - crypto_config->has_pus_hdr=has_pus_hdr; - crypto_config->ignore_sa_state=ignore_sa_state; - crypto_config->ignore_anti_replay=ignore_anti_replay; - crypto_config->vcid_bitmask=vcid_bitmask; - return status; -} -int32 Crypto_Config_MariaDB(char* mysql_username, char* mysql_password, char* mysql_hostname, char* mysql_database, uint16 mysql_port) -{ - int32 status = OS_SUCCESS; - sadb_mariadb_config = (SadbMariaDBConfig_t*)calloc(1, SADB_MARIADB_CONFIG_SIZE); - sadb_mariadb_config->mysql_username=mysql_username; - sadb_mariadb_config->mysql_password=mysql_password; - sadb_mariadb_config->mysql_hostname=mysql_hostname; - sadb_mariadb_config->mysql_database=mysql_database; - sadb_mariadb_config->mysql_port=mysql_port; - return status; -} -int32 Crypto_Config_Add_Gvcid_Managed_Parameter(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr) -{ - int32 status = OS_SUCCESS; - - if(gvcid_managed_parameters==NULL){//case: Global Root Node not Set - gvcid_managed_parameters = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); - gvcid_managed_parameters->tfvn=tfvn; - gvcid_managed_parameters->scid=scid; - gvcid_managed_parameters->vcid=vcid; - gvcid_managed_parameters->has_fecf=has_fecf; - gvcid_managed_parameters->has_segmentation_hdr=has_segmentation_hdr; - gvcid_managed_parameters->next=NULL; - return status; - } else { //Recurse through nodes and add at end - return crypto_config_add_gvcid_managed_parameter_recursion(tfvn, scid, vcid, has_fecf, has_segmentation_hdr,gvcid_managed_parameters); - } - -} - -static int32 crypto_config_add_gvcid_managed_parameter_recursion(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr,GvcidManagedParameters_t* managed_parameter) -{ - if(managed_parameter->next!=NULL){ - return crypto_config_add_gvcid_managed_parameter_recursion(tfvn, scid, vcid, has_fecf, has_segmentation_hdr,managed_parameter->next); - } else { - managed_parameter->next = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); - managed_parameter->next->tfvn = tfvn; - managed_parameter->next->scid = scid; - managed_parameter->next->vcid = vcid; - managed_parameter->next->has_fecf = has_fecf; - managed_parameter->next->has_segmentation_hdr = has_segmentation_hdr; - managed_parameter->next->next = NULL; - return OS_SUCCESS; - } -} - -static void Crypto_Local_Config(void) -{ - // Initial TM configuration - tm_frame.tm_sec_header.spi = 1; - - // Initialize Log - log_summary.num_se = 2; - log_summary.rs = LOG_SIZE; - // Add a two messages to the log - log_summary.rs--; - log.blk[log_count].emt = STARTUP; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - log_summary.rs--; - log.blk[log_count].emt = STARTUP; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - - // Master Keys - // 0 - 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F -> ACTIVE - ek_ring[0].value[0] = 0x00; - ek_ring[0].value[1] = 0x01; - ek_ring[0].value[2] = 0x02; - ek_ring[0].value[3] = 0x03; - ek_ring[0].value[4] = 0x04; - ek_ring[0].value[5] = 0x05; - ek_ring[0].value[6] = 0x06; - ek_ring[0].value[7] = 0x07; - ek_ring[0].value[8] = 0x08; - ek_ring[0].value[9] = 0x09; - ek_ring[0].value[10] = 0x0A; - ek_ring[0].value[11] = 0x0B; - ek_ring[0].value[12] = 0x0C; - ek_ring[0].value[13] = 0x0D; - ek_ring[0].value[14] = 0x0E; - ek_ring[0].value[15] = 0x0F; - ek_ring[0].value[16] = 0x00; - ek_ring[0].value[17] = 0x01; - ek_ring[0].value[18] = 0x02; - ek_ring[0].value[19] = 0x03; - ek_ring[0].value[20] = 0x04; - ek_ring[0].value[21] = 0x05; - ek_ring[0].value[22] = 0x06; - ek_ring[0].value[23] = 0x07; - ek_ring[0].value[24] = 0x08; - ek_ring[0].value[25] = 0x09; - ek_ring[0].value[26] = 0x0A; - ek_ring[0].value[27] = 0x0B; - ek_ring[0].value[28] = 0x0C; - ek_ring[0].value[29] = 0x0D; - ek_ring[0].value[30] = 0x0E; - ek_ring[0].value[31] = 0x0F; - ek_ring[0].key_state = KEY_ACTIVE; - // 1 - 101112131415161718191A1B1C1D1E1F101112131415161718191A1B1C1D1E1F -> ACTIVE - ek_ring[1].value[0] = 0x10; - ek_ring[1].value[1] = 0x11; - ek_ring[1].value[2] = 0x12; - ek_ring[1].value[3] = 0x13; - ek_ring[1].value[4] = 0x14; - ek_ring[1].value[5] = 0x15; - ek_ring[1].value[6] = 0x16; - ek_ring[1].value[7] = 0x17; - ek_ring[1].value[8] = 0x18; - ek_ring[1].value[9] = 0x19; - ek_ring[1].value[10] = 0x1A; - ek_ring[1].value[11] = 0x1B; - ek_ring[1].value[12] = 0x1C; - ek_ring[1].value[13] = 0x1D; - ek_ring[1].value[14] = 0x1E; - ek_ring[1].value[15] = 0x1F; - ek_ring[1].value[16] = 0x10; - ek_ring[1].value[17] = 0x11; - ek_ring[1].value[18] = 0x12; - ek_ring[1].value[19] = 0x13; - ek_ring[1].value[20] = 0x14; - ek_ring[1].value[21] = 0x15; - ek_ring[1].value[22] = 0x16; - ek_ring[1].value[23] = 0x17; - ek_ring[1].value[24] = 0x18; - ek_ring[1].value[25] = 0x19; - ek_ring[1].value[26] = 0x1A; - ek_ring[1].value[27] = 0x1B; - ek_ring[1].value[28] = 0x1C; - ek_ring[1].value[29] = 0x1D; - ek_ring[1].value[30] = 0x1E; - ek_ring[1].value[31] = 0x1F; - ek_ring[1].key_state = KEY_ACTIVE; - // 2 - 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F -> ACTIVE - ek_ring[2].value[0] = 0x20; - ek_ring[2].value[1] = 0x21; - ek_ring[2].value[2] = 0x22; - ek_ring[2].value[3] = 0x23; - ek_ring[2].value[4] = 0x24; - ek_ring[2].value[5] = 0x25; - ek_ring[2].value[6] = 0x26; - ek_ring[2].value[7] = 0x27; - ek_ring[2].value[8] = 0x28; - ek_ring[2].value[9] = 0x29; - ek_ring[2].value[10] = 0x2A; - ek_ring[2].value[11] = 0x2B; - ek_ring[2].value[12] = 0x2C; - ek_ring[2].value[13] = 0x2D; - ek_ring[2].value[14] = 0x2E; - ek_ring[2].value[15] = 0x2F; - ek_ring[2].value[16] = 0x20; - ek_ring[2].value[17] = 0x21; - ek_ring[2].value[18] = 0x22; - ek_ring[2].value[19] = 0x23; - ek_ring[2].value[20] = 0x24; - ek_ring[2].value[21] = 0x25; - ek_ring[2].value[22] = 0x26; - ek_ring[2].value[23] = 0x27; - ek_ring[2].value[24] = 0x28; - ek_ring[2].value[25] = 0x29; - ek_ring[2].value[26] = 0x2A; - ek_ring[2].value[27] = 0x2B; - ek_ring[2].value[28] = 0x2C; - ek_ring[2].value[29] = 0x2D; - ek_ring[2].value[30] = 0x2E; - ek_ring[2].value[31] = 0x2F; - ek_ring[2].key_state = KEY_ACTIVE; - - // Session Keys - // 128 - 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -> ACTIVE - ek_ring[128].value[0] = 0x01; - ek_ring[128].value[1] = 0x23; - ek_ring[128].value[2] = 0x45; - ek_ring[128].value[3] = 0x67; - ek_ring[128].value[4] = 0x89; - ek_ring[128].value[5] = 0xAB; - ek_ring[128].value[6] = 0xCD; - ek_ring[128].value[7] = 0xEF; - ek_ring[128].value[8] = 0x01; - ek_ring[128].value[9] = 0x23; - ek_ring[128].value[10] = 0x45; - ek_ring[128].value[11] = 0x67; - ek_ring[128].value[12] = 0x89; - ek_ring[128].value[13] = 0xAB; - ek_ring[128].value[14] = 0xCD; - ek_ring[128].value[15] = 0xEF; - ek_ring[128].value[16] = 0x01; - ek_ring[128].value[17] = 0x23; - ek_ring[128].value[18] = 0x45; - ek_ring[128].value[19] = 0x67; - ek_ring[128].value[20] = 0x89; - ek_ring[128].value[21] = 0xAB; - ek_ring[128].value[22] = 0xCD; - ek_ring[128].value[23] = 0xEF; - ek_ring[128].value[24] = 0x01; - ek_ring[128].value[25] = 0x23; - ek_ring[128].value[26] = 0x45; - ek_ring[128].value[27] = 0x67; - ek_ring[128].value[28] = 0x89; - ek_ring[128].value[29] = 0xAB; - ek_ring[128].value[30] = 0xCD; - ek_ring[128].value[31] = 0xEF; - ek_ring[128].key_state = KEY_ACTIVE; - // 129 - ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 -> ACTIVE - ek_ring[129].value[0] = 0xAB; - ek_ring[129].value[1] = 0xCD; - ek_ring[129].value[2] = 0xEF; - ek_ring[129].value[3] = 0x01; - ek_ring[129].value[4] = 0x23; - ek_ring[129].value[5] = 0x45; - ek_ring[129].value[6] = 0x67; - ek_ring[129].value[7] = 0x89; - ek_ring[129].value[8] = 0xAB; - ek_ring[129].value[9] = 0xCD; - ek_ring[129].value[10] = 0xEF; - ek_ring[129].value[11] = 0x01; - ek_ring[129].value[12] = 0x23; - ek_ring[129].value[13] = 0x45; - ek_ring[129].value[14] = 0x67; - ek_ring[129].value[15] = 0x89; - ek_ring[129].value[16] = 0xAB; - ek_ring[129].value[17] = 0xCD; - ek_ring[129].value[18] = 0xEF; - ek_ring[129].value[19] = 0x01; - ek_ring[129].value[20] = 0x23; - ek_ring[129].value[21] = 0x45; - ek_ring[129].value[22] = 0x67; - ek_ring[129].value[23] = 0x89; - ek_ring[129].value[24] = 0xAB; - ek_ring[129].value[25] = 0xCD; - ek_ring[129].value[26] = 0xEF; - ek_ring[129].value[27] = 0x01; - ek_ring[129].value[28] = 0x23; - ek_ring[129].value[29] = 0x45; - ek_ring[129].value[30] = 0x67; - ek_ring[129].value[31] = 0x89; - ek_ring[129].key_state = KEY_ACTIVE; - // 130 - FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210 -> ACTIVE - ek_ring[130].value[0] = 0xFE; - ek_ring[130].value[1] = 0xDC; - ek_ring[130].value[2] = 0xBA; - ek_ring[130].value[3] = 0x98; - ek_ring[130].value[4] = 0x76; - ek_ring[130].value[5] = 0x54; - ek_ring[130].value[6] = 0x32; - ek_ring[130].value[7] = 0x10; - ek_ring[130].value[8] = 0xFE; - ek_ring[130].value[9] = 0xDC; - ek_ring[130].value[10] = 0xBA; - ek_ring[130].value[11] = 0x98; - ek_ring[130].value[12] = 0x76; - ek_ring[130].value[13] = 0x54; - ek_ring[130].value[14] = 0x32; - ek_ring[130].value[15] = 0x10; - ek_ring[130].value[16] = 0xFE; - ek_ring[130].value[17] = 0xDC; - ek_ring[130].value[18] = 0xBA; - ek_ring[130].value[19] = 0x98; - ek_ring[130].value[20] = 0x76; - ek_ring[130].value[21] = 0x54; - ek_ring[130].value[22] = 0x32; - ek_ring[130].value[23] = 0x10; - ek_ring[130].value[24] = 0xFE; - ek_ring[130].value[25] = 0xDC; - ek_ring[130].value[26] = 0xBA; - ek_ring[130].value[27] = 0x98; - ek_ring[130].value[28] = 0x76; - ek_ring[130].value[29] = 0x54; - ek_ring[130].value[30] = 0x32; - ek_ring[130].value[31] = 0x10; - ek_ring[130].key_state = KEY_ACTIVE; - // 131 - 9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA -> ACTIVE - ek_ring[131].value[0] = 0x98; - ek_ring[131].value[1] = 0x76; - ek_ring[131].value[2] = 0x54; - ek_ring[131].value[3] = 0x32; - ek_ring[131].value[4] = 0x10; - ek_ring[131].value[5] = 0xFE; - ek_ring[131].value[6] = 0xDC; - ek_ring[131].value[7] = 0xBA; - ek_ring[131].value[8] = 0x98; - ek_ring[131].value[9] = 0x76; - ek_ring[131].value[10] = 0x54; - ek_ring[131].value[11] = 0x32; - ek_ring[131].value[12] = 0x10; - ek_ring[131].value[13] = 0xFE; - ek_ring[131].value[14] = 0xDC; - ek_ring[131].value[15] = 0xBA; - ek_ring[131].value[16] = 0x98; - ek_ring[131].value[17] = 0x76; - ek_ring[131].value[18] = 0x54; - ek_ring[131].value[19] = 0x32; - ek_ring[131].value[20] = 0x10; - ek_ring[131].value[21] = 0xFE; - ek_ring[131].value[22] = 0xDC; - ek_ring[131].value[23] = 0xBA; - ek_ring[131].value[24] = 0x98; - ek_ring[131].value[25] = 0x76; - ek_ring[131].value[26] = 0x54; - ek_ring[131].value[27] = 0x32; - ek_ring[131].value[28] = 0x10; - ek_ring[131].value[29] = 0xFE; - ek_ring[131].value[30] = 0xDC; - ek_ring[131].value[31] = 0xBA; - ek_ring[131].key_state = KEY_ACTIVE; - // 132 - 0123456789ABCDEFABCDEF01234567890123456789ABCDEFABCDEF0123456789 -> PRE_ACTIVATION - ek_ring[132].value[0] = 0x01; - ek_ring[132].value[1] = 0x23; - ek_ring[132].value[2] = 0x45; - ek_ring[132].value[3] = 0x67; - ek_ring[132].value[4] = 0x89; - ek_ring[132].value[5] = 0xAB; - ek_ring[132].value[6] = 0xCD; - ek_ring[132].value[7] = 0xEF; - ek_ring[132].value[8] = 0xAB; - ek_ring[132].value[9] = 0xCD; - ek_ring[132].value[10] = 0xEF; - ek_ring[132].value[11] = 0x01; - ek_ring[132].value[12] = 0x23; - ek_ring[132].value[13] = 0x45; - ek_ring[132].value[14] = 0x67; - ek_ring[132].value[15] = 0x89; - ek_ring[132].value[16] = 0x01; - ek_ring[132].value[17] = 0x23; - ek_ring[132].value[18] = 0x45; - ek_ring[132].value[19] = 0x67; - ek_ring[132].value[20] = 0x89; - ek_ring[132].value[21] = 0xAB; - ek_ring[132].value[22] = 0xCD; - ek_ring[132].value[23] = 0xEF; - ek_ring[132].value[24] = 0xAB; - ek_ring[132].value[25] = 0xCD; - ek_ring[132].value[26] = 0xEF; - ek_ring[132].value[27] = 0x01; - ek_ring[132].value[28] = 0x23; - ek_ring[132].value[29] = 0x45; - ek_ring[132].value[30] = 0x67; - ek_ring[132].value[31] = 0x89; - ek_ring[132].key_state = KEY_PREACTIVE; - // 133 - ABCDEF01234567890123456789ABCDEFABCDEF01234567890123456789ABCDEF -> ACTIVE - ek_ring[133].value[0] = 0xAB; - ek_ring[133].value[1] = 0xCD; - ek_ring[133].value[2] = 0xEF; - ek_ring[133].value[3] = 0x01; - ek_ring[133].value[4] = 0x23; - ek_ring[133].value[5] = 0x45; - ek_ring[133].value[6] = 0x67; - ek_ring[133].value[7] = 0x89; - ek_ring[133].value[8] = 0x01; - ek_ring[133].value[9] = 0x23; - ek_ring[133].value[10] = 0x45; - ek_ring[133].value[11] = 0x67; - ek_ring[133].value[12] = 0x89; - ek_ring[133].value[13] = 0xAB; - ek_ring[133].value[14] = 0xCD; - ek_ring[133].value[15] = 0xEF; - ek_ring[133].value[16] = 0xAB; - ek_ring[133].value[17] = 0xCD; - ek_ring[133].value[18] = 0xEF; - ek_ring[133].value[19] = 0x01; - ek_ring[133].value[20] = 0x23; - ek_ring[133].value[21] = 0x45; - ek_ring[133].value[22] = 0x67; - ek_ring[133].value[23] = 0x89; - ek_ring[133].value[24] = 0x01; - ek_ring[133].value[25] = 0x23; - ek_ring[133].value[26] = 0x45; - ek_ring[133].value[27] = 0x67; - ek_ring[133].value[28] = 0x89; - ek_ring[133].value[29] = 0xAB; - ek_ring[133].value[30] = 0xCD; - ek_ring[133].value[31] = 0xEF; - ek_ring[133].key_state = KEY_ACTIVE; - // 134 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE - ek_ring[134].value[0] = 0xAB; - ek_ring[134].value[1] = 0xCD; - ek_ring[134].value[2] = 0xEF; - ek_ring[134].value[3] = 0x01; - ek_ring[134].value[4] = 0x23; - ek_ring[134].value[5] = 0x45; - ek_ring[134].value[6] = 0x67; - ek_ring[134].value[7] = 0x89; - ek_ring[134].value[8] = 0xFE; - ek_ring[134].value[9] = 0xDC; - ek_ring[134].value[10] = 0xBA; - ek_ring[134].value[11] = 0x98; - ek_ring[134].value[12] = 0x76; - ek_ring[134].value[13] = 0x54; - ek_ring[134].value[14] = 0x32; - ek_ring[134].value[15] = 0x10; - ek_ring[134].value[16] = 0xAB; - ek_ring[134].value[17] = 0xCD; - ek_ring[134].value[18] = 0xEF; - ek_ring[134].value[19] = 0x01; - ek_ring[134].value[20] = 0x23; - ek_ring[134].value[21] = 0x45; - ek_ring[134].value[22] = 0x67; - ek_ring[134].value[23] = 0x89; - ek_ring[134].value[24] = 0xFE; - ek_ring[134].value[25] = 0xDC; - ek_ring[134].value[26] = 0xBA; - ek_ring[134].value[27] = 0x98; - ek_ring[134].value[28] = 0x76; - ek_ring[134].value[29] = 0x54; - ek_ring[134].value[30] = 0x32; - ek_ring[134].value[31] = 0x10; - ek_ring[134].key_state = KEY_DEACTIVATED; - - // 135 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE - ek_ring[135].value[0] = 0x00; - ek_ring[135].value[1] = 0x00; - ek_ring[135].value[2] = 0x00; - ek_ring[135].value[3] = 0x00; - ek_ring[135].value[4] = 0x00; - ek_ring[135].value[5] = 0x00; - ek_ring[135].value[6] = 0x00; - ek_ring[135].value[7] = 0x00; - ek_ring[135].value[8] = 0x00; - ek_ring[135].value[9] = 0x00; - ek_ring[135].value[10] = 0x00; - ek_ring[135].value[11] = 0x00; - ek_ring[135].value[12] = 0x00; - ek_ring[135].value[13] = 0x00; - ek_ring[135].value[14] = 0x00; - ek_ring[135].value[15] = 0x00; - ek_ring[135].value[16] = 0x00; - ek_ring[135].value[17] = 0x00; - ek_ring[135].value[18] = 0x00; - ek_ring[135].value[19] = 0x00; - ek_ring[135].value[20] = 0x00; - ek_ring[135].value[21] = 0x00; - ek_ring[135].value[22] = 0x00; - ek_ring[135].value[23] = 0x00; - ek_ring[135].value[24] = 0x00; - ek_ring[135].value[25] = 0x00; - ek_ring[135].value[26] = 0x00; - ek_ring[135].value[27] = 0x00; - ek_ring[135].value[28] = 0x00; - ek_ring[135].value[29] = 0x00; - ek_ring[135].value[30] = 0x00; - ek_ring[135].value[31] = 0x00; - ek_ring[135].key_state = KEY_DEACTIVATED; - - // 136 - ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8 - // Reference: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/gcmtestvectors.zip - ek_ring[136].value[0] = 0xff; - ek_ring[136].value[1] = 0x9f; - ek_ring[136].value[2] = 0x92; - ek_ring[136].value[3] = 0x84; - ek_ring[136].value[4] = 0xcf; - ek_ring[136].value[5] = 0x59; - ek_ring[136].value[6] = 0x9e; - ek_ring[136].value[7] = 0xac; - ek_ring[136].value[8] = 0x3b; - ek_ring[136].value[9] = 0x11; - ek_ring[136].value[10] = 0x99; - ek_ring[136].value[11] = 0x05; - ek_ring[136].value[12] = 0xa7; - ek_ring[136].value[13] = 0xd1; - ek_ring[136].value[14] = 0x88; - ek_ring[136].value[15] = 0x51; - ek_ring[136].value[16] = 0xe7; - ek_ring[136].value[17] = 0xe3; - ek_ring[136].value[18] = 0x74; - ek_ring[136].value[19] = 0xcf; - ek_ring[136].value[20] = 0x63; - ek_ring[136].value[21] = 0xae; - ek_ring[136].value[22] = 0xa0; - ek_ring[136].value[23] = 0x43; - ek_ring[136].value[24] = 0x58; - ek_ring[136].value[25] = 0x58; - ek_ring[136].value[26] = 0x6b; - ek_ring[136].value[27] = 0x0f; - ek_ring[136].value[28] = 0x75; - ek_ring[136].value[29] = 0x76; - ek_ring[136].value[30] = 0x70; - ek_ring[136].value[31] = 0xf9; - ek_ring[135].key_state = KEY_DEACTIVATED; -} - -static void Crypto_Local_Init(void) -{ - - // Initialize TM Frame - // TM Header - tm_frame.tm_header.tfvn = 0; // Shall be 00 for TM-/TC-SDLP - tm_frame.tm_header.scid = SCID & 0x3FF; - tm_frame.tm_header.vcid = 0; - tm_frame.tm_header.ocff = 1; - tm_frame.tm_header.mcfc = 1; - tm_frame.tm_header.vcfc = 1; - tm_frame.tm_header.tfsh = 0; - tm_frame.tm_header.sf = 0; - tm_frame.tm_header.pof = 0; // Shall be set to 0 - tm_frame.tm_header.slid = 3; // Shall be set to 11 - tm_frame.tm_header.fhp = 0; - // TM Security Header - tm_frame.tm_sec_header.spi = 0x0000; - for ( int x = 0; x < IV_SIZE; x++) - { // Initialization Vector - tm_frame.tm_sec_header.iv[x] = 0x00; - } - // TM Payload Data Unit - for ( int x = 0; x < TM_FRAME_DATA_SIZE; x++) - { // Zero TM PDU - tm_frame.tm_pdu[x] = 0x00; - } - // TM Security Trailer - for ( int x = 0; x < MAC_SIZE; x++) - { // Zero TM Message Authentication Code - tm_frame.tm_sec_trailer.mac[x] = 0x00; - } - for ( int x = 0; x < OCF_SIZE; x++) - { // Zero TM Operational Control Field - tm_frame.tm_sec_trailer.ocf[x] = 0x00; - } - tm_frame.tm_sec_trailer.fecf = 0xFECF; - - // Initialize CLCW - clcw.cwt = 0; // Control Word Type "0" - clcw.cvn = 0; // CLCW Version Number "00" - clcw.sf = 0; // Status Field - clcw.cie = 1; // COP In Effect - clcw.vci = 0; // Virtual Channel Identification - clcw.spare0 = 0; // Reserved Spare - clcw.nrfa = 0; // No RF Avaliable Flag - clcw.nbl = 0; // No Bit Lock Flag - clcw.lo = 0; // Lock-Out Flag - clcw.wait = 0; // Wait Flag - clcw.rt = 0; // Retransmit Flag - clcw.fbc = 0; // FARM-B Counter - clcw.spare1 = 0; // Reserved Spare - clcw.rv = 0; // Report Value - - // Initialize Frame Security Report - report.cwt = 1; // Control Word Type "0b1"" - report.vnum = 4; // FSR Version "0b100"" - report.af = 0; // Alarm Field - report.bsnf = 0; // Bad SN Flag - report.bmacf = 0; // Bad MAC Flag - report.ispif = 0; // Invalid SPI Flag - report.lspiu = 0; // Last SPI Used - report.snval = 0; // SN Value (LSB) - -} - -static void Crypto_Calc_CRC_Init_Table(void) -{ - uint16 val; - uint32 poly = 0xEDB88320; - uint32 crc; - - // http://create.stephan-brumme.com/crc32/ - for (unsigned int i = 0; i <= 0xFF; i++) - { - crc = i; - for (unsigned int j = 0; j < 8; j++) - { - crc = (crc >> 1) ^ (-(int)(crc & 1) & poly); - } - crc32Table[i] = crc; - //OS_printf("crc32Table[%d] = 0x%08x \n", i, crc32Table[i]); - } - - // Code provided by ESA - for (int i = 0; i < 256; i++) - { - val = 0; - if ( (i & 1) != 0 ) val ^= 0x1021; - if ( (i & 2) != 0 ) val ^= 0x2042; - if ( (i & 4) != 0 ) val ^= 0x4084; - if ( (i & 8) != 0 ) val ^= 0x8108; - if ( (i & 16) != 0 ) val ^= 0x1231; - if ( (i & 32) != 0 ) val ^= 0x2462; - if ( (i & 64) != 0 ) val ^= 0x48C4; - if ( (i & 128) != 0 ) val ^= 0x9188; - crc16Table[i] = val; - //OS_printf("crc16Table[%d] = 0x%04x \n", i, crc16Table[i]); - } -} - -/* -** Assisting Functions -*/ -static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame, SecurityAssociation_t *sa_ptr) -// Returns the payload length of current tc_frame in BYTES! -{ - int tf_hdr = 5; - int seg_hdr = 0;if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){seg_hdr=1;} - int fecf = 0;if(current_managed_parameters->has_fecf==TC_HAS_FECF){fecf=FECF_SIZE;} - int spi = 2; - int iv_size = sa_ptr->shivf_len; if(crypto_config->has_pus_hdr==TC_HAS_PUS_HDR){iv_size=sa_ptr->shivf_len - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. - int mac_size = sa_ptr->stmacf_len; - - #ifdef TC_DEBUG - OS_printf("Get_tcPayloadLength Debug [byte lengths]:\n"); - OS_printf("\thdr.fl\t%d\n", tc_frame->tc_header.fl); - OS_printf("\ttf_hdr\t%d\n",tf_hdr); - OS_printf("\tSeg hdr\t%d\t\n",seg_hdr); - OS_printf("\tspi \t%d\n",spi); - OS_printf("\tiv_size\t%d\n",iv_size); - OS_printf("\tmac\t%d\n",mac_size); - OS_printf("\tfecf \t%d\n",fecf); - OS_printf("\tTOTAL LENGTH: %d\n", (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + fecf))); - #endif - - return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + fecf) ); -} - -static int32 Crypto_Get_tmLength(int len) -// Returns the total length of the current tm_frame in BYTES! -{ - #ifdef FILL - len = TM_FILL_SIZE; - #else - len = TM_FRAME_PRIMARYHEADER_SIZE + TM_FRAME_SECHEADER_SIZE + len + TM_FRAME_SECTRAILER_SIZE + TM_FRAME_CLCW_SIZE; - #endif - - return len; -} - -static void Crypto_TM_updatePDU(char* ingest, int len_ingest) -// Update the Telemetry Payload Data Unit -{ // Copy ingest to PDU - int x = 0; - int fill_size = 0; - SecurityAssociation_t* sa_ptr; - - if(sadb_routine->sadb_get_sa_from_spi(tm_frame.tm_sec_header.spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - return; //Error -- unable to get SA from SPI. - } - - if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) - { - fill_size = 1129 - MAC_SIZE - IV_SIZE + 2; // +2 for padding bytes - } - else - { - fill_size = 1129; - } - - #ifdef TM_ZERO_FILL - for (int x = 0; x < TM_FILL_SIZE; x++) - { - if (x < len_ingest) - { // Fill - tm_frame.tm_pdu[x] = (uint8)ingest[x]; - } - else - { // Zero - tm_frame.tm_pdu[x] = 0x00; - } - } - #else - // Pre-append remaining packet if exist - if (tm_offset == 63) - { - tm_frame.tm_pdu[x++] = 0xff; - tm_offset--; - } - if (tm_offset == 62) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (tm_offset == 61) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (tm_offset == 60) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (tm_offset == 59) - { - tm_frame.tm_pdu[x++] = 0x39; - tm_offset--; - } - while (x < tm_offset) - { - tm_frame.tm_pdu[x] = 0x00; - x++; - } - // Copy actual packet - while (x < len_ingest + tm_offset) - { - //OS_printf("ingest[x - tm_offset] = 0x%02x \n", (uint8)ingest[x - tm_offset]); - tm_frame.tm_pdu[x] = (uint8)ingest[x - tm_offset]; - x++; - } - #ifdef TM_IDLE_FILL - // Check for idle frame trigger - if (((uint8)ingest[0] == 0x08) && ((uint8)ingest[1] == 0x90)) - { - // Don't fill idle frames - } - else - { - while (x < (fill_size - 64) ) - { - tm_frame.tm_pdu[x++] = 0x07; - tm_frame.tm_pdu[x++] = 0xff; - tm_frame.tm_pdu[x++] = 0x00; - tm_frame.tm_pdu[x++] = 0x00; - tm_frame.tm_pdu[x++] = 0x00; - tm_frame.tm_pdu[x++] = 0x39; - for (int y = 0; y < 58; y++) - { - tm_frame.tm_pdu[x++] = 0x00; - } - } - // Add partial packet, if possible, and set offset - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x07; - tm_offset = 63; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0xff; - tm_offset--; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x00; - tm_offset--; - } - if (x < fill_size) - { - tm_frame.tm_pdu[x++] = 0x39; - tm_offset--; - } - for (int y = 0; x < fill_size; y++) - { - tm_frame.tm_pdu[x++] = 00; - tm_offset--; - } - } - while (x < TM_FILL_SIZE) - { - tm_frame.tm_pdu[x++] = 0x00; - } - #endif - #endif - - return; -} - -static void Crypto_TM_updateOCF(void) -{ - if (ocf == 0) - { // CLCW - clcw.vci = tm_frame.tm_header.vcid; - - tm_frame.tm_sec_trailer.ocf[0] = (clcw.cwt << 7) | (clcw.cvn << 5) | (clcw.sf << 2) | (clcw.cie); - tm_frame.tm_sec_trailer.ocf[1] = (clcw.vci << 2) | (clcw.spare0); - tm_frame.tm_sec_trailer.ocf[2] = (clcw.nrfa << 7) | (clcw.nbl << 6) | (clcw.lo << 5) | (clcw.wait << 4) | (clcw.rt << 3) | (clcw.fbc << 1) | (clcw.spare1); - tm_frame.tm_sec_trailer.ocf[3] = (clcw.rv); - // Alternate OCF - ocf = 1; - #ifdef OCF_DEBUG - Crypto_clcwPrint(&clcw); - #endif - } - else - { // FSR - tm_frame.tm_sec_trailer.ocf[0] = (report.cwt << 7) | (report.vnum << 4) | (report.af << 3) | (report.bsnf << 2) | (report.bmacf << 1) | (report.ispif); - tm_frame.tm_sec_trailer.ocf[1] = (report.lspiu & 0xFF00) >> 8; - tm_frame.tm_sec_trailer.ocf[2] = (report.lspiu & 0x00FF); - tm_frame.tm_sec_trailer.ocf[3] = (report.snval); - // Alternate OCF - ocf = 0; - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - } -} - -//TODO - Review this. Not sure it quite works how we think -int32 Crypto_increment(uint8 *num, int length) -{ - int i; - /* go from right (least significant) to left (most signifcant) */ - for(i = length - 1; i >= 0; --i) - { - ++(num[i]); /* increment current byte */ - - if(num[i] != 0) /* if byte did not overflow, we're done! */ - break; - } - - if(i < 0) /* this means num[0] was incremented and overflowed */ - return OS_ERROR; - else - return OS_SUCCESS; -} - -static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window) -{ - int status = OS_ERROR; - int result = 0; - uint8 temp[length]; - - CFE_PSP_MemCpy(temp, expected, length); - - for (int i = 0; i < window; i++) - { - result = 0; - /* go from right (least significant) to left (most signifcant) */ - for (int j = length - 1; j >= 0; --j) - { - if (actual[j] == temp[j]) - { - result++; - } - } - if (result == length) - { - status = OS_SUCCESS; - break; - } - Crypto_increment(&temp[0], length); - } - return status; -} - -static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length) -{ - int status = OS_ERROR; - - for(int i = 0; i < length - 1; i++) - { - if (actual[i] > expected[i]) - { - status = OS_SUCCESS; - break; - } - else if (actual[i] < expected[i]) - { - status = OS_ERROR; - break; - } - } - return status; -} - -uint8 Crypto_Prep_Reply(char* ingest, uint8 appID) -// Assumes that both the pkt_length and pdu_len are set properly -{ - uint8 count = 0; - - // Prepare CCSDS for reply - sdls_frame.hdr.pvn = 0; - sdls_frame.hdr.type = 0; - sdls_frame.hdr.shdr = 1; - sdls_frame.hdr.appID = appID; - - sdls_frame.pdu.type = 1; - - // Fill ingest with reply header - ingest[count++] = (sdls_frame.hdr.pvn << 5) | (sdls_frame.hdr.type << 4) | (sdls_frame.hdr.shdr << 3) | ((sdls_frame.hdr.appID & 0x700 >> 8)); - ingest[count++] = (sdls_frame.hdr.appID & 0x00FF); - ingest[count++] = (sdls_frame.hdr.seq << 6) | ((sdls_frame.hdr.pktid & 0x3F00) >> 8); - ingest[count++] = (sdls_frame.hdr.pktid & 0x00FF); - ingest[count++] = (sdls_frame.hdr.pkt_length & 0xFF00) >> 8; - ingest[count++] = (sdls_frame.hdr.pkt_length & 0x00FF); - - // Fill ingest with PUS - //ingest[count++] = (sdls_frame.pus.shf << 7) | (sdls_frame.pus.pusv << 4) | (sdls_frame.pus.ack); - //ingest[count++] = (sdls_frame.pus.st); - //ingest[count++] = (sdls_frame.pus.sst); - //ingest[count++] = (sdls_frame.pus.sid << 4) | (sdls_frame.pus.spare); - - // Fill ingest with Tag and Length - ingest[count++] = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | (sdls_frame.pdu.pid); - ingest[count++] = (sdls_frame.pdu.pdu_len & 0xFF00) >> 8; - ingest[count++] = (sdls_frame.pdu.pdu_len & 0x00FF); - - return count; -} - -static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame) -// Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) -{ - int32 result = OS_SUCCESS; - uint16 calc_fecf = Crypto_Calc_FECF(ingest, len_ingest); - - if ( (fecf & 0xFFFF) != calc_fecf ) - { - if (((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) - { - // User packet check only used for ESA Testing! - } - else - { // TODO: Error Correction - OS_printf(KRED "Error: FECF incorrect!\n" RESET); - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = FECF_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - #ifdef FECF_DEBUG - OS_printf("\t Calculated = 0x%04x \n\t Received = 0x%04x \n", calc_fecf, tc_frame->tc_sec_trailer.fecf); - #endif - result = OS_ERROR; - } - } - - return result; -} - -static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest) -// Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) -{ - uint16 fecf = 0xFFFF; - uint16 poly = 0x1021; // TODO: This polynomial is (CRC-CCITT) for ESA testing, may not match standard protocol - uint8 bit; - uint8 c15; - - for (int i = 0; i < len_ingest; i++) - { // Byte Logic - for (int j = 0; j < 8; j++) - { // Bit Logic - bit = ((ingest[i] >> (7 - j) & 1) == 1); - c15 = ((fecf >> 15 & 1) == 1); - fecf <<= 1; - if (c15 ^ bit) - { - fecf ^= poly; - } - } - } - // Check if Testing - if (badFECF == 1) - { - fecf++; - } - - #ifdef FECF_DEBUG - OS_printf(KCYN "Crypto_Calc_FECF: 0x%02x%02x%02x%02x%02x, len_ingest = %d\n" RESET, ingest[0], ingest[1], ingest[2], ingest[3], ingest[4], len_ingest); - OS_printf(KCYN "0x" RESET); - for (int x = 0; x < len_ingest; x++) - { - OS_printf(KCYN "%02x" RESET, (uint8)*(ingest+x)); - } - OS_printf(KCYN "\n" RESET); - OS_printf(KCYN "In Crypto_Calc_FECF! fecf = 0x%04x\n" RESET, fecf); - #endif - - return fecf; -} - -static uint16 Crypto_Calc_CRC16(char* data, int size) -{ // Code provided by ESA - uint16 crc = 0xFFFF; - - for ( ; size > 0; size--) - { - //OS_printf("*data = 0x%02x \n", (uint8) *data); - crc = ((crc << 8) & 0xFF00) ^ crc16Table[(crc >> 8) ^ *data++]; - } - - return crc; -} - -/* -** Key Management Services -*/ -static int32 Crypto_Key_OTAR(void) -// The OTAR Rekeying procedure shall have the following Service Parameters: -// a- Key ID of the Master Key (Integer, unmanaged) -// b- Size of set of Upload Keys (Integer, managed) -// c- Set of Upload Keys (Integer[Session Key]; managed) -// NOTE- The size of the session keys is mission specific. -// a- Set of Key IDs of Upload Keys (Integer[Key IDs]; managed) -// b- Set of Encrypted Upload Keys (Integer[Size of set of Key ID]; unmanaged) -// c- Agreed Cryptographic Algorithm (managed) -{ - // Local variables - SDLS_OTAR_t packet; - int count = 0; - int x = 0; - int32 status = OS_SUCCESS; - int pdu_keys = (sdls_frame.pdu.pdu_len - 30) / (2 + KEY_SIZE); - - gcry_cipher_hd_t tmp_hd; - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - - // Master Key ID - packet.mkid = (sdls_frame.pdu.data[0] << 8) | (sdls_frame.pdu.data[1]); - - if (packet.mkid >= 128) - { - report.af = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = MKID_INVALID_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: MKID is not valid! \n" RESET); - status = OS_ERROR; - return status; - } - - for (int count = 2; count < (2 + IV_SIZE); count++) - { // Initialization Vector - packet.iv[count-2] = sdls_frame.pdu.data[count]; - //OS_printf("packet.iv[%d] = 0x%02x\n", count-2, packet.iv[count-2]); - } - - count = sdls_frame.pdu.pdu_len - MAC_SIZE; - for (int w = 0; w < 16; w++) - { // MAC - packet.mac[w] = sdls_frame.pdu.data[count + w]; - //OS_printf("packet.mac[%d] = 0x%02x\n", w, packet.mac[w]); - } - - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[packet.mkid].value[0]), - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(packet.iv[0]), - IV_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_decrypt( - tmp_hd, - &(sdls_frame.pdu.data[14]), // plaintext output - pdu_keys * (2 + KEY_SIZE), // length of data - NULL, // in place decryption - 0 // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_checktag( - tmp_hd, - &(packet.mac[0]), // tag input - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_cipher_close(tmp_hd); - - // Read in Decrypted Data - for (int count = 14; x < pdu_keys; x++) - { // Encrypted Key Blocks - packet.EKB[x].ekid = (sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1]); - if (packet.EKB[x].ekid < 128) - { - report.af = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = OTAR_MK_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; // N - log.blk[log_count].emv[1] = 0x41; // A - log.blk[log_count].emv[2] = 0x53; // S - log.blk[log_count].emv[3] = 0x41; // A - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: Cannot OTAR master key! \n" RESET); - status = OS_ERROR; - return status; - } - else - { - count = count + 2; - for (int y = count; y < (KEY_SIZE + count); y++) - { // Encrypted Key - packet.EKB[x].ek[y-count] = sdls_frame.pdu.data[y]; - #ifdef SA_DEBUG - OS_printf("\t packet.EKB[%d].ek[%d] = 0x%02x\n", x, y-count, packet.EKB[x].ek[y-count]); - #endif - - // Setup Key Ring - ek_ring[packet.EKB[x].ekid].value[y - count] = sdls_frame.pdu.data[y]; - } - count = count + KEY_SIZE; - - // Set state to PREACTIVE - ek_ring[packet.EKB[x].ekid].key_state = KEY_PREACTIVE; - } - } - - #ifdef PDU_DEBUG - OS_printf("Received %d keys via master key %d: \n", pdu_keys, packet.mkid); - for (int x = 0; x < pdu_keys; x++) - { - OS_printf("%d) Key ID = %d, 0x", x+1, packet.EKB[x].ekid); - for(int y = 0; y < KEY_SIZE; y++) - { - OS_printf("%02x", packet.EKB[x].ek[y]); - } - OS_printf("\n"); - } - #endif - - return OS_SUCCESS; -} - -static int32 Crypto_Key_update(uint8 state) -// Updates the state of the all keys in the received SDLS EP PDU -{ // Local variables - SDLS_KEY_BLK_t packet; - int count = 0; - int pdu_keys = sdls_frame.pdu.pdu_len / 2; - #ifdef PDU_DEBUG - OS_printf("Keys "); - #endif - // Read in PDU - for (int x = 0; x < pdu_keys; x++) - { - packet.kblk[x].kid = (sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1]); - count = count + 2; - #ifdef PDU_DEBUG - if (x != (pdu_keys - 1)) - { - OS_printf("%d, ", packet.kblk[x].kid); - } - else - { - OS_printf("and %d ", packet.kblk[x].kid); - } - #endif - } - #ifdef PDU_DEBUG - OS_printf("changed to state "); - switch (state) - { - case KEY_PREACTIVE: - OS_printf("PREACTIVE. \n"); - break; - case KEY_ACTIVE: - OS_printf("ACTIVE. \n"); - break; - case KEY_DEACTIVATED: - OS_printf("DEACTIVATED. \n"); - break; - case KEY_DESTROYED: - OS_printf("DESTROYED. \n"); - break; - case KEY_CORRUPTED: - OS_printf("CORRUPTED. \n"); - break; - default: - OS_printf("ERROR. \n"); - break; - } - #endif - // Update Key State - for (int x = 0; x < pdu_keys; x++) - { - if (packet.kblk[x].kid < 128) - { - report.af = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = MKID_STATE_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: MKID state cannot be changed! \n" RESET); - // TODO: Exit - } - - if (ek_ring[packet.kblk[x].kid].key_state == (state - 1)) - { - ek_ring[packet.kblk[x].kid].key_state = state; - #ifdef PDU_DEBUG - //OS_printf("Key ID %d state changed to ", packet.kblk[x].kid); - #endif - } - else - { - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = KEY_TRANSITION_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: Key %d cannot transition to desired state! \n" RESET, packet.kblk[x].kid); - } - } - return OS_SUCCESS; -} - -static int32 Crypto_Key_inventory(char* ingest) -{ - // Local variables - SDLS_KEY_INVENTORY_t packet; - int count = 0; - uint16_t range = 0; - - // Read in PDU - packet.kid_first = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); - count = count + 2; - packet.kid_last = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); - count = count + 2; - - // Prepare for Reply - range = packet.kid_last - packet.kid_first; - sdls_frame.pdu.pdu_len = 2 + (range * (2 + 1)); - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - ingest[count++] = (range & 0xFF00) >> 8; - ingest[count++] = (range & 0x00FF); - for (uint16_t x = packet.kid_first; x < packet.kid_last; x++) - { // Key ID - ingest[count++] = (x & 0xFF00) >> 8; - ingest[count++] = (x & 0x00FF); - // Key State - ingest[count++] = ek_ring[x].key_state; - } - return count; -} - -static int32 Crypto_Key_verify(char* ingest,TC_t* tc_frame) -{ - // Local variables - SDLS_KEYV_CMD_t packet; - int count = 0; - int pdu_keys = sdls_frame.pdu.pdu_len / SDLS_KEYV_CMD_BLK_SIZE; - - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - gcry_cipher_hd_t tmp_hd; - uint8 iv_loc; - - //uint8 tmp_mac[MAC_SIZE]; - - #ifdef PDU_DEBUG - OS_printf("Crypto_Key_verify: Requested %d key(s) to verify \n", pdu_keys); - #endif - - // Read in PDU - for (int x = 0; x < pdu_keys; x++) - { - // Key ID - packet.blk[x].kid = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); - count = count + 2; - #ifdef PDU_DEBUG - OS_printf("Crypto_Key_verify: Block %d Key ID is %d \n", x, packet.blk[x].kid); - #endif - // Key Challenge - for (int y = 0; y < CHALLENGE_SIZE; y++) - { - packet.blk[x].challenge[y] = sdls_frame.pdu.data[count++]; - } - #ifdef PDU_DEBUG - OS_printf("\n"); - #endif - } - - // Prepare for Reply - sdls_frame.pdu.pdu_len = pdu_keys * (2 + IV_SIZE + CHALLENGE_SIZE + CHALLENGE_MAC_SIZE); - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - for (int x = 0; x < pdu_keys; x++) - { // Key ID - ingest[count++] = (packet.blk[x].kid & 0xFF00) >> 8; - ingest[count++] = (packet.blk[x].kid & 0x00FF); - - // Initialization Vector - iv_loc = count; - for (int y = 0; y < IV_SIZE; y++) - { - ingest[count++] = tc_frame->tc_sec_header.iv[y]; - } - ingest[count-1] = ingest[count-1] + x + 1; - - // Encrypt challenge - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[packet.blk[x].kid].value[0]), - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(ingest[iv_loc]), - IV_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - gcry_error = gcry_cipher_encrypt( - tmp_hd, - &(ingest[count]), // ciphertext output - CHALLENGE_SIZE, // length of data - &(packet.blk[x].challenge[0]), // plaintext input - CHALLENGE_SIZE // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - count = count + CHALLENGE_SIZE; // Don't forget to increment count! - - gcry_error = gcry_cipher_gettag( - tmp_hd, - &(ingest[count]), // tag output - CHALLENGE_MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_gettag error code %d \n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - count = count + CHALLENGE_MAC_SIZE; // Don't forget to increment count! - - // Copy from tmp_mac into ingest - //for( int y = 0; y < CHALLENGE_MAC_SIZE; y++) - //{ - // ingest[count++] = tmp_mac[y]; - //} - gcry_cipher_close(tmp_hd); - } - - #ifdef PDU_DEBUG - OS_printf("Crypto_Key_verify: Response is %d bytes \n", count); - #endif - - return count; -} - -/* - -/* -** Security Association Monitoring and Control -*/ -static int32 Crypto_MC_ping(char* ingest) -{ - int count = 0; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 0; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - return count; -} - -static int32 Crypto_MC_status(char* ingest) -{ - int count = 0; - - // TODO: Update log_summary.rs; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 2; // 4 - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - // PDU - //ingest[count++] = (log_summary.num_se & 0xFF00) >> 8; - ingest[count++] = (log_summary.num_se & 0x00FF); - //ingest[count++] = (log_summary.rs & 0xFF00) >> 8; - ingest[count++] = (log_summary.rs & 0x00FF); - - #ifdef PDU_DEBUG - OS_printf("log_summary.num_se = 0x%02x \n",log_summary.num_se); - OS_printf("log_summary.rs = 0x%02x \n",log_summary.rs); - #endif - - return count; -} - -static int32 Crypto_MC_dump(char* ingest) -{ - int count = 0; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = (log_count * 6); // SDLS_MC_DUMP_RPLY_SIZE - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - // PDU - for (int x = 0; x < log_count; x++) - { - ingest[count++] = log.blk[x].emt; - //ingest[count++] = (log.blk[x].em_len & 0xFF00) >> 8; - ingest[count++] = (log.blk[x].em_len & 0x00FF); - for (int y = 0; y < EMV_SIZE; y++) - { - ingest[count++] = log.blk[x].emv[y]; - } - } - - #ifdef PDU_DEBUG - OS_printf("log_count = %d \n", log_count); - OS_printf("log_summary.num_se = 0x%02x \n",log_summary.num_se); - OS_printf("log_summary.rs = 0x%02x \n",log_summary.rs); - #endif - - return count; -} - -static int32 Crypto_MC_erase(char* ingest) -{ - int count = 0; - - // Zero Logs - for (int x = 0; x < LOG_SIZE; x++) - { - log.blk[x].emt = 0; - log.blk[x].em_len = 0; - for (int y = 0; y < EMV_SIZE; y++) - { - log.blk[x].emv[y] = 0; - } - } - - // Compute Summary - log_count = 0; - log_summary.num_se = 0; - log_summary.rs = LOG_SIZE; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 2; // 4 - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - // PDU - //ingest[count++] = (log_summary.num_se & 0xFF00) >> 8; - ingest[count++] = (log_summary.num_se & 0x00FF); - //ingest[count++] = (log_summary.rs & 0xFF00) >> 8; - ingest[count++] = (log_summary.rs & 0x00FF); - - return count; -} - -static int32 Crypto_MC_selftest(char* ingest) -{ - uint8 count = 0; - uint8 result = ST_OK; - - // TODO: Perform test - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 1; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - ingest[count++] = result; - - return count; -} - -static int32 Crypto_SA_readARSN(char* ingest) -{ - uint8 count = 0; - uint16 spi = 0x0000; - SecurityAssociation_t* sa_ptr; - - // Read ingest - spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 2 + IV_SIZE; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 128); - - // Write SPI to reply - ingest[count++] = (spi & 0xFF00) >> 8; - ingest[count++] = (spi & 0x00FF); - - - if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - return OS_ERROR; //Error -- unable to get SA from SPI. - } - - - if (sa_ptr->iv_len > 0) - { // Set IV - authenticated encryption - for (int x = 0; x < sa_ptr->iv_len - 1; x++) - { - ingest[count++] = sa_ptr->iv[x]; - } - - // TODO: Do we need this? - if (sa_ptr->iv[IV_SIZE - 1] > 0) - { // Adjust to report last received, not expected - ingest[count++] = sa_ptr->iv[IV_SIZE - 1] - 1; - } - else - { - ingest[count++] = sa_ptr->iv[IV_SIZE - 1]; - } - } - else - { - // TODO - } - - #ifdef PDU_DEBUG - OS_printf("spi = %d \n", spi); - if (sa_ptr->iv_len > 0) - { - OS_printf("ARSN = 0x"); - for (int x = 0; x < sa_ptr->iv_len; x++) - { - OS_printf("%02x", sa_ptr->iv[x]); - } - OS_printf("\n"); - } - #endif - - return count; -} - -static int32 Crypto_MC_resetalarm(void) -{ // Reset all alarm flags - report.af = 0; - report.bsnf = 0; - report.bmacf = 0; - report.ispif = 0; - return OS_SUCCESS; -} - -static int32 Crypto_User_IdleTrigger(char* ingest) -{ - uint8 count = 0; - - // Prepare for Reply - sdls_frame.pdu.pdu_len = 0; - sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; - count = Crypto_Prep_Reply(ingest, 144); - - return count; -} - -static int32 Crypto_User_BadSPI(void) -{ - // Toggle Bad Sequence Number - if (badSPI == 0) - { - badSPI = 1; - } - else - { - badSPI = 0; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_BadMAC(void) -{ - // Toggle Bad MAC - if (badMAC == 0) - { - badMAC = 1; - } - else - { - badMAC = 0; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_BadIV(void) -{ - // Toggle Bad MAC - if (badIV == 0) - { - badIV = 1; - } - else - { - badIV = 0; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_BadFECF(void) -{ - // Toggle Bad FECF - if (badFECF == 0) - { - badFECF = 1; - } - else - { - badFECF = 0; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_ModifyKey(void) -{ - // Local variables - uint16 kid = ((uint8)sdls_frame.pdu.data[0] << 8) | ((uint8)sdls_frame.pdu.data[1]); - uint8 mod = (uint8)sdls_frame.pdu.data[2]; - - switch (mod) - { - case 1: // Invalidate Key - ek_ring[kid].value[KEY_SIZE-1]++; - OS_printf("Key %d value invalidated! \n", kid); - break; - case 2: // Modify key state - ek_ring[kid].key_state = (uint8)sdls_frame.pdu.data[3] & 0x0F; - OS_printf("Key %d state changed to %d! \n", kid, mod); - break; - default: - // Error - break; - } - - return OS_SUCCESS; -} - -static int32 Crypto_User_ModifyActiveTM(void) -{ - tm_frame.tm_sec_header.spi = (uint8)sdls_frame.pdu.data[0]; - return OS_SUCCESS; -} - -static int32 Crypto_User_ModifyVCID(void) -{ - tm_frame.tm_header.vcid = (uint8)sdls_frame.pdu.data[0]; - SecurityAssociation_t* sa_ptr; - - for (int i = 0; i < NUM_GVCID; i++) - { - if(sadb_routine->sadb_get_sa_from_spi(i,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - return OS_ERROR; //Error -- unable to get SA from SPI. - } - for (int j = 0; j < NUM_SA; j++) - { - - if (sa_ptr->gvcid_tm_blk[j].mapid == TYPE_TM) - { - if (sa_ptr->gvcid_tm_blk[j].vcid == tm_frame.tm_header.vcid) - { - tm_frame.tm_sec_header.spi = i; - OS_printf("TM Frame SPI changed to %d \n",i); - break; - } - } - } - } - - return OS_SUCCESS; -} - -/* -** Procedures Specifications -*/ -static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) -{ - int32 status = OS_SUCCESS; - - switch (sdls_frame.pdu.type) - { - case 0: // Command - switch (sdls_frame.pdu.uf) - { - case 0: // CCSDS Defined Command - switch (sdls_frame.pdu.sg) - { - case SG_KEY_MGMT: // Key Management Procedure - switch (sdls_frame.pdu.pid) - { - case PID_OTAR: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key OTAR\n" RESET); - #endif - status = Crypto_Key_OTAR(); - break; - case PID_KEY_ACTIVATION: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Activate\n" RESET); - #endif - status = Crypto_Key_update(KEY_ACTIVE); - break; - case PID_KEY_DEACTIVATION: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Deactivate\n" RESET); - #endif - status = Crypto_Key_update(KEY_DEACTIVATED); - break; - case PID_KEY_VERIFICATION: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Verify\n" RESET); - #endif - status = Crypto_Key_verify(ingest,tc_frame); - break; - case PID_KEY_DESTRUCTION: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Destroy\n" RESET); - #endif - status = Crypto_Key_update(KEY_DESTROYED); - break; - case PID_KEY_INVENTORY: - #ifdef PDU_DEBUG - OS_printf(KGRN "Key Inventory\n" RESET); - #endif - status = Crypto_Key_inventory(ingest); - break; - default: - OS_printf(KRED "Error: Crypto_PDU failed interpreting Key Management Procedure Identification Field! \n" RESET); - break; - } - break; - case SG_SA_MGMT: // Security Association Management Procedure - switch (sdls_frame.pdu.pid) - { - case PID_CREATE_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Create\n" RESET); - #endif - status = sadb_routine->sadb_sa_create(); - break; - case PID_DELETE_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Delete\n" RESET); - #endif - status = sadb_routine->sadb_sa_delete(); - break; - case PID_SET_ARSNW: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA setARSNW\n" RESET); - #endif - status = sadb_routine->sadb_sa_setARSNW(); - break; - case PID_REKEY_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Rekey\n" RESET); - #endif - status = sadb_routine->sadb_sa_rekey(); - break; - case PID_EXPIRE_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Expire\n" RESET); - #endif - status = sadb_routine->sadb_sa_expire(); - break; - case PID_SET_ARSN: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA SetARSN\n" RESET); - #endif - status = sadb_routine->sadb_sa_setARSN(); - break; - case PID_START_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Start\n" RESET); - #endif - status = sadb_routine->sadb_sa_start(tc_frame); - break; - case PID_STOP_SA: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Stop\n" RESET); - #endif - status = sadb_routine->sadb_sa_stop(); - break; - case PID_READ_ARSN: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA readARSN\n" RESET); - #endif - status = Crypto_SA_readARSN(ingest); - break; - case PID_SA_STATUS: - #ifdef PDU_DEBUG - OS_printf(KGRN "SA Status\n" RESET); - #endif - status = sadb_routine->sadb_sa_status(ingest); - break; - default: - OS_printf(KRED "Error: Crypto_PDU failed interpreting SA Procedure Identification Field! \n" RESET); - break; - } - break; - case SG_SEC_MON_CTRL: // Security Monitoring & Control Procedure - switch (sdls_frame.pdu.pid) - { - case PID_PING: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Ping\n" RESET); - #endif - status = Crypto_MC_ping(ingest); - break; - case PID_LOG_STATUS: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Status\n" RESET); - #endif - status = Crypto_MC_status(ingest); - break; - case PID_DUMP_LOG: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Dump\n" RESET); - #endif - status = Crypto_MC_dump(ingest); - break; - case PID_ERASE_LOG: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Erase\n" RESET); - #endif - status = Crypto_MC_erase(ingest); - break; - case PID_SELF_TEST: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Selftest\n" RESET); - #endif - status = Crypto_MC_selftest(ingest); - break; - case PID_ALARM_FLAG: - #ifdef PDU_DEBUG - OS_printf(KGRN "MC Reset Alarm\n" RESET); - #endif - status = Crypto_MC_resetalarm(); - break; - default: - OS_printf(KRED "Error: Crypto_PDU failed interpreting MC Procedure Identification Field! \n" RESET); - break; - } - break; - default: // ERROR - OS_printf(KRED "Error: Crypto_PDU failed interpreting Service Group! \n" RESET); - break; - } - break; - - case 1: // User Defined Command - switch (sdls_frame.pdu.sg) - { - default: - switch (sdls_frame.pdu.pid) - { - case 0: // Idle Frame Trigger - #ifdef PDU_DEBUG - OS_printf(KMAG "User Idle Trigger\n" RESET); - #endif - status = Crypto_User_IdleTrigger(ingest); - break; - case 1: // Toggle Bad SPI - #ifdef PDU_DEBUG - OS_printf(KMAG "User Toggle Bad SPI\n" RESET); - #endif - status = Crypto_User_BadSPI(); - break; - case 2: // Toggle Bad IV - #ifdef PDU_DEBUG - OS_printf(KMAG "User Toggle Bad IV\n" RESET); - #endif - status = Crypto_User_BadIV();\ - break; - case 3: // Toggle Bad MAC - #ifdef PDU_DEBUG - OS_printf(KMAG "User Toggle Bad MAC\n" RESET); - #endif - status = Crypto_User_BadMAC(); - break; - case 4: // Toggle Bad FECF - #ifdef PDU_DEBUG - OS_printf(KMAG "User Toggle Bad FECF\n" RESET); - #endif - status = Crypto_User_BadFECF(); - break; - case 5: // Modify Key - #ifdef PDU_DEBUG - OS_printf(KMAG "User Modify Key\n" RESET); - #endif - status = Crypto_User_ModifyKey(); - break; - case 6: // Modify ActiveTM - #ifdef PDU_DEBUG - OS_printf(KMAG "User Modify Active TM\n" RESET); - #endif - status = Crypto_User_ModifyActiveTM(); - break; - case 7: // Modify TM VCID - #ifdef PDU_DEBUG - OS_printf(KMAG "User Modify VCID\n" RESET); - #endif - status = Crypto_User_ModifyVCID(); - break; - default: - OS_printf(KRED "Error: Crypto_PDU received user defined command! \n" RESET); - break; - } - } - break; - } - break; - - case 1: // Reply - OS_printf(KRED "Error: Crypto_PDU failed interpreting PDU Type! Received a Reply!?! \n" RESET); - break; - } - - #ifdef CCSDS_DEBUG - if (status > 0) - { - OS_printf(KMAG "CCSDS message put on software bus: 0x" RESET); - for (int x = 0; x < status; x++) - { - OS_printf(KMAG "%02x" RESET, (uint8) ingest[x]); - } - OS_printf("\n"); - } - #endif - - return status; -} - -static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, - GvcidManagedParameters_t** managed_parameters_out) -{ - int32 status = MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND; - - while(managed_parameters_in != NULL){ - if(managed_parameters_in->tfvn==tfvn && managed_parameters_in->scid==scid && managed_parameters_in->vcid==vcid){ - *managed_parameters_out = managed_parameters_in; //Found the managed parameters for that gvcid! - status = OS_SUCCESS; - break; - } else{ //Managed parameters for gvcid not found, set pointer to next managed parameter. - managed_parameters_in = managed_parameters_in->next; - } - } - return status; -} -//Managed parameters are expected to live the duration of the program, this may not be necessary. -//TODO - If this function is useful, we need to add a Crypto Shutdown method that invokes this internal free. -static void Crypto_Free_Managed_Parameters(GvcidManagedParameters_t* managed_parameters) -{ - if(managed_parameters->next != NULL){ - Crypto_Free_Managed_Parameters(managed_parameters->next); - } - free(managed_parameters); -} - - -int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ - uint8 **pp_in_frame, uint16 *p_enc_frame_len) -{ - // Local Variables - int32 status = OS_SUCCESS; - TC_FramePrimaryHeader_t temp_tc_header; - SecurityAssociation_t* sa_ptr = NULL; - uint8 *p_new_enc_frame = NULL; - uint8 sa_service_type = -1; - uint16 mac_loc = 0; - uint16 tf_payload_len = 0x0000; - uint16 new_fecf = 0x0000; - uint8 aad[20]; - gcry_cipher_hd_t tmp_hd; - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); - #endif - - if (p_in_frame == NULL) - { - status = CRYPTO_LIB_ERR_NULL_BUFFER; - OS_printf(KRED "Error: Input Buffer NULL! \n" RESET); - return status; // Just return here, nothing can be done. - } - - #ifdef DEBUG - OS_printf("%d TF Bytes received\n", in_frame_length); - OS_printf("DEBUG - "); - for(int i=0; i < in_frame_length; i++) - { - OS_printf("%02X", ((uint8 *)&*p_in_frame)[i]); - } - OS_printf("\nPrinted %d bytes\n", in_frame_length); - #endif - - // Primary Header - temp_tc_header.tfvn = ((uint8)p_in_frame[0] & 0xC0) >> 6; - temp_tc_header.bypass = ((uint8)p_in_frame[0] & 0x20) >> 5; - temp_tc_header.cc = ((uint8)p_in_frame[0] & 0x10) >> 4; - temp_tc_header.spare = ((uint8)p_in_frame[0] & 0x0C) >> 2; - temp_tc_header.scid = ((uint8)p_in_frame[0] & 0x03) << 8; - temp_tc_header.scid = temp_tc_header.scid | (uint8)p_in_frame[1]; - temp_tc_header.vcid = ((uint8)p_in_frame[2] & 0xFC) >> 2 & crypto_config->vcid_bitmask; - temp_tc_header.fl = ((uint8)p_in_frame[2] & 0x03) << 8; - temp_tc_header.fl = temp_tc_header.fl | (uint8)p_in_frame[3]; - temp_tc_header.fsn = (uint8)p_in_frame[4]; - - //Lookup-retrieve managed parameters for frame via gvcid: - status = Crypto_Get_Managed_Parameters_For_Gvcid(temp_tc_header.tfvn,temp_tc_header.scid,temp_tc_header.vcid,gvcid_managed_parameters,¤t_managed_parameters); - if(status != OS_SUCCESS) {return status;} //Unable to get necessary Managed Parameters for TC TF -- return with error. - - - uint8 segmentation_hdr = 0x00; - uint8 map_id = 0; - if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ - segmentation_hdr = p_in_frame[5]; - map_id = segmentation_hdr & 0x3F; - } - - - // Check if command frame flag set - if ((temp_tc_header.cc == 1) && (status == OS_SUCCESS)) - { - /* - ** CCSDS 232.0-B-3 - ** Section 6.3.1 - ** "Type-C frames do not have the Security Header and Security Trailer." - */ - #ifdef TC_DEBUG - OS_printf(KYEL "DEBUG - Received Control/Command frame - nothing to do.\n" RESET); - #endif - status = CRYPTO_LIB_ERR_INVALID_CC_FLAG; - } - - if (status == OS_SUCCESS) - { - // Query SA DB for active SA / SDLS parameters - if(sadb_routine == NULL) //This should not happen, but tested here for safety - { - OS_printf(KRED "ERROR: SA DB Not initalized! -- CRYPTO_LIB_ERR_NO_INIT, Will Exit\n" RESET); - status = CRYPTO_LIB_ERR_NO_INIT; - } - else - { - status = sadb_routine->sadb_get_operational_sa_from_gvcid(temp_tc_header.tfvn, temp_tc_header.scid, temp_tc_header.vcid, map_id,&sa_ptr); - } - - - // If unable to get operational SA, can return - if (status != OS_SUCCESS) - { - return status; - } - - #ifdef SA_DEBUG - OS_printf(KYEL "DEBUG - Printing SA Entry for current frame.\n" RESET); - Crypto_saPrint(sa_ptr); - #endif - - // Determine SA Service Type - if ((sa_ptr->est == 0) && (sa_ptr->ast == 0)) - { - sa_service_type = SA_PLAINTEXT; - } - else if ((sa_ptr->est == 0) && (sa_ptr->ast == 1)) - { - sa_service_type = SA_AUTHENTICATION; - } - else if ((sa_ptr->est == 1) && (sa_ptr->ast == 0)) - { - sa_service_type = SA_ENCRYPTION; - } - else if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) - { - sa_service_type = SA_AUTHENTICATED_ENCRYPTION; - } - else - { - // Probably unnecessary check - // Leaving for now as it would be cleaner in SA to have an association enum returned I believe - OS_printf(KRED "Error: SA Service Type is not defined! \n" RESET); - status = OS_ERROR; - return status; - } - - #ifdef TC_DEBUG - switch(sa_service_type) - { - case SA_PLAINTEXT: - OS_printf(KBLU "Creating a TC - CLEAR!\n" RESET); - break; - case SA_AUTHENTICATION: - OS_printf(KBLU "Creating a TC - AUTHENTICATED!\n" RESET); - break; - case SA_ENCRYPTION: - OS_printf(KBLU "Creating a TC - ENCRYPTED!\n" RESET); - break; - case SA_AUTHENTICATED_ENCRYPTION: - OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION!\n" RESET); - break; - } - #endif - - // Determine length of buffer to be malloced - // TODO: Determine TC_PAD_SIZE - // TODO: Note: Currently assumes ciphertext output length is same as ciphertext input length - switch(sa_service_type) - { - case SA_PLAINTEXT: - // Ingest length + spi_index (2) + some variable length fields - *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shplf_len; - case SA_AUTHENTICATION: - // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size + stmacf_len - *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ - sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; - case SA_ENCRYPTION: - // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size - *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ - sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE; - case SA_AUTHENTICATED_ENCRYPTION: - // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ - // + shplf_len + arc_len + pad_size + stmacf_len - *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ - sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; - } - - #ifdef TC_DEBUG - OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *p_enc_frame_len); - OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); - //OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded - OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); - OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, sa_ptr->shivf_len); - OS_printf(KYEL "\tshsnf_len\t = %d\n" RESET, sa_ptr->shsnf_len); - OS_printf(KYEL "\tshplf len\t = %d\n" RESET, sa_ptr->shplf_len); - OS_printf(KYEL "\tarc_len\t\t = %d\n" RESET, sa_ptr->arc_len); - OS_printf(KYEL "\tpad_size\t = %d\n" RESET, TC_PAD_SIZE); - OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, sa_ptr->stmacf_len); - #endif - - // Accio buffer - p_new_enc_frame = (uint8 *)malloc(*p_enc_frame_len * sizeof (unsigned char)); - if(!p_new_enc_frame) - { - OS_printf(KRED "Error: Malloc for encrypted output buffer failed! \n" RESET); - status = OS_ERROR; - return status; - } - CFE_PSP_MemSet(p_new_enc_frame, 0, *p_enc_frame_len); - - // Copy original TF header - CFE_PSP_MemCpy(p_new_enc_frame, p_in_frame, TC_FRAME_PRIMARYHEADER_SIZE); - - // Set new TF Header length - // Recall: Length field is one minus total length per spec - *(p_new_enc_frame+2) = ((*(p_new_enc_frame+2) & 0xFC) | (((*p_enc_frame_len - 1) & (0x0300)) >> 8)); - *(p_new_enc_frame+3) = ((*p_enc_frame_len - 1) & (0x00FF)); - - #ifdef TC_DEBUG - OS_printf(KYEL "Printing updated TF Header:\n\t"); - for (int i=0; ihas_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ - index++; //Add 1 byte to index because segmentation header used for this gvcid. - } - - /* - ** Begin Security Header Fields - ** Reference CCSDS SDLP 3550b1 4.1.1.1.3 - */ - // Set SPI - *(p_new_enc_frame + index) = ((sa_ptr->spi & 0xFF00) >> 8); - *(p_new_enc_frame + index + 1) = (sa_ptr->spi & 0x00FF); - index += 2; - - // Set initialization vector if specified - if ((sa_service_type == SA_AUTHENTICATION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION) || (sa_service_type == SA_ENCRYPTION)) - { - #ifdef SA_DEBUG - OS_printf(KYEL "Using IV value:\n\t"); - for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} - OS_printf("\n" RESET); - #endif - - for (int i=0; i < sa_ptr->shivf_len; i++) - { - // TODO: Likely API call - // Copy in IV from SA - *(p_new_enc_frame + index) = sa_ptr->iv[i]; - index++; - } - } - - // Set anti-replay sequence number if specified - /* - ** See also: 4.1.1.4.2 - ** 4.1.1.4.4 If authentication or authenticated encryption is not selected - ** for an SA, the Sequence Number field shall be zero octets in length. - ** Reference CCSDS 3550b1 - */ - // Determine if seq num field is needed - // TODO: Likely SA API Call - if (sa_ptr->shsnf_len > 0) - { - // If using anti-replay counter, increment it - // TODO: API call instead? - // TODO: Check return code - Crypto_increment(sa_ptr->arc, sa_ptr->shsnf_len); - for (int i=0; i < sa_ptr->shsnf_len; i++) - { - *(p_new_enc_frame + index) = sa_ptr->arc[i]; - index++; - } - } - - // Set security header padding if specified - /* - ** 4.2.3.4 h) if the algorithm and mode selected for the SA require the use of - ** fill padding, place the number of fill bytes used into the Pad Length field - ** of the Security Header - Reference CCSDS 3550b1 - */ - // TODO: Revisit this - // TODO: Likely SA API Call - for (int i=0; i < sa_ptr->shplf_len; i++) - { - /* 4.1.1.5.2 The Pad Length field shall contain the count of fill bytes used in the - ** cryptographic process, consisting of an integral number of octets. - CCSDS 3550b1 - */ - // TODO: Set this depending on crypto cipher used - *(p_new_enc_frame + index) = 0x00; - index++; - } - - /* - ** End Security Header Fields - */ - - uint8 fecf_len = FECF_SIZE; - if(current_managed_parameters->has_fecf==TC_NO_FECF) { fecf_len = 0; } - uint8 segment_hdr_len = SEGMENT_HDR_SIZE; - if(current_managed_parameters->has_segmentation_hdr==TC_NO_SEGMENT_HDRS) { segment_hdr_len = 0; } - // Copy in original TF data - except FECF - // Will be over-written if using encryption later - // and if it was present in the original TCTF - //if FECF - // Even though FECF is not part of apply_security payload, we still have to subtract the length from the in_frame_length since that includes FECF length & segment header length. - tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - segment_hdr_len - fecf_len; - //if no FECF - //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; - CFE_PSP_MemCpy((p_new_enc_frame+index), (p_in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); - //index += tf_payload_len; - - /* - ** Begin Security Trailer Fields - */ - - // Set MAC Field if present - /* - ** May be present and unused if switching between clear and authenticated - ** CCSDS 3550b1 4.1.2.3 - */ - // By leaving MAC as zeros, can use index for encryption output - // for (int i=0; i < temp_SA.stmacf_len; i++) - // { - // // Temp fill MAC - // *(p_new_enc_frame + index) = 0x00; - // index++; - // } - - /* - ** End Security Trailer Fields - */ - - /* - ** Begin Authentication / Encryption - */ - - if (sa_service_type != SA_PLAINTEXT) - { - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[sa_ptr->ekid].value[0]), - KEY_SIZE //TODO: look into this - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(sa_ptr->iv[0]), - sa_ptr->iv_len - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - - // Prepare additional authenticated data, if needed - if ((sa_service_type == SA_AUTHENTICATION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) - { - uint8 bit_masked_data[sa_ptr->abm_len]; - for (int y = 0; y < sa_ptr->abm_len; y++) - { - bit_masked_data[y] = p_new_enc_frame[y] & sa_ptr->abm[y]; - } - #ifdef MAC_DEBUG - OS_printf(KYEL "Preparing AAD:\n"); - OS_printf("\tUsing ABM Length of %d\n\t", sa_ptr->abm_len); - for (int y = 0; y < sa_ptr->abm_len; y++) - { - OS_printf("%02x", bit_masked_data[y]); - } - OS_printf("\n" RESET); - #endif - - gcry_error = gcry_cipher_authenticate( - tmp_hd, - bit_masked_data, // additional authenticated data - sa_ptr->abm_len // length of AAD - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); - status = OS_ERROR; - return status; - } - } - - if ((sa_service_type == SA_ENCRYPTION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) - { - // TODO: More robust calculation of this location - // uint16 output_loc = TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; - #ifdef TC_DEBUG - OS_printf("Encrypted bytes output_loc is %d\n", index); - OS_printf("tf_payload_len is %d\n", tf_payload_len); - OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); - for(int i=0; i < *p_enc_frame_len; i++) - { - OS_printf("%02X", *(p_new_enc_frame + i)); - } - OS_printf("\n"); - #endif - - gcry_error = gcry_cipher_encrypt( - tmp_hd, - &p_new_enc_frame[index], // ciphertext output - tf_payload_len, // length of data - (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE + segment_hdr_len), // plaintext input - tf_payload_len // in data length - ); - - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - - #ifdef TC_DEBUG - OS_printf("Encrypted bytes output_loc is %d\n", index); - OS_printf("tf_payload_len is %d\n", tf_payload_len); - OS_printf(KYEL "Printing TC Frame after encryption:\n\t"); - for(int i=0; i < *p_enc_frame_len; i++) - { - OS_printf("%02X", *(p_new_enc_frame + i)); - } - OS_printf("\n"); - #endif - } - - if ((sa_service_type == SA_AUTHENTICATION) || \ - (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) - { - // TODO - Know if FECF exists - mac_loc = *p_enc_frame_len - sa_ptr->stmacf_len - FECF_SIZE; - #ifdef MAC_DEBUG - OS_printf(KYEL "MAC location is: %d\n" RESET, mac_loc); - OS_printf(KYEL "MAC size is: %d\n" RESET, MAC_SIZE); - #endif - gcry_error = gcry_cipher_gettag( - tmp_hd, - &p_new_enc_frame[mac_loc], // tag output - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - } - // Zeroise any sensitive information - if (sa_service_type != SA_PLAINTEXT) - { - gcry_cipher_close(tmp_hd); - } - } - - #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); - #ifdef SA_DEBUG - OS_printf(KYEL "Next IV value is:\n\t"); - for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} - OS_printf("\n" RESET); - #endif - #endif - /* - ** End Authentication / Encryption - */ - - //Only calculate & insert FECF if CryptoLib is configured to do so & gvcid includes FECF. - if( crypto_config->crypto_create_fecf==CRYPTO_TC_CREATE_FECF_TRUE && - current_managed_parameters->has_fecf==TC_HAS_FECF) - { - // Set FECF Field if present - #ifdef FECF_DEBUG - OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *p_enc_frame_len - 2); - #endif - new_fecf = Crypto_Calc_FECF(p_new_enc_frame, *p_enc_frame_len - 2); - *(p_new_enc_frame + *p_enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); - *(p_new_enc_frame + *p_enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); - index += 2; - } - - #ifdef TC_DEBUG - OS_printf(KYEL "Printing new TC Frame:\n\t"); - for(int i=0; i < *p_enc_frame_len; i++) - { - OS_printf("%02X", *(p_new_enc_frame + i)); - } - OS_printf("\n\tThe returned length is: %d\n" RESET, *p_enc_frame_len); - #endif - - *pp_in_frame = p_new_enc_frame; - } - - status = sadb_routine->sadb_save_sa(sa_ptr); - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_TC_ApplySecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_processed_frame) -// Loads the ingest frame into the global tc_frame while performing decryption -{ - // Local Variables - int32 status = OS_SUCCESS; - int x = 0; - int y = 0; - gcry_cipher_hd_t tmp_hd; - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - SecurityAssociation_t* sa_ptr = NULL; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_TC_ProcessSecurity START -----\n" RESET); - #endif - - int byte_idx = 0; - // Primary Header - tc_sdls_processed_frame->tc_header.tfvn = ((uint8)ingest[byte_idx] & 0xC0) >> 6; - tc_sdls_processed_frame->tc_header.bypass = ((uint8)ingest[byte_idx] & 0x20) >> 5; - tc_sdls_processed_frame->tc_header.cc = ((uint8)ingest[byte_idx] & 0x10) >> 4; - tc_sdls_processed_frame->tc_header.spare = ((uint8)ingest[byte_idx] & 0x0C) >> 2; - tc_sdls_processed_frame->tc_header.scid = ((uint8)ingest[byte_idx] & 0x03) << 8; - byte_idx++; - tc_sdls_processed_frame->tc_header.scid = tc_sdls_processed_frame->tc_header.scid | (uint8)ingest[byte_idx]; - byte_idx++; - tc_sdls_processed_frame->tc_header.vcid = (((uint8)ingest[byte_idx] & 0xFC) >> 2) & crypto_config->vcid_bitmask; - tc_sdls_processed_frame->tc_header.fl = ((uint8)ingest[byte_idx] & 0x03) << 8; - byte_idx++; - tc_sdls_processed_frame->tc_header.fl = tc_sdls_processed_frame->tc_header.fl | (uint8)ingest[byte_idx]; - byte_idx++; - tc_sdls_processed_frame->tc_header.fsn = (uint8)ingest[byte_idx]; - byte_idx++; - - //Lookup-retrieve managed parameters for frame via gvcid: - status = Crypto_Get_Managed_Parameters_For_Gvcid(tc_sdls_processed_frame->tc_header.tfvn,tc_sdls_processed_frame->tc_header.scid, - tc_sdls_processed_frame->tc_header.vcid,gvcid_managed_parameters,¤t_managed_parameters); - - if(status != OS_SUCCESS) {return status;} //Unable to get necessary Managed Parameters for TC TF -- return with error. - - // Security Header - if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ - tc_sdls_processed_frame->tc_sec_header.sh = (uint8)ingest[byte_idx]; - byte_idx++; - } - tc_sdls_processed_frame->tc_sec_header.spi = ((uint8)ingest[byte_idx] << 8) | (uint8)ingest[byte_idx+1]; - byte_idx+=2; - #ifdef TC_DEBUG - OS_printf("vcid = %d \n", tc_sdls_processed_frame->tc_header.vcid ); - OS_printf("spi = %d \n", tc_sdls_processed_frame->tc_sec_header.spi); - #endif - - // Checks - if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR && ((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) - { - // User packet check only used for ESA Testing! - } - else - { // Update last spi used - report.lspiu = tc_sdls_processed_frame->tc_sec_header.spi; - - // Verify - if (tc_sdls_processed_frame->tc_header.scid != (SCID & 0x3FF)) - { - OS_printf(KRED "Error: SCID incorrect! \n" RESET); - status = OS_ERROR; - } - else - { - switch (report.lspiu) - { // Invalid SPIs fall through to trigger flag in FSR - case 0x0000: - case 0xFFFF: - status = OS_ERROR; - report.ispif = 1; - OS_printf(KRED "Error: SPI invalid! \n" RESET); - break; - default: - break; - } - } - - if ((report.lspiu > NUM_SA) && (status == OS_SUCCESS)) - { - report.ispif = 1; - OS_printf(KRED "Error: SPI value greater than NUM_SA! \n" RESET); - status = OS_ERROR; - } - if (status == OS_SUCCESS) - { - if(sadb_routine->sadb_get_sa_from_spi(report.lspiu,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - status = OS_ERROR; //Error -- unable to get SA from SPI. - } - } - if (status == OS_SUCCESS) - { - if (sa_ptr->gvcid_tc_blk.mapid != TYPE_TC) - { - OS_printf(KRED "Error: SA invalid type! \n" RESET); - status = OS_ERROR; - } - } - // TODO: I don't think this is needed. - //if (status == OS_SUCCESS) - //{ - // if (sa_ptr->gvcid_tc_blk.vcid != tc_sdls_processed_frame->tc_header.vcid) - // { - // OS_printf(KRED "Error: VCID not mapped to provided SPI! \n" RESET); - // status = OS_ERROR; - // } - //} - if (status == OS_SUCCESS) - { - if (sa_ptr->sa_state != SA_OPERATIONAL) - { - OS_printf(KRED "Error: SA state not operational! \n" RESET); - status = OS_ERROR; - } - } - if (status != OS_SUCCESS) - { - report.af = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = SPI_INVALID_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - *len_ingest = 0; - return status; - } - } - if(sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - status = OS_ERROR; //Error -- unable to get SA from SPI. - return status; - } - if((sa_ptr->est == 1) && (sa_ptr->ast == 0)) - { - // Encryption Only - #ifdef DEBUG - OS_printf(KBLU "ENCRYPTED TC Received!\n" RESET); - #endif - - #ifdef TC_DEBUG - OS_printf("IV: \n"); - #endif - for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) - { - tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; - #ifdef TC_DEBUG - OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); - #endif - } - byte_idx += sa_ptr->shivf_len; - report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; - - #ifdef DEBUG - OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); - OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); - #endif - - // Check IV is in ARCW - if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, - sa_ptr->arcw[sa_ptr->arcw_len-1]) != CRYPTO_LIB_SUCCESS ) - { - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_WINDOW_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV not in window! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { - if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == CRYPTO_LIB_SUCCESS ) - { // Replay - IV value lower than expected - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_REPLAY_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { // Adjust expected IV to acceptable received value - for (int i = 0; i < (sa_ptr->shivf_len); i++) - { - sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; - } - } - } - - if ( status != CRYPTO_LIB_SUCCESS ) - { // Exit - *len_ingest = 0; - return status; - } - - tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); - - x = x + tc_sdls_processed_frame->tc_pdu_len; - - #ifdef TC_DEBUG - OS_printf("TC: \n"); - for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) - { - OS_printf("\t ingest[%d] = 0x%02x \n", temp, (uint8)ingest[temp+20]); - } - #endif - - // FECF - tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); - Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 1),tc_sdls_processed_frame); - - // Initialize the key - //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[sa_ptr->ekid]); - - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - #ifdef DEBUG - OS_printf("Key ID = %d, 0x", sa_ptr->ekid); - for(int y = 0; y < KEY_SIZE; y++) - { - OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); - } - OS_printf("\n"); - #endif - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[sa_ptr->ekid].value[0]), - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(sa_ptr->iv[0]), - sa_ptr->iv_len - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - - gcry_error = gcry_cipher_decrypt( - tmp_hd, - &(tc_sdls_processed_frame->tc_pdu[0]), // plaintext output - tc_sdls_processed_frame->tc_pdu_len, // length of data - &(ingest[20]), // ciphertext input - tc_sdls_processed_frame->tc_pdu_len // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_cipher_close(tmp_hd); - - // Increment the IV for next time - #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); - #endif - } - // Determine mode via SPI - else if ((sa_ptr->est == 1) && - (sa_ptr->ast == 1)) - { // Authenticated/Encrypted - #ifdef DEBUG - OS_printf(KBLU "Authenticated/Encrypted TC Received!\n" RESET); - #endif - #ifdef TC_DEBUG - OS_printf("IV: \n"); - #endif - for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) - { - tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; - #ifdef TC_DEBUG - OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); - #endif - } - byte_idx += sa_ptr->shivf_len; - report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; - - #ifdef DEBUG - OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); - OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); - #endif - - // Check IV is in ARCW - if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, - sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) - { - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_WINDOW_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV not in window! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { - if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) - { // Replay - IV value lower than expected - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_REPLAY_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { // Adjust expected IV to acceptable received value - for (int i = 0; i < (sa_ptr->shivf_len); i++) - { - sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; - } - } - } - - if ( status == OS_ERROR ) - { // Exit - *len_ingest = 0; - return status; - } - - tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); - - x = x + tc_sdls_processed_frame->tc_pdu_len; - - #ifdef TC_DEBUG - OS_printf("TC: \n"); - for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) - { - OS_printf("\t ingest[%d] = 0x%02x \n", temp, (uint8)ingest[temp+20]); - } - #endif - - // Security Trailer - #ifdef TC_DEBUG - OS_printf("MAC: \n"); - #endif - for (y = x; y < (x + MAC_SIZE); y++) - { - tc_sdls_processed_frame->tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; - #ifdef TC_DEBUG - OS_printf("\t mac[%d] = 0x%02x\n", y-x, tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); - #endif - } - x = x + sa_ptr->stmacf_len; - - // FECF - tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); - Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 1),tc_sdls_processed_frame); - - // Initialize the key - //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[sa_ptr->ekid]); - - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - #ifdef DEBUG - OS_printf("Key ID = %d, 0x", sa_ptr->ekid); - for(int y = 0; y < KEY_SIZE; y++) - { - OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); - } - OS_printf("\n"); - #endif - gcry_error = gcry_cipher_setkey( - tmp_hd, - ek_ring[sa_ptr->ekid].value, - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - sa_ptr->iv, - sa_ptr->iv_len - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - #ifdef MAC_DEBUG - OS_printf("AAD = 0x"); - #endif - // Prepare additional authenticated data (AAD) - - uint8 aad[sa_ptr->abm_len]; - for (y = 0; y < sa_ptr->abm_len; y++) - { - aad[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); - #ifdef MAC_DEBUG - OS_printf("%02x", (uint8) ingest[y]); - #endif - } - #ifdef MAC_DEBUG - OS_printf("\n"); - #endif - - gcry_error = gcry_cipher_authenticate( - tmp_hd, - aad, // additional authenticated data - sa_ptr->abm_len // length of AAD - ); - - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); - status = OS_ERROR; - return status; - } - - gcry_error = gcry_cipher_decrypt( - tmp_hd, - tc_sdls_processed_frame->tc_pdu, // plaintext output - tc_sdls_processed_frame->tc_pdu_len, // length of data - &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input - tc_sdls_processed_frame->tc_pdu_len // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_checktag( - tmp_hd, - tc_sdls_processed_frame->tc_sec_trailer.mac, // tag input - sa_ptr->stmacf_len // tag size - ); - - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - - OS_printf("Calculated MAC = 0x"); - for (int z = 0; z < MAC_SIZE; z++) - { - OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); - } - OS_printf("\n"); - - gcry_error = gcry_cipher_gettag( - tmp_hd, - &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - - OS_printf("Expected MAC = 0x"); - for (int z = 0; z < MAC_SIZE; z++) - { - OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); - } - OS_printf("\n"); - status = OS_ERROR; - report.bmacf = 1; - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - return status; - } - gcry_cipher_close(tmp_hd); - - // Increment the IV for next time - #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); - #endif - } - else if((sa_ptr->ast == 1) && (sa_ptr->est == 0)) - { - // Authentication only - #ifdef DEBUG - OS_printf(KBLU "Authenticated TC Received!\n" RESET); - #endif - #ifdef TC_DEBUG - OS_printf(KYEL "IV: \n\t"); - #endif - for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) - { - tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; - #ifdef TC_DEBUG - OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); - #endif - } - #ifdef TC_DEBUG - OS_printf("\n"RESET); - #endif - byte_idx += sa_ptr->shivf_len; - report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; - - #ifdef DEBUG - OS_printf("\ttc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); - OS_printf("\tsa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); - #endif - - // Check IV is in ARCW - if (Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, - sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) - { - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_WINDOW_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV not in window! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { - if (Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) - { // Replay - IV value lower than expected - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) - { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_REPLAY_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { // Adjust expected IV to acceptable received value - for (int i = 0; i < (sa_ptr->shivf_len); i++) - { - sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; - } - } - } - if ( status == OS_ERROR ) - { // Exit - *len_ingest = 0; - return status; - } - tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); - - // Copy pdu data from ingest into memory - for(int i=0; itc_pdu_len; i++) - { - tc_sdls_processed_frame->tc_pdu[i] = ingest[x]; - x++; - } - - // x = x + tc_sdls_processed_frame->tc_pdu_len; - - #ifdef TC_DEBUG - OS_printf("tc_pdu_len is: %d\n", tc_sdls_processed_frame->tc_pdu_len); - OS_printf("TC PDU ingest Payload: \n\t"); - for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) - { - OS_printf("%02x", (uint8)ingest[temp+20]); - } - OS_printf("\n"); - #endif - - // Security Trailer - #ifdef TC_DEBUG - OS_printf("MAC: \n\t"); - #endif - for (y = x; y < (x + sa_ptr->stmacf_len); y++) - { - tc_sdls_processed_frame->tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; - #ifdef TC_DEBUG - OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); - #endif - } - #ifdef TC_DEBUG - OS_printf("\n"); - #endif - x = x + sa_ptr->stmacf_len; - - // FECF - tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); - Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl-1),tc_sdls_processed_frame); - - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - #ifdef DEBUG - OS_printf("Key ID = %d, 0x", sa_ptr->ekid); - for(int y = 0; y < KEY_SIZE; y++) - { - OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); - } - OS_printf("\n"); - #endif - gcry_error = gcry_cipher_setkey( - tmp_hd, - ek_ring[sa_ptr->ekid].value, - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - sa_ptr->iv, - sa_ptr->iv_len - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - #ifdef MAC_DEBUG - OS_printf("AAD = 0x"); - #endif - // Prepare additional authenticated data (AAD) - for (y = 0; y < sa_ptr->abm_len; y++) - { - ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); - #ifdef DEBUG - OS_printf("%02x", (uint8) ingest[y]); - #endif - } - #ifdef DEBUG - OS_printf("\n"); - #endif - - gcry_error = gcry_cipher_authenticate( - tmp_hd, - ingest, // additional authenticated data - sa_ptr->abm_len // length of AAD - ); - - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); - status = OS_ERROR; - return status; - } - // printf("PDU LEN: %d\n", tc_sdls_processed_frame->tc_pdu_len); - // gcry_error = gcry_cipher_decrypt( - // tmp_hd, - // tc_sdls_processed_frame->tc_pdu, // plaintext output - // tc_sdls_processed_frame->tc_pdu_len, // length of data - // &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input - // tc_sdls_processed_frame->tc_pdu_len // in data length - // ); - // if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - // { - // OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - // status = OS_ERROR; - // return status; - // } - char *garbage_buff = malloc(tc_sdls_processed_frame->tc_pdu_len * sizeof(unsigned char)); - - gcry_error = gcry_cipher_encrypt( - tmp_hd, - // tc_sdls_processed_frame->tc_pdu, // plaintext output - garbage_buff, - tc_sdls_processed_frame->tc_pdu_len, // length of data - &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input - tc_sdls_processed_frame->tc_pdu_len // in data length - ); - free(garbage_buff); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_gettag( - tmp_hd, - &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output - sa_ptr->stmacf_len // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_gettag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - } - - #ifdef MAC_DEBUG - OS_printf("TC_Process Expected MAC = 0x"); - for (int z = 0; z < sa_ptr->stmacf_len ; z++) - { - OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[z]); - } - OS_printf("\n"); - OS_printf("TC_Process Actual MAC = 0x"); - for (int z = 0; z < sa_ptr->stmacf_len ; z++) - { - OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); - } - OS_printf("\n"); - #endif - - #ifdef DEBUG - OS_printf("Using PDU length of: %d\n", tc_sdls_processed_frame->tc_pdu_len); - OS_printf("Printing entire frame sans header in memory:\n\t0x"); - // for(int i=0; itc_header); i++) - // { - // OS_printf("%02x", tc_sdls_processed_frame->tc_header[i]); - // } - OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.sh); - OS_printf("%04x", tc_sdls_processed_frame->tc_sec_header.spi); - for(int i=0; iiv_len; i++) - { - OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.iv[i]); - } - for(int i=0; itc_pdu_len; i++) - { - OS_printf("%02x", tc_sdls_processed_frame->tc_pdu[i]); - } - for(int i=0; istmacf_len; i++) - { - OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[i]); - } - OS_printf("%04x\n", tc_sdls_processed_frame->tc_sec_trailer.fecf); - #endif - - status = OS_ERROR; - report.bmacf = 1; - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - return status; - gcry_cipher_close(tmp_hd); - - // Increment the IV for next time - #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); - #endif - - } - else - { // Clear - #ifdef DEBUG - OS_printf(KBLU "CLEAR TC Received!\n" RESET); - #endif - - for (y = 10; y <= (tc_sdls_processed_frame->tc_header.fl -1); y++) //tfhdr+seghdr+sechdr=5+1+6=12 - { - tc_sdls_processed_frame->tc_pdu[y - 10] = (uint8)ingest[y]; - } - // FECF - tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[y] << 8) | ((uint8)ingest[y+1]); - Crypto_FECF((int) tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl),tc_sdls_processed_frame); - } - - #ifdef TC_DEBUG - Crypto_tcPrint(tc_sdls_processed_frame); - #endif - - // // Zero ingest - // for (x = 0; x < *len_ingest; x++) - // { - // ingest[x] = 0; - // } - - - if(crypto_config->process_sdls_pdus==TC_PROCESS_SDLS_PDUS_FALSE) //If we don't want to process frame data for SDLS PDUs, only reverse security & return content. - { - // CCSDS Pass-through - #ifdef DEBUG - OS_printf(KGRN "CCSDS Pass-through \n" RESET); - #endif - if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR) { - for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl - 11); x++) { - ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; - #ifdef CCSDS_DEBUG - OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); - #endif - *len_ingest = x; - } - } else { - for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl); x++) { //with no PUS header, entire PDU is data - ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; - #ifdef CCSDS_DEBUG - OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); - #endif - *len_ingest = x; - } - } - } - else //Process SDLS PDU - { - if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR) - { - if ((tc_sdls_processed_frame->tc_pdu[0] == 0x18) && (tc_sdls_processed_frame->tc_pdu[1] == 0x80)) - // Crypto Lib Application ID - { - #ifdef DEBUG - OS_printf(KGRN "Received SDLS command: " RESET); - #endif - // CCSDS Header - sdls_frame.hdr.pvn = (tc_sdls_processed_frame->tc_pdu[0] & 0xE0) >> 5; - sdls_frame.hdr.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x10) >> 4; - sdls_frame.hdr.shdr = (tc_sdls_processed_frame->tc_pdu[0] & 0x08) >> 3; - sdls_frame.hdr.appID = - ((tc_sdls_processed_frame->tc_pdu[0] & 0x07) << 8) | tc_sdls_processed_frame->tc_pdu[1]; - sdls_frame.hdr.seq = (tc_sdls_processed_frame->tc_pdu[2] & 0xC0) >> 6; - sdls_frame.hdr.pktid = - ((tc_sdls_processed_frame->tc_pdu[2] & 0x3F) << 8) | tc_sdls_processed_frame->tc_pdu[3]; - sdls_frame.hdr.pkt_length = (tc_sdls_processed_frame->tc_pdu[4] << 8) | tc_sdls_processed_frame->tc_pdu[5]; - - // CCSDS PUS - sdls_frame.pus.shf = (tc_sdls_processed_frame->tc_pdu[6] & 0x80) >> 7; - sdls_frame.pus.pusv = (tc_sdls_processed_frame->tc_pdu[6] & 0x70) >> 4; - sdls_frame.pus.ack = (tc_sdls_processed_frame->tc_pdu[6] & 0x0F); - sdls_frame.pus.st = tc_sdls_processed_frame->tc_pdu[7]; - sdls_frame.pus.sst = tc_sdls_processed_frame->tc_pdu[8]; - sdls_frame.pus.sid = (tc_sdls_processed_frame->tc_pdu[9] & 0xF0) >> 4; - sdls_frame.pus.spare = (tc_sdls_processed_frame->tc_pdu[9] & 0x0F); - - // SDLS TLV PDU - sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[10] & 0x80) >> 7; - sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[10] & 0x40) >> 6; - sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[10] & 0x30) >> 4; - sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[10] & 0x0F); - sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[11] << 8) | tc_sdls_processed_frame->tc_pdu[12]; - for (x = 13; x < (13 + sdls_frame.hdr.pkt_length); x++) { - sdls_frame.pdu.data[x - 13] = tc_sdls_processed_frame->tc_pdu[x]; - } - - #ifdef CCSDS_DEBUG - Crypto_ccsdsPrint(&sdls_frame); - #endif - - // Determine type of PDU - *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); - } - } - else if (tc_sdls_processed_frame->tc_header.vcid == TC_SDLS_EP_VCID) //TC SDLS PDU with no packet layer - { - #ifdef DEBUG - OS_printf(KGRN "Received SDLS command: " RESET); - #endif - // No Packet HDR or PUS in these frames - // SDLS TLV PDU - sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x80) >> 7; - sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[0] & 0x40) >> 6; - sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[0] & 0x30) >> 4; - sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[0] & 0x0F); - sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[1] << 8) | tc_sdls_processed_frame->tc_pdu[2]; - for (x = 3; x < (3 + tc_sdls_processed_frame->tc_header.fl); x++) { - //Todo - Consider how this behaves with large OTAR PDUs that are larger than 1 TC in size. Most likely fails. Must consider Uplink Sessions (sequence numbers). - sdls_frame.pdu.data[x - 3] = tc_sdls_processed_frame->tc_pdu[x]; - } - - #ifdef CCSDS_DEBUG - Crypto_ccsdsPrint(&sdls_frame); - #endif - - // Determine type of PDU - *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); - } - else { - //TODO - Process SDLS PDU with Packet Layer without PUS_HDR - } - }//End Process SDLS PDU - - // Zero ingest - memset(ingest, 0, *len_ingest); - // for (x = 0; x < *len_ingest; x++) - // { - // ingest[x] = 0; - // } - - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_TC_ProcessSecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) -// Accepts CCSDS message in ingest, and packs into TM before encryption -{ - int32 status = CRYPTO_LIB_SUCCESS; - int count = 0; - int pdu_loc = 0; - int pdu_len = *len_ingest - TM_MIN_SIZE; - int pad_len = 0; - int mac_loc = 0; - int fecf_loc = 0; - uint8 tempTM[TM_SIZE]; - int x = 0; - int y = 0; - uint8 aad[20]; - uint16 spi = tm_frame.tm_sec_header.spi; - uint16 spp_crc = 0x0000; - SecurityAssociation_t* sa_ptr; - SecurityAssociation_t sa; - - gcry_cipher_hd_t tmp_hd; - gcry_error_t gcry_error = GPG_ERR_NO_ERROR; - CFE_PSP_MemSet(&tempTM, 0, TM_SIZE); - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_TM_ApplySecurity START -----\n" RESET); - #endif - - // Check for idle frame trigger - if (((uint8)ingest[0] == 0x08) && ((uint8)ingest[1] == 0x90)) - { // Zero ingest - for (x = 0; x < *len_ingest; x++) - { - ingest[x] = 0; - } - // Update TM First Header Pointer - tm_frame.tm_header.fhp = 0xFE; - } - else - { // Update the length of the ingest from the CCSDS header - *len_ingest = (ingest[4] << 8) | ingest[5]; - ingest[5] = ingest[5] - 5; - // Remove outgoing secondary space packet header flag - ingest[0] = 0x00; - // Change sequence flags to 0xFFFF - ingest[2] = 0xFF; - ingest[3] = 0xFF; - // Add 2 bytes of CRC to space packet - spp_crc = Crypto_Calc_CRC16((char*) ingest, *len_ingest); - ingest[*len_ingest] = (spp_crc & 0xFF00) >> 8; - ingest[*len_ingest+1] = (spp_crc & 0x00FF); - *len_ingest = *len_ingest + 2; - // Update TM First Header Pointer - tm_frame.tm_header.fhp = tm_offset; - #ifdef TM_DEBUG - OS_printf("tm_offset = %d \n", tm_offset); - #endif - } - - // Update Current Telemetry Frame in Memory - // Counters - tm_frame.tm_header.mcfc++; - tm_frame.tm_header.vcfc++; - // Operational Control Field - Crypto_TM_updateOCF(); - // Payload Data Unit - Crypto_TM_updatePDU(ingest, *len_ingest); - - if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - return OS_ERROR; //Error -- unable to get SA from SPI. - } - - - // Check test flags - if (badSPI == 1) - { - tm_frame.tm_sec_header.spi++; - } - if (badIV == 1) - { - sa_ptr->iv[IV_SIZE-1]++; - } - if (badMAC == 1) - { - tm_frame.tm_sec_trailer.mac[MAC_SIZE-1]++; - } - - // Initialize the temporary TM frame - // Header - tempTM[count++] = (uint8) ((tm_frame.tm_header.tfvn << 6) | ((tm_frame.tm_header.scid & 0x3F0) >> 4)); - tempTM[count++] = (uint8) (((tm_frame.tm_header.scid & 0x00F) << 4) | (tm_frame.tm_header.vcid << 1) | (tm_frame.tm_header.ocff)); - tempTM[count++] = (uint8) (tm_frame.tm_header.mcfc); - tempTM[count++] = (uint8) (tm_frame.tm_header.vcfc); - tempTM[count++] = (uint8) ((tm_frame.tm_header.tfsh << 7) | (tm_frame.tm_header.sf << 6) | (tm_frame.tm_header.pof << 5) | (tm_frame.tm_header.slid << 3) | ((tm_frame.tm_header.fhp & 0x700) >> 8)); - tempTM[count++] = (uint8) (tm_frame.tm_header.fhp & 0x0FF); - // tempTM[count++] = (uint8) ((tm_frame.tm_header.tfshvn << 6) | tm_frame.tm_header.tfshlen); - // Security Header - tempTM[count++] = (uint8) ((spi & 0xFF00) >> 8); - tempTM[count++] = (uint8) ((spi & 0x00FF)); - CFE_PSP_MemCpy(tm_frame.tm_sec_header.iv, sa_ptr->iv, IV_SIZE); - - // Padding Length - pad_len = Crypto_Get_tmLength(*len_ingest) - TM_MIN_SIZE + IV_SIZE + TM_PAD_SIZE - *len_ingest; - - // Only add IV for authenticated encryption - if ((sa_ptr->est == 1) && - (sa_ptr->ast == 1)) - { // Initialization Vector - #ifdef INCREMENT - Crypto_increment(sa_ptr->iv, IV_SIZE); - #endif - if ((sa_ptr->est == 1) || (sa_ptr->ast == 1)) - { for (x = 0; x < IV_SIZE; x++) - { - tempTM[count++] = sa_ptr->iv[x]; - } - } - pdu_loc = count; - pad_len = pad_len - IV_SIZE - TM_PAD_SIZE + OCF_SIZE; - pdu_len = *len_ingest + pad_len; - } - else - { // Include padding length bytes - hard coded per ESA testing - tempTM[count++] = 0x00; // pad_len >> 8; - tempTM[count++] = 0x1A; // pad_len - pdu_loc = count; - pdu_len = *len_ingest + pad_len; - } - - // Payload Data Unit - for (x = 0; x < (pdu_len); x++) - { - tempTM[count++] = (uint8) tm_frame.tm_pdu[x]; - } - // Message Authentication Code - mac_loc = count; - for (x = 0; x < MAC_SIZE; x++) - { - tempTM[count++] = 0x00; - } - // Operational Control Field - for (x = 0; x < OCF_SIZE; x++) - { - tempTM[count++] = (uint8) tm_frame.tm_sec_trailer.ocf[x]; - } - // Frame Error Control Field - fecf_loc = count; - tm_frame.tm_sec_trailer.fecf = Crypto_Calc_FECF((char*) tempTM, count); - tempTM[count++] = (uint8) ((tm_frame.tm_sec_trailer.fecf & 0xFF00) >> 8); - tempTM[count++] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); - - // Determine Mode - // Clear - if ((sa_ptr->est == 0) && - (sa_ptr->ast == 0)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TM - CLEAR! \n" RESET); - #endif - // Copy temporary frame to ingest - CFE_PSP_MemCpy(ingest, tempTM, count); - } - // Authenticated Encryption - else if ((sa_ptr->est == 1) && - (sa_ptr->ast == 1)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TM - AUTHENTICATED ENCRYPTION! \n" RESET); - #endif - - // Copy TM to ingest - CFE_PSP_MemCpy(ingest, tempTM, pdu_loc); - - #ifdef MAC_DEBUG - OS_printf("AAD = 0x"); - #endif - // Prepare additional authenticated data - for (y = 0; y < sa_ptr->abm_len; y++) - { - aad[y] = ingest[y] & sa_ptr->abm[y]; - #ifdef MAC_DEBUG - OS_printf("%02x", aad[y]); - #endif - } - #ifdef MAC_DEBUG - OS_printf("\n"); - #endif - - gcry_error = gcry_cipher_open( - &(tmp_hd), - GCRY_CIPHER_AES256, - GCRY_CIPHER_MODE_GCM, - GCRY_CIPHER_CBC_MAC - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setkey( - tmp_hd, - &(ek_ring[sa_ptr->ekid].value[0]), - KEY_SIZE - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_setiv( - tmp_hd, - &(sa_ptr->iv[0]), - sa_ptr->iv_len - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_encrypt( - tmp_hd, - &(ingest[pdu_loc]), // ciphertext output - pdu_len, // length of data - &(tempTM[pdu_loc]), // plaintext input - pdu_len // in data length - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_authenticate( - tmp_hd, - &(aad[0]), // additional authenticated data - sa_ptr->abm_len // length of AAD - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - gcry_error = gcry_cipher_gettag( - tmp_hd, - &(ingest[mac_loc]), // tag output - MAC_SIZE // tag size - ); - if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) - { - OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); - status = OS_ERROR; - return status; - } - - #ifdef MAC_DEBUG - OS_printf("MAC = 0x"); - for(x = 0; x < MAC_SIZE; x++) - { - OS_printf("%02x", (uint8) ingest[x + mac_loc]); - } - OS_printf("\n"); - #endif - - // Update OCF - y = 0; - for (x = OCF_SIZE; x > 0; x--) - { - ingest[fecf_loc - x] = tm_frame.tm_sec_trailer.ocf[y++]; - } - - // Update FECF - tm_frame.tm_sec_trailer.fecf = Crypto_Calc_FECF((char*) ingest, fecf_loc - 1); - ingest[fecf_loc] = (uint8) ((tm_frame.tm_sec_trailer.fecf & 0xFF00) >> 8); - ingest[fecf_loc + 1] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); - } - // Authentication - else if ((sa_ptr->est == 0) && - (sa_ptr->ast == 1)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TM - AUTHENTICATED! \n" RESET); - #endif - // TODO: Future work. Operationally same as clear. - CFE_PSP_MemCpy(ingest, tempTM, count); - } - // Encryption - else if ((sa_ptr->est == 1) && - (sa_ptr->ast == 0)) - { - #ifdef DEBUG - OS_printf(KBLU "Creating a TM - ENCRYPTED! \n" RESET); - #endif - // TODO: Future work. Operationally same as clear. - CFE_PSP_MemCpy(ingest, tempTM, count); - } - - #ifdef TM_DEBUG - Crypto_tmPrint(&tm_frame); - #endif - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_TM_ApplySecurity END -----\n" RESET); - #endif - - *len_ingest = count; - return status; -} - -int32 Crypto_TM_ProcessSecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_TM_ProcessSecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_TM_ProcessSecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_AOS_ApplySecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_AOS_ApplySecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_AOS_ApplySecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_AOS_ProcessSecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_AOS_ProcessSecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_AOS_ProcessSecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_ApplySecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_ApplySecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_ApplySecurity END -----\n" RESET); - #endif - - return status; -} - -int32 Crypto_ProcessSecurity(char* ingest, int* len_ingest) -{ - // Local Variables - int32 status = OS_SUCCESS; - - #ifdef DEBUG - OS_printf(KYEL "\n----- Crypto_ProcessSecurity START -----\n" RESET); - #endif - - // TODO: This whole function! - len_ingest = len_ingest; - ingest[0] = ingest[0]; - - #ifdef DEBUG - OS_printf(KYEL "----- Crypto_ProcessSecurity END -----\n" RESET); - #endif - - return status; -} - +/* Copyright (C) 2009 - 2022 National Aeronautics and Space Administration. All Foreign Rights are Reserved to the U.S. Government. + + This software is provided "as is" without any warranty of any kind, either expressed, implied, or statutory, including, but not + limited to, any warranty that the software will conform to specifications, any implied warranties of merchantability, fitness + for a particular purpose, and freedom from infringement, and any warranty that the documentation will conform to the program, or + any warranty that the software will be error free. + + In no event shall NASA be liable for any damages, including, but not limited to direct, indirect, special or consequential damages, + arising out of, resulting from, or in any way connected with the software or its documentation, whether or not based upon warranty, + contract, tort or otherwise, and whether or not loss was sustained from, or arose out of the results of, or use of, the software, + documentation or services provided hereunder. + + ITC Team + NASA IV&V + jstar-development-team@mail.nasa.gov +*/ +#ifndef _crypto_c_ +#define _crypto_c_ + +/* +** Includes +*/ +#include "crypto.h" +#include "sadb_routine.h" + +// #include "itc_aes128.h" +// #include "itc_gcm128.h" + +#include "crypto_structs.h" +#include "crypto_config_structs.h" +#include "crypto_print.h" +#include "crypto_config.h" +#include "crypto_events.h" +#include "crypto_error.h" + + + +#include + + +/* +** Static Library Declaration +*/ +#ifdef BUILD_STATIC + CFS_MODULE_DECLARE_LIB(crypto); +#endif + +static SadbRoutine sadb_routine = NULL; + +/* +** Static Prototypes +*/ +// Assisting Functions +static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame, SecurityAssociation_t *sa_ptr); +static int32 Crypto_Get_tmLength(int len); +static void Crypto_TM_updatePDU(char* ingest, int len_ingest); +static void Crypto_TM_updateOCF(void); +static void Crypto_Local_Config(void); +static void Crypto_Local_Init(void); +//static int32 Crypto_gcm_err(int gcm_err); +static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window); +static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length); +static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame); +static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest); +static void Crypto_Calc_CRC_Init_Table(void); +static uint16 Crypto_Calc_CRC16(char* data, int size); +// Key Management Functions +static int32 Crypto_Key_OTAR(void); +static int32 Crypto_Key_update(uint8 state); +static int32 Crypto_Key_inventory(char*); +static int32 Crypto_Key_verify(char*,TC_t* tc_frame); +// Security Monitoring & Control Procedure +static int32 Crypto_MC_ping(char* ingest); +static int32 Crypto_MC_status(char* ingest); +static int32 Crypto_MC_dump(char* ingest); +static int32 Crypto_MC_erase(char* ingest); +static int32 Crypto_MC_selftest(char* ingest); +static int32 Crypto_SA_readARSN(char* ingest); +static int32 Crypto_MC_resetalarm(void); +// User Functions +static int32 Crypto_User_IdleTrigger(char* ingest); +static int32 Crypto_User_BadSPI(void); +static int32 Crypto_User_BadIV(void); +static int32 Crypto_User_BadMAC(void); +static int32 Crypto_User_BadFECF(void); +static int32 Crypto_User_ModifyKey(void); +static int32 Crypto_User_ModifyActiveTM(void); +static int32 Crypto_User_ModifyVCID(void); +// Determine Payload Data Unit +static int32 Crypto_PDU(char* ingest, TC_t* tc_frame); +// Managed Parameter Functions +static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, + GvcidManagedParameters_t** managed_parameters_out); +static int32 crypto_config_add_gvcid_managed_parameter_recursion(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr,GvcidManagedParameters_t* managed_parameter); +static void Crypto_Free_Managed_Parameters(GvcidManagedParameters_t* managed_parameters); + +/* +** Global Variables +*/ +// Security +crypto_key_t ek_ring[NUM_KEYS] = {0}; +//static crypto_key_t ak_ring[NUM_KEYS]; +CCSDS_t sdls_frame; +TM_t tm_frame; +CryptoConfig_t* crypto_config = NULL; +SadbMariaDBConfig_t* sadb_mariadb_config = NULL; +GvcidManagedParameters_t* gvcid_managed_parameters = NULL; +GvcidManagedParameters_t* current_managed_parameters = NULL; +// OCF +static uint8 ocf = 0; +static SDLS_FSR_t report; +static TM_FrameCLCW_t clcw; +// Flags +static SDLS_MC_LOG_RPLY_t log_summary; +static SDLS_MC_DUMP_BLK_RPLY_t log; +static uint8 log_count = 0; +static uint16 tm_offset = 0; +// ESA Testing - 0 = disabled, 1 = enabled +static uint8 badSPI = 0; +static uint8 badIV = 0; +static uint8 badMAC = 0; +static uint8 badFECF = 0; +// CRC +static uint32 crc32Table[256]; +static uint16 crc16Table[256]; +/* +** Initialization Functions +*/ +int32 Crypto_Init_Unit_Test(void) +{ + int32 status = OS_SUCCESS; + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE,0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); + status = Crypto_Init(); + return status; +} +int32 Crypto_Init_With_Configs(CryptoConfig_t* crypto_config_p,GvcidManagedParameters_t* gvcid_managed_parameters_p,SadbMariaDBConfig_t* sadb_mariadb_config_p) +{ + int32 status = OS_SUCCESS; + crypto_config = crypto_config_p; + gvcid_managed_parameters = gvcid_managed_parameters_p; + sadb_mariadb_config = sadb_mariadb_config_p; + status = Crypto_Init(); + return status; +} + +int32 Crypto_Init(void) +{ + int32 status = OS_SUCCESS; + + if(crypto_config==NULL){ + status = CRYPTO_CONFIGURATION_NOT_COMPLETE; + OS_printf(KRED "ERROR: CryptoLib must be configured before intializing!\n" RESET); + return status; //No configuration set -- return! + } + if(gvcid_managed_parameters==NULL){ + status = CRYPTO_MANAGED_PARAM_CONFIGURATION_NOT_COMPLETE; + OS_printf(KRED "ERROR: CryptoLib Managed Parameters must be configured before intializing!\n" RESET); + return status; //No Managed Parameter configuration set -- return! + } + + #ifdef TC_DEBUG + Crypto_mpPrint(gvcid_managed_parameters,1); + #endif + + //Prepare SADB type from config + if (crypto_config->sadb_type == SADB_TYPE_INMEMORY){ sadb_routine = get_sadb_routine_inmemory(); } + else if (crypto_config->sadb_type == SADB_TYPE_MARIADB){ + if(sadb_mariadb_config == NULL){ + status = CRYPTO_MARIADB_CONFIGURATION_NOT_COMPLETE; + OS_printf(KRED "ERROR: CryptoLib MariaDB must be configured before intializing!\n" RESET); + return status; //MariaDB connection specified but no configuration exists, return! + } + sadb_routine = get_sadb_routine_mariadb(); + } + else { status = SADB_INVALID_SADB_TYPE; return status; } //TODO: Error stack + + // Initialize libgcrypt + if (!gcry_check_version(GCRYPT_VERSION)) + { + fprintf(stderr, "Gcrypt Version: %s",GCRYPT_VERSION); + OS_printf(KRED "\tERROR: gcrypt version mismatch! \n" RESET); + } + if (gcry_control(GCRYCTL_SELFTEST) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcrypt self test failed\n" RESET); + } + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + + // Init Security Associations + status = sadb_routine->sadb_init(); + status = sadb_routine->sadb_config(); + + Crypto_Local_Init(); + Crypto_Local_Config(); + + // TODO - Add error checking + + // Init table for CRC calculations + Crypto_Calc_CRC_Init_Table(); + + // cFS Standard Initialized Message + OS_printf (KBLU "Crypto Lib Intialized. Version %d.%d.%d.%d\n" RESET, + CRYPTO_LIB_MAJOR_VERSION, + CRYPTO_LIB_MINOR_VERSION, + CRYPTO_LIB_REVISION, + CRYPTO_LIB_MISSION_REV); + + return status; +} + +//Free memory objects & restore pointers to NULL for re-initialization +int32 Crypto_Shutdown(void) +{ + int32 status = OS_SUCCESS; + + if(crypto_config!=NULL){ + free(crypto_config); + crypto_config=NULL; + } + if(sadb_mariadb_config!=NULL){ + free(sadb_mariadb_config); + sadb_mariadb_config=NULL; + } + current_managed_parameters=NULL; + + if(gvcid_managed_parameters!=NULL){ + Crypto_Free_Managed_Parameters(gvcid_managed_parameters); + gvcid_managed_parameters=NULL; + } + + return status; +} + + +int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 process_sdls_pdus, uint8 has_pus_hdr, uint8 ignore_sa_state, uint8 ignore_anti_replay, uint8 vcid_bitmask) +{ + int32 status = OS_SUCCESS; + crypto_config = (CryptoConfig_t*) calloc(1, CRYPTO_CONFIG_SIZE); + crypto_config->sadb_type=sadb_type; + crypto_config->crypto_create_fecf=crypto_create_fecf; + crypto_config->process_sdls_pdus=process_sdls_pdus; + crypto_config->has_pus_hdr=has_pus_hdr; + crypto_config->ignore_sa_state=ignore_sa_state; + crypto_config->ignore_anti_replay=ignore_anti_replay; + crypto_config->vcid_bitmask=vcid_bitmask; + return status; +} +int32 Crypto_Config_MariaDB(char* mysql_username, char* mysql_password, char* mysql_hostname, char* mysql_database, uint16 mysql_port) +{ + int32 status = OS_SUCCESS; + sadb_mariadb_config = (SadbMariaDBConfig_t*)calloc(1, SADB_MARIADB_CONFIG_SIZE); + sadb_mariadb_config->mysql_username=mysql_username; + sadb_mariadb_config->mysql_password=mysql_password; + sadb_mariadb_config->mysql_hostname=mysql_hostname; + sadb_mariadb_config->mysql_database=mysql_database; + sadb_mariadb_config->mysql_port=mysql_port; + return status; +} +int32 Crypto_Config_Add_Gvcid_Managed_Parameter(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr) +{ + int32 status = OS_SUCCESS; + + if(gvcid_managed_parameters==NULL){//case: Global Root Node not Set + gvcid_managed_parameters = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); + gvcid_managed_parameters->tfvn=tfvn; + gvcid_managed_parameters->scid=scid; + gvcid_managed_parameters->vcid=vcid; + gvcid_managed_parameters->has_fecf=has_fecf; + gvcid_managed_parameters->has_segmentation_hdr=has_segmentation_hdr; + gvcid_managed_parameters->next=NULL; + return status; + } else { //Recurse through nodes and add at end + return crypto_config_add_gvcid_managed_parameter_recursion(tfvn, scid, vcid, has_fecf, has_segmentation_hdr,gvcid_managed_parameters); + } + +} + +static int32 crypto_config_add_gvcid_managed_parameter_recursion(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr,GvcidManagedParameters_t* managed_parameter) +{ + if(managed_parameter->next!=NULL){ + return crypto_config_add_gvcid_managed_parameter_recursion(tfvn, scid, vcid, has_fecf, has_segmentation_hdr,managed_parameter->next); + } else { + managed_parameter->next = (GvcidManagedParameters_t*) calloc(1,GVCID_MANAGED_PARAMETERS_SIZE); + managed_parameter->next->tfvn = tfvn; + managed_parameter->next->scid = scid; + managed_parameter->next->vcid = vcid; + managed_parameter->next->has_fecf = has_fecf; + managed_parameter->next->has_segmentation_hdr = has_segmentation_hdr; + managed_parameter->next->next = NULL; + return OS_SUCCESS; + } +} + +static void Crypto_Local_Config(void) +{ + // Initial TM configuration + tm_frame.tm_sec_header.spi = 1; + + // Initialize Log + log_summary.num_se = 2; + log_summary.rs = LOG_SIZE; + // Add a two messages to the log + log_summary.rs--; + log.blk[log_count].emt = STARTUP; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + log_summary.rs--; + log.blk[log_count].emt = STARTUP; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + + // Master Keys + // 0 - 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F -> ACTIVE + ek_ring[0].value[0] = 0x00; + ek_ring[0].value[1] = 0x01; + ek_ring[0].value[2] = 0x02; + ek_ring[0].value[3] = 0x03; + ek_ring[0].value[4] = 0x04; + ek_ring[0].value[5] = 0x05; + ek_ring[0].value[6] = 0x06; + ek_ring[0].value[7] = 0x07; + ek_ring[0].value[8] = 0x08; + ek_ring[0].value[9] = 0x09; + ek_ring[0].value[10] = 0x0A; + ek_ring[0].value[11] = 0x0B; + ek_ring[0].value[12] = 0x0C; + ek_ring[0].value[13] = 0x0D; + ek_ring[0].value[14] = 0x0E; + ek_ring[0].value[15] = 0x0F; + ek_ring[0].value[16] = 0x00; + ek_ring[0].value[17] = 0x01; + ek_ring[0].value[18] = 0x02; + ek_ring[0].value[19] = 0x03; + ek_ring[0].value[20] = 0x04; + ek_ring[0].value[21] = 0x05; + ek_ring[0].value[22] = 0x06; + ek_ring[0].value[23] = 0x07; + ek_ring[0].value[24] = 0x08; + ek_ring[0].value[25] = 0x09; + ek_ring[0].value[26] = 0x0A; + ek_ring[0].value[27] = 0x0B; + ek_ring[0].value[28] = 0x0C; + ek_ring[0].value[29] = 0x0D; + ek_ring[0].value[30] = 0x0E; + ek_ring[0].value[31] = 0x0F; + ek_ring[0].key_state = KEY_ACTIVE; + // 1 - 101112131415161718191A1B1C1D1E1F101112131415161718191A1B1C1D1E1F -> ACTIVE + ek_ring[1].value[0] = 0x10; + ek_ring[1].value[1] = 0x11; + ek_ring[1].value[2] = 0x12; + ek_ring[1].value[3] = 0x13; + ek_ring[1].value[4] = 0x14; + ek_ring[1].value[5] = 0x15; + ek_ring[1].value[6] = 0x16; + ek_ring[1].value[7] = 0x17; + ek_ring[1].value[8] = 0x18; + ek_ring[1].value[9] = 0x19; + ek_ring[1].value[10] = 0x1A; + ek_ring[1].value[11] = 0x1B; + ek_ring[1].value[12] = 0x1C; + ek_ring[1].value[13] = 0x1D; + ek_ring[1].value[14] = 0x1E; + ek_ring[1].value[15] = 0x1F; + ek_ring[1].value[16] = 0x10; + ek_ring[1].value[17] = 0x11; + ek_ring[1].value[18] = 0x12; + ek_ring[1].value[19] = 0x13; + ek_ring[1].value[20] = 0x14; + ek_ring[1].value[21] = 0x15; + ek_ring[1].value[22] = 0x16; + ek_ring[1].value[23] = 0x17; + ek_ring[1].value[24] = 0x18; + ek_ring[1].value[25] = 0x19; + ek_ring[1].value[26] = 0x1A; + ek_ring[1].value[27] = 0x1B; + ek_ring[1].value[28] = 0x1C; + ek_ring[1].value[29] = 0x1D; + ek_ring[1].value[30] = 0x1E; + ek_ring[1].value[31] = 0x1F; + ek_ring[1].key_state = KEY_ACTIVE; + // 2 - 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F -> ACTIVE + ek_ring[2].value[0] = 0x20; + ek_ring[2].value[1] = 0x21; + ek_ring[2].value[2] = 0x22; + ek_ring[2].value[3] = 0x23; + ek_ring[2].value[4] = 0x24; + ek_ring[2].value[5] = 0x25; + ek_ring[2].value[6] = 0x26; + ek_ring[2].value[7] = 0x27; + ek_ring[2].value[8] = 0x28; + ek_ring[2].value[9] = 0x29; + ek_ring[2].value[10] = 0x2A; + ek_ring[2].value[11] = 0x2B; + ek_ring[2].value[12] = 0x2C; + ek_ring[2].value[13] = 0x2D; + ek_ring[2].value[14] = 0x2E; + ek_ring[2].value[15] = 0x2F; + ek_ring[2].value[16] = 0x20; + ek_ring[2].value[17] = 0x21; + ek_ring[2].value[18] = 0x22; + ek_ring[2].value[19] = 0x23; + ek_ring[2].value[20] = 0x24; + ek_ring[2].value[21] = 0x25; + ek_ring[2].value[22] = 0x26; + ek_ring[2].value[23] = 0x27; + ek_ring[2].value[24] = 0x28; + ek_ring[2].value[25] = 0x29; + ek_ring[2].value[26] = 0x2A; + ek_ring[2].value[27] = 0x2B; + ek_ring[2].value[28] = 0x2C; + ek_ring[2].value[29] = 0x2D; + ek_ring[2].value[30] = 0x2E; + ek_ring[2].value[31] = 0x2F; + ek_ring[2].key_state = KEY_ACTIVE; + + // Session Keys + // 128 - 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF -> ACTIVE + ek_ring[128].value[0] = 0x01; + ek_ring[128].value[1] = 0x23; + ek_ring[128].value[2] = 0x45; + ek_ring[128].value[3] = 0x67; + ek_ring[128].value[4] = 0x89; + ek_ring[128].value[5] = 0xAB; + ek_ring[128].value[6] = 0xCD; + ek_ring[128].value[7] = 0xEF; + ek_ring[128].value[8] = 0x01; + ek_ring[128].value[9] = 0x23; + ek_ring[128].value[10] = 0x45; + ek_ring[128].value[11] = 0x67; + ek_ring[128].value[12] = 0x89; + ek_ring[128].value[13] = 0xAB; + ek_ring[128].value[14] = 0xCD; + ek_ring[128].value[15] = 0xEF; + ek_ring[128].value[16] = 0x01; + ek_ring[128].value[17] = 0x23; + ek_ring[128].value[18] = 0x45; + ek_ring[128].value[19] = 0x67; + ek_ring[128].value[20] = 0x89; + ek_ring[128].value[21] = 0xAB; + ek_ring[128].value[22] = 0xCD; + ek_ring[128].value[23] = 0xEF; + ek_ring[128].value[24] = 0x01; + ek_ring[128].value[25] = 0x23; + ek_ring[128].value[26] = 0x45; + ek_ring[128].value[27] = 0x67; + ek_ring[128].value[28] = 0x89; + ek_ring[128].value[29] = 0xAB; + ek_ring[128].value[30] = 0xCD; + ek_ring[128].value[31] = 0xEF; + ek_ring[128].key_state = KEY_ACTIVE; + // 129 - ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 -> ACTIVE + ek_ring[129].value[0] = 0xAB; + ek_ring[129].value[1] = 0xCD; + ek_ring[129].value[2] = 0xEF; + ek_ring[129].value[3] = 0x01; + ek_ring[129].value[4] = 0x23; + ek_ring[129].value[5] = 0x45; + ek_ring[129].value[6] = 0x67; + ek_ring[129].value[7] = 0x89; + ek_ring[129].value[8] = 0xAB; + ek_ring[129].value[9] = 0xCD; + ek_ring[129].value[10] = 0xEF; + ek_ring[129].value[11] = 0x01; + ek_ring[129].value[12] = 0x23; + ek_ring[129].value[13] = 0x45; + ek_ring[129].value[14] = 0x67; + ek_ring[129].value[15] = 0x89; + ek_ring[129].value[16] = 0xAB; + ek_ring[129].value[17] = 0xCD; + ek_ring[129].value[18] = 0xEF; + ek_ring[129].value[19] = 0x01; + ek_ring[129].value[20] = 0x23; + ek_ring[129].value[21] = 0x45; + ek_ring[129].value[22] = 0x67; + ek_ring[129].value[23] = 0x89; + ek_ring[129].value[24] = 0xAB; + ek_ring[129].value[25] = 0xCD; + ek_ring[129].value[26] = 0xEF; + ek_ring[129].value[27] = 0x01; + ek_ring[129].value[28] = 0x23; + ek_ring[129].value[29] = 0x45; + ek_ring[129].value[30] = 0x67; + ek_ring[129].value[31] = 0x89; + ek_ring[129].key_state = KEY_ACTIVE; + // 130 - FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210 -> ACTIVE + ek_ring[130].value[0] = 0xFE; + ek_ring[130].value[1] = 0xDC; + ek_ring[130].value[2] = 0xBA; + ek_ring[130].value[3] = 0x98; + ek_ring[130].value[4] = 0x76; + ek_ring[130].value[5] = 0x54; + ek_ring[130].value[6] = 0x32; + ek_ring[130].value[7] = 0x10; + ek_ring[130].value[8] = 0xFE; + ek_ring[130].value[9] = 0xDC; + ek_ring[130].value[10] = 0xBA; + ek_ring[130].value[11] = 0x98; + ek_ring[130].value[12] = 0x76; + ek_ring[130].value[13] = 0x54; + ek_ring[130].value[14] = 0x32; + ek_ring[130].value[15] = 0x10; + ek_ring[130].value[16] = 0xFE; + ek_ring[130].value[17] = 0xDC; + ek_ring[130].value[18] = 0xBA; + ek_ring[130].value[19] = 0x98; + ek_ring[130].value[20] = 0x76; + ek_ring[130].value[21] = 0x54; + ek_ring[130].value[22] = 0x32; + ek_ring[130].value[23] = 0x10; + ek_ring[130].value[24] = 0xFE; + ek_ring[130].value[25] = 0xDC; + ek_ring[130].value[26] = 0xBA; + ek_ring[130].value[27] = 0x98; + ek_ring[130].value[28] = 0x76; + ek_ring[130].value[29] = 0x54; + ek_ring[130].value[30] = 0x32; + ek_ring[130].value[31] = 0x10; + ek_ring[130].key_state = KEY_ACTIVE; + // 131 - 9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA -> ACTIVE + ek_ring[131].value[0] = 0x98; + ek_ring[131].value[1] = 0x76; + ek_ring[131].value[2] = 0x54; + ek_ring[131].value[3] = 0x32; + ek_ring[131].value[4] = 0x10; + ek_ring[131].value[5] = 0xFE; + ek_ring[131].value[6] = 0xDC; + ek_ring[131].value[7] = 0xBA; + ek_ring[131].value[8] = 0x98; + ek_ring[131].value[9] = 0x76; + ek_ring[131].value[10] = 0x54; + ek_ring[131].value[11] = 0x32; + ek_ring[131].value[12] = 0x10; + ek_ring[131].value[13] = 0xFE; + ek_ring[131].value[14] = 0xDC; + ek_ring[131].value[15] = 0xBA; + ek_ring[131].value[16] = 0x98; + ek_ring[131].value[17] = 0x76; + ek_ring[131].value[18] = 0x54; + ek_ring[131].value[19] = 0x32; + ek_ring[131].value[20] = 0x10; + ek_ring[131].value[21] = 0xFE; + ek_ring[131].value[22] = 0xDC; + ek_ring[131].value[23] = 0xBA; + ek_ring[131].value[24] = 0x98; + ek_ring[131].value[25] = 0x76; + ek_ring[131].value[26] = 0x54; + ek_ring[131].value[27] = 0x32; + ek_ring[131].value[28] = 0x10; + ek_ring[131].value[29] = 0xFE; + ek_ring[131].value[30] = 0xDC; + ek_ring[131].value[31] = 0xBA; + ek_ring[131].key_state = KEY_ACTIVE; + // 132 - 0123456789ABCDEFABCDEF01234567890123456789ABCDEFABCDEF0123456789 -> PRE_ACTIVATION + ek_ring[132].value[0] = 0x01; + ek_ring[132].value[1] = 0x23; + ek_ring[132].value[2] = 0x45; + ek_ring[132].value[3] = 0x67; + ek_ring[132].value[4] = 0x89; + ek_ring[132].value[5] = 0xAB; + ek_ring[132].value[6] = 0xCD; + ek_ring[132].value[7] = 0xEF; + ek_ring[132].value[8] = 0xAB; + ek_ring[132].value[9] = 0xCD; + ek_ring[132].value[10] = 0xEF; + ek_ring[132].value[11] = 0x01; + ek_ring[132].value[12] = 0x23; + ek_ring[132].value[13] = 0x45; + ek_ring[132].value[14] = 0x67; + ek_ring[132].value[15] = 0x89; + ek_ring[132].value[16] = 0x01; + ek_ring[132].value[17] = 0x23; + ek_ring[132].value[18] = 0x45; + ek_ring[132].value[19] = 0x67; + ek_ring[132].value[20] = 0x89; + ek_ring[132].value[21] = 0xAB; + ek_ring[132].value[22] = 0xCD; + ek_ring[132].value[23] = 0xEF; + ek_ring[132].value[24] = 0xAB; + ek_ring[132].value[25] = 0xCD; + ek_ring[132].value[26] = 0xEF; + ek_ring[132].value[27] = 0x01; + ek_ring[132].value[28] = 0x23; + ek_ring[132].value[29] = 0x45; + ek_ring[132].value[30] = 0x67; + ek_ring[132].value[31] = 0x89; + ek_ring[132].key_state = KEY_PREACTIVE; + // 133 - ABCDEF01234567890123456789ABCDEFABCDEF01234567890123456789ABCDEF -> ACTIVE + ek_ring[133].value[0] = 0xAB; + ek_ring[133].value[1] = 0xCD; + ek_ring[133].value[2] = 0xEF; + ek_ring[133].value[3] = 0x01; + ek_ring[133].value[4] = 0x23; + ek_ring[133].value[5] = 0x45; + ek_ring[133].value[6] = 0x67; + ek_ring[133].value[7] = 0x89; + ek_ring[133].value[8] = 0x01; + ek_ring[133].value[9] = 0x23; + ek_ring[133].value[10] = 0x45; + ek_ring[133].value[11] = 0x67; + ek_ring[133].value[12] = 0x89; + ek_ring[133].value[13] = 0xAB; + ek_ring[133].value[14] = 0xCD; + ek_ring[133].value[15] = 0xEF; + ek_ring[133].value[16] = 0xAB; + ek_ring[133].value[17] = 0xCD; + ek_ring[133].value[18] = 0xEF; + ek_ring[133].value[19] = 0x01; + ek_ring[133].value[20] = 0x23; + ek_ring[133].value[21] = 0x45; + ek_ring[133].value[22] = 0x67; + ek_ring[133].value[23] = 0x89; + ek_ring[133].value[24] = 0x01; + ek_ring[133].value[25] = 0x23; + ek_ring[133].value[26] = 0x45; + ek_ring[133].value[27] = 0x67; + ek_ring[133].value[28] = 0x89; + ek_ring[133].value[29] = 0xAB; + ek_ring[133].value[30] = 0xCD; + ek_ring[133].value[31] = 0xEF; + ek_ring[133].key_state = KEY_ACTIVE; + // 134 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE + ek_ring[134].value[0] = 0xAB; + ek_ring[134].value[1] = 0xCD; + ek_ring[134].value[2] = 0xEF; + ek_ring[134].value[3] = 0x01; + ek_ring[134].value[4] = 0x23; + ek_ring[134].value[5] = 0x45; + ek_ring[134].value[6] = 0x67; + ek_ring[134].value[7] = 0x89; + ek_ring[134].value[8] = 0xFE; + ek_ring[134].value[9] = 0xDC; + ek_ring[134].value[10] = 0xBA; + ek_ring[134].value[11] = 0x98; + ek_ring[134].value[12] = 0x76; + ek_ring[134].value[13] = 0x54; + ek_ring[134].value[14] = 0x32; + ek_ring[134].value[15] = 0x10; + ek_ring[134].value[16] = 0xAB; + ek_ring[134].value[17] = 0xCD; + ek_ring[134].value[18] = 0xEF; + ek_ring[134].value[19] = 0x01; + ek_ring[134].value[20] = 0x23; + ek_ring[134].value[21] = 0x45; + ek_ring[134].value[22] = 0x67; + ek_ring[134].value[23] = 0x89; + ek_ring[134].value[24] = 0xFE; + ek_ring[134].value[25] = 0xDC; + ek_ring[134].value[26] = 0xBA; + ek_ring[134].value[27] = 0x98; + ek_ring[134].value[28] = 0x76; + ek_ring[134].value[29] = 0x54; + ek_ring[134].value[30] = 0x32; + ek_ring[134].value[31] = 0x10; + ek_ring[134].key_state = KEY_DEACTIVATED; + + // 135 - ABCDEF0123456789FEDCBA9876543210ABCDEF0123456789FEDCBA9876543210 -> DEACTIVE + ek_ring[135].value[0] = 0x00; + ek_ring[135].value[1] = 0x00; + ek_ring[135].value[2] = 0x00; + ek_ring[135].value[3] = 0x00; + ek_ring[135].value[4] = 0x00; + ek_ring[135].value[5] = 0x00; + ek_ring[135].value[6] = 0x00; + ek_ring[135].value[7] = 0x00; + ek_ring[135].value[8] = 0x00; + ek_ring[135].value[9] = 0x00; + ek_ring[135].value[10] = 0x00; + ek_ring[135].value[11] = 0x00; + ek_ring[135].value[12] = 0x00; + ek_ring[135].value[13] = 0x00; + ek_ring[135].value[14] = 0x00; + ek_ring[135].value[15] = 0x00; + ek_ring[135].value[16] = 0x00; + ek_ring[135].value[17] = 0x00; + ek_ring[135].value[18] = 0x00; + ek_ring[135].value[19] = 0x00; + ek_ring[135].value[20] = 0x00; + ek_ring[135].value[21] = 0x00; + ek_ring[135].value[22] = 0x00; + ek_ring[135].value[23] = 0x00; + ek_ring[135].value[24] = 0x00; + ek_ring[135].value[25] = 0x00; + ek_ring[135].value[26] = 0x00; + ek_ring[135].value[27] = 0x00; + ek_ring[135].value[28] = 0x00; + ek_ring[135].value[29] = 0x00; + ek_ring[135].value[30] = 0x00; + ek_ring[135].value[31] = 0x00; + ek_ring[135].key_state = KEY_DEACTIVATED; + + // 136 - ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8 + // Reference: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/gcmtestvectors.zip + ek_ring[136].value[0] = 0xff; + ek_ring[136].value[1] = 0x9f; + ek_ring[136].value[2] = 0x92; + ek_ring[136].value[3] = 0x84; + ek_ring[136].value[4] = 0xcf; + ek_ring[136].value[5] = 0x59; + ek_ring[136].value[6] = 0x9e; + ek_ring[136].value[7] = 0xac; + ek_ring[136].value[8] = 0x3b; + ek_ring[136].value[9] = 0x11; + ek_ring[136].value[10] = 0x99; + ek_ring[136].value[11] = 0x05; + ek_ring[136].value[12] = 0xa7; + ek_ring[136].value[13] = 0xd1; + ek_ring[136].value[14] = 0x88; + ek_ring[136].value[15] = 0x51; + ek_ring[136].value[16] = 0xe7; + ek_ring[136].value[17] = 0xe3; + ek_ring[136].value[18] = 0x74; + ek_ring[136].value[19] = 0xcf; + ek_ring[136].value[20] = 0x63; + ek_ring[136].value[21] = 0xae; + ek_ring[136].value[22] = 0xa0; + ek_ring[136].value[23] = 0x43; + ek_ring[136].value[24] = 0x58; + ek_ring[136].value[25] = 0x58; + ek_ring[136].value[26] = 0x6b; + ek_ring[136].value[27] = 0x0f; + ek_ring[136].value[28] = 0x75; + ek_ring[136].value[29] = 0x76; + ek_ring[136].value[30] = 0x70; + ek_ring[136].value[31] = 0xf9; + ek_ring[135].key_state = KEY_DEACTIVATED; +} + +static void Crypto_Local_Init(void) +{ + + // Initialize TM Frame + // TM Header + tm_frame.tm_header.tfvn = 0; // Shall be 00 for TM-/TC-SDLP + tm_frame.tm_header.scid = SCID & 0x3FF; + tm_frame.tm_header.vcid = 0; + tm_frame.tm_header.ocff = 1; + tm_frame.tm_header.mcfc = 1; + tm_frame.tm_header.vcfc = 1; + tm_frame.tm_header.tfsh = 0; + tm_frame.tm_header.sf = 0; + tm_frame.tm_header.pof = 0; // Shall be set to 0 + tm_frame.tm_header.slid = 3; // Shall be set to 11 + tm_frame.tm_header.fhp = 0; + // TM Security Header + tm_frame.tm_sec_header.spi = 0x0000; + for ( int x = 0; x < IV_SIZE; x++) + { // Initialization Vector + tm_frame.tm_sec_header.iv[x] = 0x00; + } + // TM Payload Data Unit + for ( int x = 0; x < TM_FRAME_DATA_SIZE; x++) + { // Zero TM PDU + tm_frame.tm_pdu[x] = 0x00; + } + // TM Security Trailer + for ( int x = 0; x < MAC_SIZE; x++) + { // Zero TM Message Authentication Code + tm_frame.tm_sec_trailer.mac[x] = 0x00; + } + for ( int x = 0; x < OCF_SIZE; x++) + { // Zero TM Operational Control Field + tm_frame.tm_sec_trailer.ocf[x] = 0x00; + } + tm_frame.tm_sec_trailer.fecf = 0xFECF; + + // Initialize CLCW + clcw.cwt = 0; // Control Word Type "0" + clcw.cvn = 0; // CLCW Version Number "00" + clcw.sf = 0; // Status Field + clcw.cie = 1; // COP In Effect + clcw.vci = 0; // Virtual Channel Identification + clcw.spare0 = 0; // Reserved Spare + clcw.nrfa = 0; // No RF Avaliable Flag + clcw.nbl = 0; // No Bit Lock Flag + clcw.lo = 0; // Lock-Out Flag + clcw.wait = 0; // Wait Flag + clcw.rt = 0; // Retransmit Flag + clcw.fbc = 0; // FARM-B Counter + clcw.spare1 = 0; // Reserved Spare + clcw.rv = 0; // Report Value + + // Initialize Frame Security Report + report.cwt = 1; // Control Word Type "0b1"" + report.vnum = 4; // FSR Version "0b100"" + report.af = 0; // Alarm Field + report.bsnf = 0; // Bad SN Flag + report.bmacf = 0; // Bad MAC Flag + report.ispif = 0; // Invalid SPI Flag + report.lspiu = 0; // Last SPI Used + report.snval = 0; // SN Value (LSB) + +} + +static void Crypto_Calc_CRC_Init_Table(void) +{ + uint16 val; + uint32 poly = 0xEDB88320; + uint32 crc; + + // http://create.stephan-brumme.com/crc32/ + for (unsigned int i = 0; i <= 0xFF; i++) + { + crc = i; + for (unsigned int j = 0; j < 8; j++) + { + crc = (crc >> 1) ^ (-(int)(crc & 1) & poly); + } + crc32Table[i] = crc; + //OS_printf("crc32Table[%d] = 0x%08x \n", i, crc32Table[i]); + } + + // Code provided by ESA + for (int i = 0; i < 256; i++) + { + val = 0; + if ( (i & 1) != 0 ) val ^= 0x1021; + if ( (i & 2) != 0 ) val ^= 0x2042; + if ( (i & 4) != 0 ) val ^= 0x4084; + if ( (i & 8) != 0 ) val ^= 0x8108; + if ( (i & 16) != 0 ) val ^= 0x1231; + if ( (i & 32) != 0 ) val ^= 0x2462; + if ( (i & 64) != 0 ) val ^= 0x48C4; + if ( (i & 128) != 0 ) val ^= 0x9188; + crc16Table[i] = val; + //OS_printf("crc16Table[%d] = 0x%04x \n", i, crc16Table[i]); + } +} + +/* +** Assisting Functions +*/ +static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame, SecurityAssociation_t *sa_ptr) +// Returns the payload length of current tc_frame in BYTES! +{ + int tf_hdr = 5; + int seg_hdr = 0;if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){seg_hdr=1;} + int fecf = 0;if(current_managed_parameters->has_fecf==TC_HAS_FECF){fecf=FECF_SIZE;} + int spi = 2; + int iv_size = sa_ptr->shivf_len; if(crypto_config->has_pus_hdr==TC_HAS_PUS_HDR){iv_size=sa_ptr->shivf_len - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. + int mac_size = sa_ptr->stmacf_len; + + #ifdef TC_DEBUG + OS_printf("Get_tcPayloadLength Debug [byte lengths]:\n"); + OS_printf("\thdr.fl\t%d\n", tc_frame->tc_header.fl); + OS_printf("\ttf_hdr\t%d\n",tf_hdr); + OS_printf("\tSeg hdr\t%d\t\n",seg_hdr); + OS_printf("\tspi \t%d\n",spi); + OS_printf("\tiv_size\t%d\n",iv_size); + OS_printf("\tmac\t%d\n",mac_size); + OS_printf("\tfecf \t%d\n",fecf); + OS_printf("\tTOTAL LENGTH: %d\n", (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + fecf))); + #endif + + return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + fecf) ); +} + +static int32 Crypto_Get_tmLength(int len) +// Returns the total length of the current tm_frame in BYTES! +{ + #ifdef FILL + len = TM_FILL_SIZE; + #else + len = TM_FRAME_PRIMARYHEADER_SIZE + TM_FRAME_SECHEADER_SIZE + len + TM_FRAME_SECTRAILER_SIZE + TM_FRAME_CLCW_SIZE; + #endif + + return len; +} + +static void Crypto_TM_updatePDU(char* ingest, int len_ingest) +// Update the Telemetry Payload Data Unit +{ // Copy ingest to PDU + int x = 0; + int fill_size = 0; + SecurityAssociation_t* sa_ptr; + + if(sadb_routine->sadb_get_sa_from_spi(tm_frame.tm_sec_header.spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return; //Error -- unable to get SA from SPI. + } + + if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) + { + fill_size = 1129 - MAC_SIZE - IV_SIZE + 2; // +2 for padding bytes + } + else + { + fill_size = 1129; + } + + #ifdef TM_ZERO_FILL + for (int x = 0; x < TM_FILL_SIZE; x++) + { + if (x < len_ingest) + { // Fill + tm_frame.tm_pdu[x] = (uint8)ingest[x]; + } + else + { // Zero + tm_frame.tm_pdu[x] = 0x00; + } + } + #else + // Pre-append remaining packet if exist + if (tm_offset == 63) + { + tm_frame.tm_pdu[x++] = 0xff; + tm_offset--; + } + if (tm_offset == 62) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (tm_offset == 61) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (tm_offset == 60) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (tm_offset == 59) + { + tm_frame.tm_pdu[x++] = 0x39; + tm_offset--; + } + while (x < tm_offset) + { + tm_frame.tm_pdu[x] = 0x00; + x++; + } + // Copy actual packet + while (x < len_ingest + tm_offset) + { + //OS_printf("ingest[x - tm_offset] = 0x%02x \n", (uint8)ingest[x - tm_offset]); + tm_frame.tm_pdu[x] = (uint8)ingest[x - tm_offset]; + x++; + } + #ifdef TM_IDLE_FILL + // Check for idle frame trigger + if (((uint8)ingest[0] == 0x08) && ((uint8)ingest[1] == 0x90)) + { + // Don't fill idle frames + } + else + { + while (x < (fill_size - 64) ) + { + tm_frame.tm_pdu[x++] = 0x07; + tm_frame.tm_pdu[x++] = 0xff; + tm_frame.tm_pdu[x++] = 0x00; + tm_frame.tm_pdu[x++] = 0x00; + tm_frame.tm_pdu[x++] = 0x00; + tm_frame.tm_pdu[x++] = 0x39; + for (int y = 0; y < 58; y++) + { + tm_frame.tm_pdu[x++] = 0x00; + } + } + // Add partial packet, if possible, and set offset + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x07; + tm_offset = 63; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0xff; + tm_offset--; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x00; + tm_offset--; + } + if (x < fill_size) + { + tm_frame.tm_pdu[x++] = 0x39; + tm_offset--; + } + for (int y = 0; x < fill_size; y++) + { + tm_frame.tm_pdu[x++] = 00; + tm_offset--; + } + } + while (x < TM_FILL_SIZE) + { + tm_frame.tm_pdu[x++] = 0x00; + } + #endif + #endif + + return; +} + +static void Crypto_TM_updateOCF(void) +{ + if (ocf == 0) + { // CLCW + clcw.vci = tm_frame.tm_header.vcid; + + tm_frame.tm_sec_trailer.ocf[0] = (clcw.cwt << 7) | (clcw.cvn << 5) | (clcw.sf << 2) | (clcw.cie); + tm_frame.tm_sec_trailer.ocf[1] = (clcw.vci << 2) | (clcw.spare0); + tm_frame.tm_sec_trailer.ocf[2] = (clcw.nrfa << 7) | (clcw.nbl << 6) | (clcw.lo << 5) | (clcw.wait << 4) | (clcw.rt << 3) | (clcw.fbc << 1) | (clcw.spare1); + tm_frame.tm_sec_trailer.ocf[3] = (clcw.rv); + // Alternate OCF + ocf = 1; + #ifdef OCF_DEBUG + Crypto_clcwPrint(&clcw); + #endif + } + else + { // FSR + tm_frame.tm_sec_trailer.ocf[0] = (report.cwt << 7) | (report.vnum << 4) | (report.af << 3) | (report.bsnf << 2) | (report.bmacf << 1) | (report.ispif); + tm_frame.tm_sec_trailer.ocf[1] = (report.lspiu & 0xFF00) >> 8; + tm_frame.tm_sec_trailer.ocf[2] = (report.lspiu & 0x00FF); + tm_frame.tm_sec_trailer.ocf[3] = (report.snval); + // Alternate OCF + ocf = 0; + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + } +} + +//TODO - Review this. Not sure it quite works how we think +int32 Crypto_increment(uint8 *num, int length) +{ + int i; + /* go from right (least significant) to left (most signifcant) */ + for(i = length - 1; i >= 0; --i) + { + ++(num[i]); /* increment current byte */ + + if(num[i] != 0) /* if byte did not overflow, we're done! */ + break; + } + + if(i < 0) /* this means num[0] was incremented and overflowed */ + return OS_ERROR; + else + return OS_SUCCESS; +} + +static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window) +{ + int status = OS_ERROR; + int result = 0; + uint8 temp[length]; + + CFE_PSP_MemCpy(temp, expected, length); + + for (int i = 0; i < window; i++) + { + result = 0; + /* go from right (least significant) to left (most signifcant) */ + for (int j = length - 1; j >= 0; --j) + { + if (actual[j] == temp[j]) + { + result++; + } + } + if (result == length) + { + status = OS_SUCCESS; + break; + } + Crypto_increment(&temp[0], length); + } + return status; +} + +static int32 Crypto_compare_less_equal(uint8 *actual, uint8 *expected, int length) +{ + int status = OS_ERROR; + + for(int i = 0; i < length - 1; i++) + { + if (actual[i] > expected[i]) + { + status = OS_SUCCESS; + break; + } + else if (actual[i] < expected[i]) + { + status = OS_ERROR; + break; + } + } + return status; +} + +uint8 Crypto_Prep_Reply(char* ingest, uint8 appID) +// Assumes that both the pkt_length and pdu_len are set properly +{ + uint8 count = 0; + + // Prepare CCSDS for reply + sdls_frame.hdr.pvn = 0; + sdls_frame.hdr.type = 0; + sdls_frame.hdr.shdr = 1; + sdls_frame.hdr.appID = appID; + + sdls_frame.pdu.type = 1; + + // Fill ingest with reply header + ingest[count++] = (sdls_frame.hdr.pvn << 5) | (sdls_frame.hdr.type << 4) | (sdls_frame.hdr.shdr << 3) | ((sdls_frame.hdr.appID & 0x700 >> 8)); + ingest[count++] = (sdls_frame.hdr.appID & 0x00FF); + ingest[count++] = (sdls_frame.hdr.seq << 6) | ((sdls_frame.hdr.pktid & 0x3F00) >> 8); + ingest[count++] = (sdls_frame.hdr.pktid & 0x00FF); + ingest[count++] = (sdls_frame.hdr.pkt_length & 0xFF00) >> 8; + ingest[count++] = (sdls_frame.hdr.pkt_length & 0x00FF); + + // Fill ingest with PUS + //ingest[count++] = (sdls_frame.pus.shf << 7) | (sdls_frame.pus.pusv << 4) | (sdls_frame.pus.ack); + //ingest[count++] = (sdls_frame.pus.st); + //ingest[count++] = (sdls_frame.pus.sst); + //ingest[count++] = (sdls_frame.pus.sid << 4) | (sdls_frame.pus.spare); + + // Fill ingest with Tag and Length + ingest[count++] = (sdls_frame.pdu.type << 7) | (sdls_frame.pdu.uf << 6) | (sdls_frame.pdu.sg << 4) | (sdls_frame.pdu.pid); + ingest[count++] = (sdls_frame.pdu.pdu_len & 0xFF00) >> 8; + ingest[count++] = (sdls_frame.pdu.pdu_len & 0x00FF); + + return count; +} + +static int32 Crypto_FECF(int fecf, char* ingest, int len_ingest,TC_t* tc_frame) +// Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) +{ + int32 result = OS_SUCCESS; + uint16 calc_fecf = Crypto_Calc_FECF(ingest, len_ingest); + + if ( (fecf & 0xFFFF) != calc_fecf ) + { + if (((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) + { + // User packet check only used for ESA Testing! + } + else + { // TODO: Error Correction + OS_printf(KRED "Error: FECF incorrect!\n" RESET); + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = FECF_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + #ifdef FECF_DEBUG + OS_printf("\t Calculated = 0x%04x \n\t Received = 0x%04x \n", calc_fecf, tc_frame->tc_sec_trailer.fecf); + #endif + result = OS_ERROR; + } + } + + return result; +} + +static uint16 Crypto_Calc_FECF(char* ingest, int len_ingest) +// Calculate the Frame Error Control Field (FECF), also known as a cyclic redundancy check (CRC) +{ + uint16 fecf = 0xFFFF; + uint16 poly = 0x1021; // TODO: This polynomial is (CRC-CCITT) for ESA testing, may not match standard protocol + uint8 bit; + uint8 c15; + + for (int i = 0; i < len_ingest; i++) + { // Byte Logic + for (int j = 0; j < 8; j++) + { // Bit Logic + bit = ((ingest[i] >> (7 - j) & 1) == 1); + c15 = ((fecf >> 15 & 1) == 1); + fecf <<= 1; + if (c15 ^ bit) + { + fecf ^= poly; + } + } + } + // Check if Testing + if (badFECF == 1) + { + fecf++; + } + + #ifdef FECF_DEBUG + OS_printf(KCYN "Crypto_Calc_FECF: 0x%02x%02x%02x%02x%02x, len_ingest = %d\n" RESET, ingest[0], ingest[1], ingest[2], ingest[3], ingest[4], len_ingest); + OS_printf(KCYN "0x" RESET); + for (int x = 0; x < len_ingest; x++) + { + OS_printf(KCYN "%02x" RESET, (uint8)*(ingest+x)); + } + OS_printf(KCYN "\n" RESET); + OS_printf(KCYN "In Crypto_Calc_FECF! fecf = 0x%04x\n" RESET, fecf); + #endif + + return fecf; +} + +static uint16 Crypto_Calc_CRC16(char* data, int size) +{ // Code provided by ESA + uint16 crc = 0xFFFF; + + for ( ; size > 0; size--) + { + //OS_printf("*data = 0x%02x \n", (uint8) *data); + crc = ((crc << 8) & 0xFF00) ^ crc16Table[(crc >> 8) ^ *data++]; + } + + return crc; +} + +/* +** Key Management Services +*/ +static int32 Crypto_Key_OTAR(void) +// The OTAR Rekeying procedure shall have the following Service Parameters: +// a- Key ID of the Master Key (Integer, unmanaged) +// b- Size of set of Upload Keys (Integer, managed) +// c- Set of Upload Keys (Integer[Session Key]; managed) +// NOTE- The size of the session keys is mission specific. +// a- Set of Key IDs of Upload Keys (Integer[Key IDs]; managed) +// b- Set of Encrypted Upload Keys (Integer[Size of set of Key ID]; unmanaged) +// c- Agreed Cryptographic Algorithm (managed) +{ + // Local variables + SDLS_OTAR_t packet; + int count = 0; + int x = 0; + int32 status = OS_SUCCESS; + int pdu_keys = (sdls_frame.pdu.pdu_len - 30) / (2 + KEY_SIZE); + + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + + // Master Key ID + packet.mkid = (sdls_frame.pdu.data[0] << 8) | (sdls_frame.pdu.data[1]); + + if (packet.mkid >= 128) + { + report.af = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = MKID_INVALID_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: MKID is not valid! \n" RESET); + status = OS_ERROR; + return status; + } + + for (int count = 2; count < (2 + IV_SIZE); count++) + { // Initialization Vector + packet.iv[count-2] = sdls_frame.pdu.data[count]; + //OS_printf("packet.iv[%d] = 0x%02x\n", count-2, packet.iv[count-2]); + } + + count = sdls_frame.pdu.pdu_len - MAC_SIZE; + for (int w = 0; w < 16; w++) + { // MAC + packet.mac[w] = sdls_frame.pdu.data[count + w]; + //OS_printf("packet.mac[%d] = 0x%02x\n", w, packet.mac[w]); + } + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[packet.mkid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(packet.iv[0]), + IV_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_decrypt( + tmp_hd, + &(sdls_frame.pdu.data[14]), // plaintext output + pdu_keys * (2 + KEY_SIZE), // length of data + NULL, // in place decryption + 0 // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_checktag( + tmp_hd, + &(packet.mac[0]), // tag input + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_cipher_close(tmp_hd); + + // Read in Decrypted Data + for (int count = 14; x < pdu_keys; x++) + { // Encrypted Key Blocks + packet.EKB[x].ekid = (sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1]); + if (packet.EKB[x].ekid < 128) + { + report.af = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = OTAR_MK_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; // N + log.blk[log_count].emv[1] = 0x41; // A + log.blk[log_count].emv[2] = 0x53; // S + log.blk[log_count].emv[3] = 0x41; // A + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: Cannot OTAR master key! \n" RESET); + status = OS_ERROR; + return status; + } + else + { + count = count + 2; + for (int y = count; y < (KEY_SIZE + count); y++) + { // Encrypted Key + packet.EKB[x].ek[y-count] = sdls_frame.pdu.data[y]; + #ifdef SA_DEBUG + OS_printf("\t packet.EKB[%d].ek[%d] = 0x%02x\n", x, y-count, packet.EKB[x].ek[y-count]); + #endif + + // Setup Key Ring + ek_ring[packet.EKB[x].ekid].value[y - count] = sdls_frame.pdu.data[y]; + } + count = count + KEY_SIZE; + + // Set state to PREACTIVE + ek_ring[packet.EKB[x].ekid].key_state = KEY_PREACTIVE; + } + } + + #ifdef PDU_DEBUG + OS_printf("Received %d keys via master key %d: \n", pdu_keys, packet.mkid); + for (int x = 0; x < pdu_keys; x++) + { + OS_printf("%d) Key ID = %d, 0x", x+1, packet.EKB[x].ekid); + for(int y = 0; y < KEY_SIZE; y++) + { + OS_printf("%02x", packet.EKB[x].ek[y]); + } + OS_printf("\n"); + } + #endif + + return OS_SUCCESS; +} + +static int32 Crypto_Key_update(uint8 state) +// Updates the state of the all keys in the received SDLS EP PDU +{ // Local variables + SDLS_KEY_BLK_t packet; + int count = 0; + int pdu_keys = sdls_frame.pdu.pdu_len / 2; + #ifdef PDU_DEBUG + OS_printf("Keys "); + #endif + // Read in PDU + for (int x = 0; x < pdu_keys; x++) + { + packet.kblk[x].kid = (sdls_frame.pdu.data[count] << 8) | (sdls_frame.pdu.data[count+1]); + count = count + 2; + #ifdef PDU_DEBUG + if (x != (pdu_keys - 1)) + { + OS_printf("%d, ", packet.kblk[x].kid); + } + else + { + OS_printf("and %d ", packet.kblk[x].kid); + } + #endif + } + #ifdef PDU_DEBUG + OS_printf("changed to state "); + switch (state) + { + case KEY_PREACTIVE: + OS_printf("PREACTIVE. \n"); + break; + case KEY_ACTIVE: + OS_printf("ACTIVE. \n"); + break; + case KEY_DEACTIVATED: + OS_printf("DEACTIVATED. \n"); + break; + case KEY_DESTROYED: + OS_printf("DESTROYED. \n"); + break; + case KEY_CORRUPTED: + OS_printf("CORRUPTED. \n"); + break; + default: + OS_printf("ERROR. \n"); + break; + } + #endif + // Update Key State + for (int x = 0; x < pdu_keys; x++) + { + if (packet.kblk[x].kid < 128) + { + report.af = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = MKID_STATE_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: MKID state cannot be changed! \n" RESET); + // TODO: Exit + } + + if (ek_ring[packet.kblk[x].kid].key_state == (state - 1)) + { + ek_ring[packet.kblk[x].kid].key_state = state; + #ifdef PDU_DEBUG + //OS_printf("Key ID %d state changed to ", packet.kblk[x].kid); + #endif + } + else + { + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = KEY_TRANSITION_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: Key %d cannot transition to desired state! \n" RESET, packet.kblk[x].kid); + } + } + return OS_SUCCESS; +} + +static int32 Crypto_Key_inventory(char* ingest) +{ + // Local variables + SDLS_KEY_INVENTORY_t packet; + int count = 0; + uint16_t range = 0; + + // Read in PDU + packet.kid_first = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); + count = count + 2; + packet.kid_last = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); + count = count + 2; + + // Prepare for Reply + range = packet.kid_last - packet.kid_first; + sdls_frame.pdu.pdu_len = 2 + (range * (2 + 1)); + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + ingest[count++] = (range & 0xFF00) >> 8; + ingest[count++] = (range & 0x00FF); + for (uint16_t x = packet.kid_first; x < packet.kid_last; x++) + { // Key ID + ingest[count++] = (x & 0xFF00) >> 8; + ingest[count++] = (x & 0x00FF); + // Key State + ingest[count++] = ek_ring[x].key_state; + } + return count; +} + +static int32 Crypto_Key_verify(char* ingest,TC_t* tc_frame) +{ + // Local variables + SDLS_KEYV_CMD_t packet; + int count = 0; + int pdu_keys = sdls_frame.pdu.pdu_len / SDLS_KEYV_CMD_BLK_SIZE; + + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + gcry_cipher_hd_t tmp_hd; + uint8 iv_loc; + + //uint8 tmp_mac[MAC_SIZE]; + + #ifdef PDU_DEBUG + OS_printf("Crypto_Key_verify: Requested %d key(s) to verify \n", pdu_keys); + #endif + + // Read in PDU + for (int x = 0; x < pdu_keys; x++) + { + // Key ID + packet.blk[x].kid = ((uint8)sdls_frame.pdu.data[count] << 8) | ((uint8)sdls_frame.pdu.data[count+1]); + count = count + 2; + #ifdef PDU_DEBUG + OS_printf("Crypto_Key_verify: Block %d Key ID is %d \n", x, packet.blk[x].kid); + #endif + // Key Challenge + for (int y = 0; y < CHALLENGE_SIZE; y++) + { + packet.blk[x].challenge[y] = sdls_frame.pdu.data[count++]; + } + #ifdef PDU_DEBUG + OS_printf("\n"); + #endif + } + + // Prepare for Reply + sdls_frame.pdu.pdu_len = pdu_keys * (2 + IV_SIZE + CHALLENGE_SIZE + CHALLENGE_MAC_SIZE); + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + for (int x = 0; x < pdu_keys; x++) + { // Key ID + ingest[count++] = (packet.blk[x].kid & 0xFF00) >> 8; + ingest[count++] = (packet.blk[x].kid & 0x00FF); + + // Initialization Vector + iv_loc = count; + for (int y = 0; y < IV_SIZE; y++) + { + ingest[count++] = tc_frame->tc_sec_header.iv[y]; + } + ingest[count-1] = ingest[count-1] + x + 1; + + // Encrypt challenge + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[packet.blk[x].kid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(ingest[iv_loc]), + IV_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + gcry_error = gcry_cipher_encrypt( + tmp_hd, + &(ingest[count]), // ciphertext output + CHALLENGE_SIZE, // length of data + &(packet.blk[x].challenge[0]), // plaintext input + CHALLENGE_SIZE // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + count = count + CHALLENGE_SIZE; // Don't forget to increment count! + + gcry_error = gcry_cipher_gettag( + tmp_hd, + &(ingest[count]), // tag output + CHALLENGE_MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_gettag error code %d \n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + count = count + CHALLENGE_MAC_SIZE; // Don't forget to increment count! + + // Copy from tmp_mac into ingest + //for( int y = 0; y < CHALLENGE_MAC_SIZE; y++) + //{ + // ingest[count++] = tmp_mac[y]; + //} + gcry_cipher_close(tmp_hd); + } + + #ifdef PDU_DEBUG + OS_printf("Crypto_Key_verify: Response is %d bytes \n", count); + #endif + + return count; +} + +/* + +/* +** Security Association Monitoring and Control +*/ +static int32 Crypto_MC_ping(char* ingest) +{ + int count = 0; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 0; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + return count; +} + +static int32 Crypto_MC_status(char* ingest) +{ + int count = 0; + + // TODO: Update log_summary.rs; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 2; // 4 + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + // PDU + //ingest[count++] = (log_summary.num_se & 0xFF00) >> 8; + ingest[count++] = (log_summary.num_se & 0x00FF); + //ingest[count++] = (log_summary.rs & 0xFF00) >> 8; + ingest[count++] = (log_summary.rs & 0x00FF); + + #ifdef PDU_DEBUG + OS_printf("log_summary.num_se = 0x%02x \n",log_summary.num_se); + OS_printf("log_summary.rs = 0x%02x \n",log_summary.rs); + #endif + + return count; +} + +static int32 Crypto_MC_dump(char* ingest) +{ + int count = 0; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = (log_count * 6); // SDLS_MC_DUMP_RPLY_SIZE + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + // PDU + for (int x = 0; x < log_count; x++) + { + ingest[count++] = log.blk[x].emt; + //ingest[count++] = (log.blk[x].em_len & 0xFF00) >> 8; + ingest[count++] = (log.blk[x].em_len & 0x00FF); + for (int y = 0; y < EMV_SIZE; y++) + { + ingest[count++] = log.blk[x].emv[y]; + } + } + + #ifdef PDU_DEBUG + OS_printf("log_count = %d \n", log_count); + OS_printf("log_summary.num_se = 0x%02x \n",log_summary.num_se); + OS_printf("log_summary.rs = 0x%02x \n",log_summary.rs); + #endif + + return count; +} + +static int32 Crypto_MC_erase(char* ingest) +{ + int count = 0; + + // Zero Logs + for (int x = 0; x < LOG_SIZE; x++) + { + log.blk[x].emt = 0; + log.blk[x].em_len = 0; + for (int y = 0; y < EMV_SIZE; y++) + { + log.blk[x].emv[y] = 0; + } + } + + // Compute Summary + log_count = 0; + log_summary.num_se = 0; + log_summary.rs = LOG_SIZE; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 2; // 4 + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + // PDU + //ingest[count++] = (log_summary.num_se & 0xFF00) >> 8; + ingest[count++] = (log_summary.num_se & 0x00FF); + //ingest[count++] = (log_summary.rs & 0xFF00) >> 8; + ingest[count++] = (log_summary.rs & 0x00FF); + + return count; +} + +static int32 Crypto_MC_selftest(char* ingest) +{ + uint8 count = 0; + uint8 result = ST_OK; + + // TODO: Perform test + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 1; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + ingest[count++] = result; + + return count; +} + +static int32 Crypto_SA_readARSN(char* ingest) +{ + uint8 count = 0; + uint16 spi = 0x0000; + SecurityAssociation_t* sa_ptr; + + // Read ingest + spi = ((uint8)sdls_frame.pdu.data[0] << 8) | (uint8)sdls_frame.pdu.data[1]; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 2 + IV_SIZE; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 128); + + // Write SPI to reply + ingest[count++] = (spi & 0xFF00) >> 8; + ingest[count++] = (spi & 0x00FF); + + + if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } + + + if (sa_ptr->iv_len > 0) + { // Set IV - authenticated encryption + for (int x = 0; x < sa_ptr->iv_len - 1; x++) + { + ingest[count++] = sa_ptr->iv[x]; + } + + // TODO: Do we need this? + if (sa_ptr->iv[IV_SIZE - 1] > 0) + { // Adjust to report last received, not expected + ingest[count++] = sa_ptr->iv[IV_SIZE - 1] - 1; + } + else + { + ingest[count++] = sa_ptr->iv[IV_SIZE - 1]; + } + } + else + { + // TODO + } + + #ifdef PDU_DEBUG + OS_printf("spi = %d \n", spi); + if (sa_ptr->iv_len > 0) + { + OS_printf("ARSN = 0x"); + for (int x = 0; x < sa_ptr->iv_len; x++) + { + OS_printf("%02x", sa_ptr->iv[x]); + } + OS_printf("\n"); + } + #endif + + return count; +} + +static int32 Crypto_MC_resetalarm(void) +{ // Reset all alarm flags + report.af = 0; + report.bsnf = 0; + report.bmacf = 0; + report.ispif = 0; + return OS_SUCCESS; +} + +static int32 Crypto_User_IdleTrigger(char* ingest) +{ + uint8 count = 0; + + // Prepare for Reply + sdls_frame.pdu.pdu_len = 0; + sdls_frame.hdr.pkt_length = sdls_frame.pdu.pdu_len + 9; + count = Crypto_Prep_Reply(ingest, 144); + + return count; +} + +static int32 Crypto_User_BadSPI(void) +{ + // Toggle Bad Sequence Number + if (badSPI == 0) + { + badSPI = 1; + } + else + { + badSPI = 0; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_BadMAC(void) +{ + // Toggle Bad MAC + if (badMAC == 0) + { + badMAC = 1; + } + else + { + badMAC = 0; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_BadIV(void) +{ + // Toggle Bad MAC + if (badIV == 0) + { + badIV = 1; + } + else + { + badIV = 0; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_BadFECF(void) +{ + // Toggle Bad FECF + if (badFECF == 0) + { + badFECF = 1; + } + else + { + badFECF = 0; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_ModifyKey(void) +{ + // Local variables + uint16 kid = ((uint8)sdls_frame.pdu.data[0] << 8) | ((uint8)sdls_frame.pdu.data[1]); + uint8 mod = (uint8)sdls_frame.pdu.data[2]; + + switch (mod) + { + case 1: // Invalidate Key + ek_ring[kid].value[KEY_SIZE-1]++; + OS_printf("Key %d value invalidated! \n", kid); + break; + case 2: // Modify key state + ek_ring[kid].key_state = (uint8)sdls_frame.pdu.data[3] & 0x0F; + OS_printf("Key %d state changed to %d! \n", kid, mod); + break; + default: + // Error + break; + } + + return OS_SUCCESS; +} + +static int32 Crypto_User_ModifyActiveTM(void) +{ + tm_frame.tm_sec_header.spi = (uint8)sdls_frame.pdu.data[0]; + return OS_SUCCESS; +} + +static int32 Crypto_User_ModifyVCID(void) +{ + tm_frame.tm_header.vcid = (uint8)sdls_frame.pdu.data[0]; + SecurityAssociation_t* sa_ptr; + + for (int i = 0; i < NUM_GVCID; i++) + { + if(sadb_routine->sadb_get_sa_from_spi(i,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } + for (int j = 0; j < NUM_SA; j++) + { + + if (sa_ptr->gvcid_tm_blk[j].mapid == TYPE_TM) + { + if (sa_ptr->gvcid_tm_blk[j].vcid == tm_frame.tm_header.vcid) + { + tm_frame.tm_sec_header.spi = i; + OS_printf("TM Frame SPI changed to %d \n",i); + break; + } + } + } + } + + return OS_SUCCESS; +} + +/* +** Procedures Specifications +*/ +static int32 Crypto_PDU(char* ingest,TC_t* tc_frame) +{ + int32 status = OS_SUCCESS; + + switch (sdls_frame.pdu.type) + { + case 0: // Command + switch (sdls_frame.pdu.uf) + { + case 0: // CCSDS Defined Command + switch (sdls_frame.pdu.sg) + { + case SG_KEY_MGMT: // Key Management Procedure + switch (sdls_frame.pdu.pid) + { + case PID_OTAR: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key OTAR\n" RESET); + #endif + status = Crypto_Key_OTAR(); + break; + case PID_KEY_ACTIVATION: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Activate\n" RESET); + #endif + status = Crypto_Key_update(KEY_ACTIVE); + break; + case PID_KEY_DEACTIVATION: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Deactivate\n" RESET); + #endif + status = Crypto_Key_update(KEY_DEACTIVATED); + break; + case PID_KEY_VERIFICATION: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Verify\n" RESET); + #endif + status = Crypto_Key_verify(ingest,tc_frame); + break; + case PID_KEY_DESTRUCTION: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Destroy\n" RESET); + #endif + status = Crypto_Key_update(KEY_DESTROYED); + break; + case PID_KEY_INVENTORY: + #ifdef PDU_DEBUG + OS_printf(KGRN "Key Inventory\n" RESET); + #endif + status = Crypto_Key_inventory(ingest); + break; + default: + OS_printf(KRED "Error: Crypto_PDU failed interpreting Key Management Procedure Identification Field! \n" RESET); + break; + } + break; + case SG_SA_MGMT: // Security Association Management Procedure + switch (sdls_frame.pdu.pid) + { + case PID_CREATE_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Create\n" RESET); + #endif + status = sadb_routine->sadb_sa_create(); + break; + case PID_DELETE_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Delete\n" RESET); + #endif + status = sadb_routine->sadb_sa_delete(); + break; + case PID_SET_ARSNW: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA setARSNW\n" RESET); + #endif + status = sadb_routine->sadb_sa_setARSNW(); + break; + case PID_REKEY_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Rekey\n" RESET); + #endif + status = sadb_routine->sadb_sa_rekey(); + break; + case PID_EXPIRE_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Expire\n" RESET); + #endif + status = sadb_routine->sadb_sa_expire(); + break; + case PID_SET_ARSN: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA SetARSN\n" RESET); + #endif + status = sadb_routine->sadb_sa_setARSN(); + break; + case PID_START_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Start\n" RESET); + #endif + status = sadb_routine->sadb_sa_start(tc_frame); + break; + case PID_STOP_SA: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Stop\n" RESET); + #endif + status = sadb_routine->sadb_sa_stop(); + break; + case PID_READ_ARSN: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA readARSN\n" RESET); + #endif + status = Crypto_SA_readARSN(ingest); + break; + case PID_SA_STATUS: + #ifdef PDU_DEBUG + OS_printf(KGRN "SA Status\n" RESET); + #endif + status = sadb_routine->sadb_sa_status(ingest); + break; + default: + OS_printf(KRED "Error: Crypto_PDU failed interpreting SA Procedure Identification Field! \n" RESET); + break; + } + break; + case SG_SEC_MON_CTRL: // Security Monitoring & Control Procedure + switch (sdls_frame.pdu.pid) + { + case PID_PING: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Ping\n" RESET); + #endif + status = Crypto_MC_ping(ingest); + break; + case PID_LOG_STATUS: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Status\n" RESET); + #endif + status = Crypto_MC_status(ingest); + break; + case PID_DUMP_LOG: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Dump\n" RESET); + #endif + status = Crypto_MC_dump(ingest); + break; + case PID_ERASE_LOG: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Erase\n" RESET); + #endif + status = Crypto_MC_erase(ingest); + break; + case PID_SELF_TEST: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Selftest\n" RESET); + #endif + status = Crypto_MC_selftest(ingest); + break; + case PID_ALARM_FLAG: + #ifdef PDU_DEBUG + OS_printf(KGRN "MC Reset Alarm\n" RESET); + #endif + status = Crypto_MC_resetalarm(); + break; + default: + OS_printf(KRED "Error: Crypto_PDU failed interpreting MC Procedure Identification Field! \n" RESET); + break; + } + break; + default: // ERROR + OS_printf(KRED "Error: Crypto_PDU failed interpreting Service Group! \n" RESET); + break; + } + break; + + case 1: // User Defined Command + switch (sdls_frame.pdu.sg) + { + default: + switch (sdls_frame.pdu.pid) + { + case 0: // Idle Frame Trigger + #ifdef PDU_DEBUG + OS_printf(KMAG "User Idle Trigger\n" RESET); + #endif + status = Crypto_User_IdleTrigger(ingest); + break; + case 1: // Toggle Bad SPI + #ifdef PDU_DEBUG + OS_printf(KMAG "User Toggle Bad SPI\n" RESET); + #endif + status = Crypto_User_BadSPI(); + break; + case 2: // Toggle Bad IV + #ifdef PDU_DEBUG + OS_printf(KMAG "User Toggle Bad IV\n" RESET); + #endif + status = Crypto_User_BadIV();\ + break; + case 3: // Toggle Bad MAC + #ifdef PDU_DEBUG + OS_printf(KMAG "User Toggle Bad MAC\n" RESET); + #endif + status = Crypto_User_BadMAC(); + break; + case 4: // Toggle Bad FECF + #ifdef PDU_DEBUG + OS_printf(KMAG "User Toggle Bad FECF\n" RESET); + #endif + status = Crypto_User_BadFECF(); + break; + case 5: // Modify Key + #ifdef PDU_DEBUG + OS_printf(KMAG "User Modify Key\n" RESET); + #endif + status = Crypto_User_ModifyKey(); + break; + case 6: // Modify ActiveTM + #ifdef PDU_DEBUG + OS_printf(KMAG "User Modify Active TM\n" RESET); + #endif + status = Crypto_User_ModifyActiveTM(); + break; + case 7: // Modify TM VCID + #ifdef PDU_DEBUG + OS_printf(KMAG "User Modify VCID\n" RESET); + #endif + status = Crypto_User_ModifyVCID(); + break; + default: + OS_printf(KRED "Error: Crypto_PDU received user defined command! \n" RESET); + break; + } + } + break; + } + break; + + case 1: // Reply + OS_printf(KRED "Error: Crypto_PDU failed interpreting PDU Type! Received a Reply!?! \n" RESET); + break; + } + + #ifdef CCSDS_DEBUG + if (status > 0) + { + OS_printf(KMAG "CCSDS message put on software bus: 0x" RESET); + for (int x = 0; x < status; x++) + { + OS_printf(KMAG "%02x" RESET, (uint8) ingest[x]); + } + OS_printf("\n"); + } + #endif + + return status; +} + +static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint8 vcid,GvcidManagedParameters_t* managed_parameters_in, + GvcidManagedParameters_t** managed_parameters_out) +{ + int32 status = MANAGED_PARAMETERS_FOR_GVCID_NOT_FOUND; + + if(managed_parameters_in != NULL) + { + if(managed_parameters_in->tfvn==tfvn && managed_parameters_in->scid==scid && managed_parameters_in->vcid==vcid) { + *managed_parameters_out = managed_parameters_in; + status = OS_SUCCESS; + return status; + }else { + return Crypto_Get_Managed_Parameters_For_Gvcid(tfvn,scid,vcid,managed_parameters_in->next,managed_parameters_out); + } + } + else + { + return status; + } +} +//Managed parameters are expected to live the duration of the program, this may not be necessary. +static void Crypto_Free_Managed_Parameters(GvcidManagedParameters_t* managed_parameters) +{ + if(managed_parameters==NULL){ + return; //Nothing to free, just return! + } + if(managed_parameters->next != NULL){ + Crypto_Free_Managed_Parameters(managed_parameters->next); + } + free(managed_parameters); +} + + +int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_length, \ + uint8 **pp_in_frame, uint16 *p_enc_frame_len) +{ + // Local Variables + int32 status = OS_SUCCESS; + TC_FramePrimaryHeader_t temp_tc_header; + SecurityAssociation_t* sa_ptr = NULL; + uint8 *p_new_enc_frame = NULL; + uint8 sa_service_type = -1; + uint16 mac_loc = 0; + uint16 tf_payload_len = 0x0000; + uint16 new_fecf = 0x0000; + uint8 aad[20]; + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); + #endif + + if (p_in_frame == NULL) + { + status = CRYPTO_LIB_ERR_NULL_BUFFER; + OS_printf(KRED "Error: Input Buffer NULL! \n" RESET); + return status; // Just return here, nothing can be done. + } + + #ifdef DEBUG + OS_printf("%d TF Bytes received\n", in_frame_length); + OS_printf("DEBUG - "); + for(int i=0; i < in_frame_length; i++) + { + OS_printf("%02X", ((uint8 *)&*p_in_frame)[i]); + } + OS_printf("\nPrinted %d bytes\n", in_frame_length); + #endif + + if(crypto_config == NULL) + { + OS_printf(KRED "ERROR: CryptoLib Configuration Not Set! -- CRYPTO_LIB_ERR_NO_CONFIG, Will Exit\n" RESET); + status = CRYPTO_LIB_ERR_NO_CONFIG; + } + + // Primary Header + temp_tc_header.tfvn = ((uint8)p_in_frame[0] & 0xC0) >> 6; + temp_tc_header.bypass = ((uint8)p_in_frame[0] & 0x20) >> 5; + temp_tc_header.cc = ((uint8)p_in_frame[0] & 0x10) >> 4; + temp_tc_header.spare = ((uint8)p_in_frame[0] & 0x0C) >> 2; + temp_tc_header.scid = ((uint8)p_in_frame[0] & 0x03) << 8; + temp_tc_header.scid = temp_tc_header.scid | (uint8)p_in_frame[1]; + temp_tc_header.vcid = ((uint8)p_in_frame[2] & 0xFC) >> 2 & crypto_config->vcid_bitmask; + temp_tc_header.fl = ((uint8)p_in_frame[2] & 0x03) << 8; + temp_tc_header.fl = temp_tc_header.fl | (uint8)p_in_frame[3]; + temp_tc_header.fsn = (uint8)p_in_frame[4]; + + //Lookup-retrieve managed parameters for frame via gvcid: + status = Crypto_Get_Managed_Parameters_For_Gvcid(temp_tc_header.tfvn,temp_tc_header.scid,temp_tc_header.vcid,gvcid_managed_parameters,¤t_managed_parameters); + if(status != OS_SUCCESS) {return status;} //Unable to get necessary Managed Parameters for TC TF -- return with error. + + + uint8 segmentation_hdr = 0x00; + uint8 map_id = 0; + if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ + segmentation_hdr = p_in_frame[5]; + map_id = segmentation_hdr & 0x3F; + } + + + // Check if command frame flag set + if ((temp_tc_header.cc == 1) && (status == OS_SUCCESS)) + { + /* + ** CCSDS 232.0-B-3 + ** Section 6.3.1 + ** "Type-C frames do not have the Security Header and Security Trailer." + */ + #ifdef TC_DEBUG + OS_printf(KYEL "DEBUG - Received Control/Command frame - nothing to do.\n" RESET); + #endif + status = CRYPTO_LIB_ERR_INVALID_CC_FLAG; + } + + if (status == OS_SUCCESS) + { + // Query SA DB for active SA / SDLS parameters + if(sadb_routine == NULL) //This should not happen, but tested here for safety + { + OS_printf(KRED "ERROR: SA DB Not initalized! -- CRYPTO_LIB_ERR_NO_INIT, Will Exit\n" RESET); + status = CRYPTO_LIB_ERR_NO_INIT; + } + else + { + status = sadb_routine->sadb_get_operational_sa_from_gvcid(temp_tc_header.tfvn, temp_tc_header.scid, temp_tc_header.vcid, map_id,&sa_ptr); + } + + + // If unable to get operational SA, can return + if (status != OS_SUCCESS) + { + return status; + } + + #ifdef SA_DEBUG + OS_printf(KYEL "DEBUG - Printing SA Entry for current frame.\n" RESET); + Crypto_saPrint(sa_ptr); + #endif + + // Determine SA Service Type + if ((sa_ptr->est == 0) && (sa_ptr->ast == 0)) + { + sa_service_type = SA_PLAINTEXT; + } + else if ((sa_ptr->est == 0) && (sa_ptr->ast == 1)) + { + sa_service_type = SA_AUTHENTICATION; + } + else if ((sa_ptr->est == 1) && (sa_ptr->ast == 0)) + { + sa_service_type = SA_ENCRYPTION; + } + else if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) + { + sa_service_type = SA_AUTHENTICATED_ENCRYPTION; + } + else + { + // Probably unnecessary check + // Leaving for now as it would be cleaner in SA to have an association enum returned I believe + OS_printf(KRED "Error: SA Service Type is not defined! \n" RESET); + status = OS_ERROR; + return status; + } + + #ifdef TC_DEBUG + switch(sa_service_type) + { + case SA_PLAINTEXT: + OS_printf(KBLU "Creating a TC - CLEAR!\n" RESET); + break; + case SA_AUTHENTICATION: + OS_printf(KBLU "Creating a TC - AUTHENTICATED!\n" RESET); + break; + case SA_ENCRYPTION: + OS_printf(KBLU "Creating a TC - ENCRYPTED!\n" RESET); + break; + case SA_AUTHENTICATED_ENCRYPTION: + OS_printf(KBLU "Creating a TC - AUTHENTICATED ENCRYPTION!\n" RESET); + break; + } + #endif + + // Determine length of buffer to be malloced + // TODO: Determine TC_PAD_SIZE + // TODO: Note: Currently assumes ciphertext output length is same as ciphertext input length + switch(sa_service_type) + { + case SA_PLAINTEXT: + // Ingest length + spi_index (2) + some variable length fields + *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shplf_len; + case SA_AUTHENTICATION: + // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + stmacf_len + *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; + case SA_ENCRYPTION: + // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE; + case SA_AUTHENTICATED_ENCRYPTION: + // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ + // + shplf_len + arc_len + pad_size + stmacf_len + *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; + } + + #ifdef TC_DEBUG + OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *p_enc_frame_len); + OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); + //OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded + OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); + OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, sa_ptr->shivf_len); + OS_printf(KYEL "\tshsnf_len\t = %d\n" RESET, sa_ptr->shsnf_len); + OS_printf(KYEL "\tshplf len\t = %d\n" RESET, sa_ptr->shplf_len); + OS_printf(KYEL "\tarc_len\t\t = %d\n" RESET, sa_ptr->arc_len); + OS_printf(KYEL "\tpad_size\t = %d\n" RESET, TC_PAD_SIZE); + OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, sa_ptr->stmacf_len); + #endif + + // Accio buffer + p_new_enc_frame = (uint8 *)malloc(*p_enc_frame_len * sizeof (unsigned char)); + if(!p_new_enc_frame) + { + OS_printf(KRED "Error: Malloc for encrypted output buffer failed! \n" RESET); + status = OS_ERROR; + return status; + } + CFE_PSP_MemSet(p_new_enc_frame, 0, *p_enc_frame_len); + + // Copy original TF header + CFE_PSP_MemCpy(p_new_enc_frame, p_in_frame, TC_FRAME_PRIMARYHEADER_SIZE); + + // Set new TF Header length + // Recall: Length field is one minus total length per spec + *(p_new_enc_frame+2) = ((*(p_new_enc_frame+2) & 0xFC) | (((*p_enc_frame_len - 1) & (0x0300)) >> 8)); + *(p_new_enc_frame+3) = ((*p_enc_frame_len - 1) & (0x00FF)); + + #ifdef TC_DEBUG + OS_printf(KYEL "Printing updated TF Header:\n\t"); + for (int i=0; ihas_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ + index++; //Add 1 byte to index because segmentation header used for this gvcid. + } + + /* + ** Begin Security Header Fields + ** Reference CCSDS SDLP 3550b1 4.1.1.1.3 + */ + // Set SPI + *(p_new_enc_frame + index) = ((sa_ptr->spi & 0xFF00) >> 8); + *(p_new_enc_frame + index + 1) = (sa_ptr->spi & 0x00FF); + index += 2; + + // Set initialization vector if specified + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION) || (sa_service_type == SA_ENCRYPTION)) + { + #ifdef SA_DEBUG + OS_printf(KYEL "Using IV value:\n\t"); + for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} + OS_printf("\n" RESET); + #endif + + for (int i=0; i < sa_ptr->shivf_len; i++) + { + // TODO: Likely API call + // Copy in IV from SA + *(p_new_enc_frame + index) = sa_ptr->iv[i]; + index++; + } + } + + // Set anti-replay sequence number if specified + /* + ** See also: 4.1.1.4.2 + ** 4.1.1.4.4 If authentication or authenticated encryption is not selected + ** for an SA, the Sequence Number field shall be zero octets in length. + ** Reference CCSDS 3550b1 + */ + // Determine if seq num field is needed + // TODO: Likely SA API Call + if (sa_ptr->shsnf_len > 0) + { + // If using anti-replay counter, increment it + // TODO: API call instead? + // TODO: Check return code + Crypto_increment(sa_ptr->arc, sa_ptr->shsnf_len); + for (int i=0; i < sa_ptr->shsnf_len; i++) + { + *(p_new_enc_frame + index) = sa_ptr->arc[i]; + index++; + } + } + + // Set security header padding if specified + /* + ** 4.2.3.4 h) if the algorithm and mode selected for the SA require the use of + ** fill padding, place the number of fill bytes used into the Pad Length field + ** of the Security Header - Reference CCSDS 3550b1 + */ + // TODO: Revisit this + // TODO: Likely SA API Call + for (int i=0; i < sa_ptr->shplf_len; i++) + { + /* 4.1.1.5.2 The Pad Length field shall contain the count of fill bytes used in the + ** cryptographic process, consisting of an integral number of octets. - CCSDS 3550b1 + */ + // TODO: Set this depending on crypto cipher used + *(p_new_enc_frame + index) = 0x00; + index++; + } + + /* + ** End Security Header Fields + */ + + uint8 fecf_len = FECF_SIZE; + if(current_managed_parameters->has_fecf==TC_NO_FECF) { fecf_len = 0; } + uint8 segment_hdr_len = SEGMENT_HDR_SIZE; + if(current_managed_parameters->has_segmentation_hdr==TC_NO_SEGMENT_HDRS) { segment_hdr_len = 0; } + // Copy in original TF data - except FECF + // Will be over-written if using encryption later + // and if it was present in the original TCTF + //if FECF + // Even though FECF is not part of apply_security payload, we still have to subtract the length from the in_frame_length since that includes FECF length & segment header length. + tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - segment_hdr_len - fecf_len; + //if no FECF + //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; + CFE_PSP_MemCpy((p_new_enc_frame+index), (p_in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); + //index += tf_payload_len; + + /* + ** Begin Security Trailer Fields + */ + + // Set MAC Field if present + /* + ** May be present and unused if switching between clear and authenticated + ** CCSDS 3550b1 4.1.2.3 + */ + // By leaving MAC as zeros, can use index for encryption output + // for (int i=0; i < temp_SA.stmacf_len; i++) + // { + // // Temp fill MAC + // *(p_new_enc_frame + index) = 0x00; + // index++; + // } + + /* + ** End Security Trailer Fields + */ + + /* + ** Begin Authentication / Encryption + */ + + if (sa_service_type != SA_PLAINTEXT) + { + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[sa_ptr->ekid].value[0]), + KEY_SIZE //TODO: look into this + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(sa_ptr->iv[0]), + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + // Prepare additional authenticated data, if needed + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + uint8 bit_masked_data[sa_ptr->abm_len]; + for (int y = 0; y < sa_ptr->abm_len; y++) + { + bit_masked_data[y] = p_new_enc_frame[y] & sa_ptr->abm[y]; + } + #ifdef MAC_DEBUG + OS_printf(KYEL "Preparing AAD:\n"); + OS_printf("\tUsing ABM Length of %d\n\t", sa_ptr->abm_len); + for (int y = 0; y < sa_ptr->abm_len; y++) + { + OS_printf("%02x", bit_masked_data[y]); + } + OS_printf("\n" RESET); + #endif + + gcry_error = gcry_cipher_authenticate( + tmp_hd, + bit_masked_data, // additional authenticated data + sa_ptr->abm_len // length of AAD + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + status = OS_ERROR; + return status; + } + } + + if ((sa_service_type == SA_ENCRYPTION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + // TODO: More robust calculation of this location + // uint16 output_loc = TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; + #ifdef TC_DEBUG + OS_printf("Encrypted bytes output_loc is %d\n", index); + OS_printf("tf_payload_len is %d\n", tf_payload_len); + OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); + for(int i=0; i < *p_enc_frame_len; i++) + { + OS_printf("%02X", *(p_new_enc_frame + i)); + } + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_encrypt( + tmp_hd, + &p_new_enc_frame[index], // ciphertext output + tf_payload_len, // length of data + (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE + segment_hdr_len), // plaintext input + tf_payload_len // in data length + ); + + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + #ifdef TC_DEBUG + OS_printf("Encrypted bytes output_loc is %d\n", index); + OS_printf("tf_payload_len is %d\n", tf_payload_len); + OS_printf(KYEL "Printing TC Frame after encryption:\n\t"); + for(int i=0; i < *p_enc_frame_len; i++) + { + OS_printf("%02X", *(p_new_enc_frame + i)); + } + OS_printf("\n"); + #endif + } + + if ((sa_service_type == SA_AUTHENTICATION) || \ + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + // TODO - Know if FECF exists + mac_loc = *p_enc_frame_len - sa_ptr->stmacf_len - FECF_SIZE; + #ifdef MAC_DEBUG + OS_printf(KYEL "MAC location is: %d\n" RESET, mac_loc); + OS_printf(KYEL "MAC size is: %d\n" RESET, MAC_SIZE); + #endif + gcry_error = gcry_cipher_gettag( + tmp_hd, + &p_new_enc_frame[mac_loc], // tag output + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + } + // Zeroise any sensitive information + if (sa_service_type != SA_PLAINTEXT) + { + gcry_cipher_close(tmp_hd); + } + } + + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); + #ifdef SA_DEBUG + OS_printf(KYEL "Next IV value is:\n\t"); + for(int i=0; ishivf_len; i++) {OS_printf("%02x", sa_ptr->iv[i]);} + OS_printf("\n" RESET); + #endif + #endif + /* + ** End Authentication / Encryption + */ + + //Only calculate & insert FECF if CryptoLib is configured to do so & gvcid includes FECF. + if( crypto_config->crypto_create_fecf==CRYPTO_TC_CREATE_FECF_TRUE && + current_managed_parameters->has_fecf==TC_HAS_FECF) + { + // Set FECF Field if present + #ifdef FECF_DEBUG + OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *p_enc_frame_len - 2); + #endif + new_fecf = Crypto_Calc_FECF(p_new_enc_frame, *p_enc_frame_len - 2); + *(p_new_enc_frame + *p_enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(p_new_enc_frame + *p_enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); + index += 2; + } + + #ifdef TC_DEBUG + OS_printf(KYEL "Printing new TC Frame:\n\t"); + for(int i=0; i < *p_enc_frame_len; i++) + { + OS_printf("%02X", *(p_new_enc_frame + i)); + } + OS_printf("\n\tThe returned length is: %d\n" RESET, *p_enc_frame_len); + #endif + + *pp_in_frame = p_new_enc_frame; + } + + status = sadb_routine->sadb_save_sa(sa_ptr); + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_TC_ApplySecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_processed_frame) +// Loads the ingest frame into the global tc_frame while performing decryption +{ + // Local Variables + int32 status = OS_SUCCESS; + int x = 0; + int y = 0; + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + SecurityAssociation_t* sa_ptr = NULL; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_TC_ProcessSecurity START -----\n" RESET); + #endif + + int byte_idx = 0; + // Primary Header + tc_sdls_processed_frame->tc_header.tfvn = ((uint8)ingest[byte_idx] & 0xC0) >> 6; + tc_sdls_processed_frame->tc_header.bypass = ((uint8)ingest[byte_idx] & 0x20) >> 5; + tc_sdls_processed_frame->tc_header.cc = ((uint8)ingest[byte_idx] & 0x10) >> 4; + tc_sdls_processed_frame->tc_header.spare = ((uint8)ingest[byte_idx] & 0x0C) >> 2; + tc_sdls_processed_frame->tc_header.scid = ((uint8)ingest[byte_idx] & 0x03) << 8; + byte_idx++; + tc_sdls_processed_frame->tc_header.scid = tc_sdls_processed_frame->tc_header.scid | (uint8)ingest[byte_idx]; + byte_idx++; + tc_sdls_processed_frame->tc_header.vcid = (((uint8)ingest[byte_idx] & 0xFC) >> 2) & crypto_config->vcid_bitmask; + tc_sdls_processed_frame->tc_header.fl = ((uint8)ingest[byte_idx] & 0x03) << 8; + byte_idx++; + tc_sdls_processed_frame->tc_header.fl = tc_sdls_processed_frame->tc_header.fl | (uint8)ingest[byte_idx]; + byte_idx++; + tc_sdls_processed_frame->tc_header.fsn = (uint8)ingest[byte_idx]; + byte_idx++; + + //Lookup-retrieve managed parameters for frame via gvcid: + status = Crypto_Get_Managed_Parameters_For_Gvcid(tc_sdls_processed_frame->tc_header.tfvn,tc_sdls_processed_frame->tc_header.scid, + tc_sdls_processed_frame->tc_header.vcid,gvcid_managed_parameters,¤t_managed_parameters); + + if(status != OS_SUCCESS) {return status;} //Unable to get necessary Managed Parameters for TC TF -- return with error. + + // Security Header + if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ + tc_sdls_processed_frame->tc_sec_header.sh = (uint8)ingest[byte_idx]; + byte_idx++; + } + tc_sdls_processed_frame->tc_sec_header.spi = ((uint8)ingest[byte_idx] << 8) | (uint8)ingest[byte_idx+1]; + byte_idx+=2; + #ifdef TC_DEBUG + OS_printf("vcid = %d \n", tc_sdls_processed_frame->tc_header.vcid ); + OS_printf("spi = %d \n", tc_sdls_processed_frame->tc_sec_header.spi); + #endif + + // Checks + if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR && ((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) + { + // User packet check only used for ESA Testing! + } + else + { // Update last spi used + report.lspiu = tc_sdls_processed_frame->tc_sec_header.spi; + + // Verify + if (tc_sdls_processed_frame->tc_header.scid != (SCID & 0x3FF)) + { + OS_printf(KRED "Error: SCID incorrect! \n" RESET); + status = OS_ERROR; + } + else + { + switch (report.lspiu) + { // Invalid SPIs fall through to trigger flag in FSR + case 0x0000: + case 0xFFFF: + status = OS_ERROR; + report.ispif = 1; + OS_printf(KRED "Error: SPI invalid! \n" RESET); + break; + default: + break; + } + } + + if ((report.lspiu > NUM_SA) && (status == OS_SUCCESS)) + { + report.ispif = 1; + OS_printf(KRED "Error: SPI value greater than NUM_SA! \n" RESET); + status = OS_ERROR; + } + if (status == OS_SUCCESS) + { + if(sadb_routine->sadb_get_sa_from_spi(report.lspiu,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + status = OS_ERROR; //Error -- unable to get SA from SPI. + } + } + if (status == OS_SUCCESS) + { + if (sa_ptr->gvcid_tc_blk.mapid != TYPE_TC) + { + OS_printf(KRED "Error: SA invalid type! \n" RESET); + status = OS_ERROR; + } + } + // TODO: I don't think this is needed. + //if (status == OS_SUCCESS) + //{ + // if (sa_ptr->gvcid_tc_blk.vcid != tc_sdls_processed_frame->tc_header.vcid) + // { + // OS_printf(KRED "Error: VCID not mapped to provided SPI! \n" RESET); + // status = OS_ERROR; + // } + //} + if (status == OS_SUCCESS) + { + if (sa_ptr->sa_state != SA_OPERATIONAL) + { + OS_printf(KRED "Error: SA state not operational! \n" RESET); + status = OS_ERROR; + } + } + if (status != OS_SUCCESS) + { + report.af = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = SPI_INVALID_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + *len_ingest = 0; + return status; + } + } + if(sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + status = OS_ERROR; //Error -- unable to get SA from SPI. + return status; + } + if((sa_ptr->est == 1) && (sa_ptr->ast == 0)) + { + // Encryption Only + #ifdef DEBUG + OS_printf(KBLU "ENCRYPTED TC Received!\n" RESET); + #endif + + #ifdef TC_DEBUG + OS_printf("IV: \n"); + #endif + for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) + { + tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; + #ifdef TC_DEBUG + OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); + #endif + } + byte_idx += sa_ptr->shivf_len; + report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; + + #ifdef DEBUG + OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); + OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); + #endif + + // Check IV is in ARCW + if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != CRYPTO_LIB_SUCCESS ) + { + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV not in window! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { + if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == CRYPTO_LIB_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value + for (int i = 0; i < (sa_ptr->shivf_len); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } + } + } + + if ( status != CRYPTO_LIB_SUCCESS ) + { // Exit + *len_ingest = 0; + return status; + } + + tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); + + x = x + tc_sdls_processed_frame->tc_pdu_len; + + #ifdef TC_DEBUG + OS_printf("TC: \n"); + for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) + { + OS_printf("\t ingest[%d] = 0x%02x \n", temp, (uint8)ingest[temp+20]); + } + #endif + + // FECF + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); + Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 1),tc_sdls_processed_frame); + + // Initialize the key + //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[sa_ptr->ekid]); + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef DEBUG + OS_printf("Key ID = %d, 0x", sa_ptr->ekid); + for(int y = 0; y < KEY_SIZE; y++) + { + OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); + } + OS_printf("\n"); + #endif + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[sa_ptr->ekid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(sa_ptr->iv[0]), + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + gcry_error = gcry_cipher_decrypt( + tmp_hd, + &(tc_sdls_processed_frame->tc_pdu[0]), // plaintext output + tc_sdls_processed_frame->tc_pdu_len, // length of data + &(ingest[20]), // ciphertext input + tc_sdls_processed_frame->tc_pdu_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_cipher_close(tmp_hd); + + // Increment the IV for next time + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); + #endif + } + // Determine mode via SPI + else if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) + { // Authenticated/Encrypted + #ifdef DEBUG + OS_printf(KBLU "Authenticated/Encrypted TC Received!\n" RESET); + #endif + #ifdef TC_DEBUG + OS_printf("IV: \n"); + #endif + for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) + { + tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; + #ifdef TC_DEBUG + OS_printf("\t iv[%d] = 0x%02x\n", x-byte_idx, tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); + #endif + } + byte_idx += sa_ptr->shivf_len; + report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; + + #ifdef DEBUG + OS_printf("\t tc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); + OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); + #endif + + // Check IV is in ARCW + if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) + { + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV not in window! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { + if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value + for (int i = 0; i < (sa_ptr->shivf_len); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } + } + } + + if ( status == OS_ERROR ) + { // Exit + *len_ingest = 0; + return status; + } + + tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); + + x = x + tc_sdls_processed_frame->tc_pdu_len; + + #ifdef TC_DEBUG + OS_printf("TC: \n"); + for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) + { + OS_printf("\t ingest[%d] = 0x%02x \n", temp, (uint8)ingest[temp+20]); + } + #endif + + // Security Trailer + #ifdef TC_DEBUG + OS_printf("MAC: \n"); + #endif + for (y = x; y < (x + MAC_SIZE); y++) + { + tc_sdls_processed_frame->tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; + #ifdef TC_DEBUG + OS_printf("\t mac[%d] = 0x%02x\n", y-x, tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); + #endif + } + x = x + sa_ptr->stmacf_len; + + // FECF + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); + Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl - 1),tc_sdls_processed_frame); + + // Initialize the key + //itc_gcm128_init(&sa[tc_sdls_processed_frame->tc_sec_header.spi].gcm_ctx, (const unsigned char*) &ek_ring[sa[sa_ptr->ekid]); + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef DEBUG + OS_printf("Key ID = %d, 0x", sa_ptr->ekid); + for(int y = 0; y < KEY_SIZE; y++) + { + OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); + } + OS_printf("\n"); + #endif + gcry_error = gcry_cipher_setkey( + tmp_hd, + ek_ring[sa_ptr->ekid].value, + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + sa_ptr->iv, + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef MAC_DEBUG + OS_printf("AAD = 0x"); + #endif + // Prepare additional authenticated data (AAD) + + uint8 aad[sa_ptr->abm_len]; + for (y = 0; y < sa_ptr->abm_len; y++) + { + aad[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); + #ifdef MAC_DEBUG + OS_printf("%02x", (uint8) ingest[y]); + #endif + } + #ifdef MAC_DEBUG + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_authenticate( + tmp_hd, + aad, // additional authenticated data + sa_ptr->abm_len // length of AAD + ); + + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + status = OS_ERROR; + return status; + } + + gcry_error = gcry_cipher_decrypt( + tmp_hd, + tc_sdls_processed_frame->tc_pdu, // plaintext output + tc_sdls_processed_frame->tc_pdu_len, // length of data + &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input + tc_sdls_processed_frame->tc_pdu_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_checktag( + tmp_hd, + tc_sdls_processed_frame->tc_sec_trailer.mac, // tag input + sa_ptr->stmacf_len // tag size + ); + + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + + OS_printf("Calculated MAC = 0x"); + for (int z = 0; z < MAC_SIZE; z++) + { + OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); + } + OS_printf("\n"); + + gcry_error = gcry_cipher_gettag( + tmp_hd, + &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + + OS_printf("Expected MAC = 0x"); + for (int z = 0; z < MAC_SIZE; z++) + { + OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); + } + OS_printf("\n"); + status = OS_ERROR; + report.bmacf = 1; + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + return status; + } + gcry_cipher_close(tmp_hd); + + // Increment the IV for next time + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); + #endif + } + else if((sa_ptr->ast == 1) && (sa_ptr->est == 0)) + { + // Authentication only + #ifdef DEBUG + OS_printf(KBLU "Authenticated TC Received!\n" RESET); + #endif + #ifdef TC_DEBUG + OS_printf(KYEL "IV: \n\t"); + #endif + for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) + { + tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; + #ifdef TC_DEBUG + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); + #endif + } + #ifdef TC_DEBUG + OS_printf("\n"RESET); + #endif + byte_idx += sa_ptr->shivf_len; + report.snval = tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]; + + #ifdef DEBUG + OS_printf("\ttc_sec_header.iv[%d] = 0x%02x \n", sa_ptr->shivf_len-1, tc_sdls_processed_frame->tc_sec_header.iv[sa_ptr->shivf_len-1]); + OS_printf("\tsa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); + #endif + + // Check IV is in ARCW + if (Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) + { + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV not in window! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { + if (Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value + for (int i = 0; i < (sa_ptr->shivf_len); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } + } + } + if ( status == OS_ERROR ) + { // Exit + *len_ingest = 0; + return status; + } + tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); + + // Copy pdu data from ingest into memory + for(int i=0; itc_pdu_len; i++) + { + tc_sdls_processed_frame->tc_pdu[i] = ingest[x]; + x++; + } + + // x = x + tc_sdls_processed_frame->tc_pdu_len; + + #ifdef TC_DEBUG + OS_printf("tc_pdu_len is: %d\n", tc_sdls_processed_frame->tc_pdu_len); + OS_printf("TC PDU ingest Payload: \n\t"); + for (int temp = 0; temp < tc_sdls_processed_frame->tc_pdu_len; temp++) + { + OS_printf("%02x", (uint8)ingest[temp+20]); + } + OS_printf("\n"); + #endif + + // Security Trailer + #ifdef TC_DEBUG + OS_printf("MAC: \n\t"); + #endif + for (y = x; y < (x + sa_ptr->stmacf_len); y++) + { + tc_sdls_processed_frame->tc_sec_trailer.mac[y-x] = (uint8)ingest[y]; + #ifdef TC_DEBUG + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[y-x]); + #endif + } + #ifdef TC_DEBUG + OS_printf("\n"); + #endif + x = x + sa_ptr->stmacf_len; + + // FECF + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[x] << 8) | ((uint8)ingest[x+1]); + Crypto_FECF(tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl-1),tc_sdls_processed_frame); + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef DEBUG + OS_printf("Key ID = %d, 0x", sa_ptr->ekid); + for(int y = 0; y < KEY_SIZE; y++) + { + OS_printf("%02x", ek_ring[sa_ptr->ekid].value[y]); + } + OS_printf("\n"); + #endif + gcry_error = gcry_cipher_setkey( + tmp_hd, + ek_ring[sa_ptr->ekid].value, + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + sa_ptr->iv, + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + #ifdef MAC_DEBUG + OS_printf("AAD = 0x"); + #endif + // Prepare additional authenticated data (AAD) + for (y = 0; y < sa_ptr->abm_len; y++) + { + ingest[y] = (uint8) ((uint8)ingest[y] & (uint8)sa_ptr->abm[y]); + #ifdef DEBUG + OS_printf("%02x", (uint8) ingest[y]); + #endif + } + #ifdef DEBUG + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_authenticate( + tmp_hd, + ingest, // additional authenticated data + sa_ptr->abm_len // length of AAD + ); + + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + OS_printf(KRED "Failure: %s/%s\n", gcry_strsource(gcry_error),gcry_strerror (gcry_error)); + status = OS_ERROR; + return status; + } + // printf("PDU LEN: %d\n", tc_sdls_processed_frame->tc_pdu_len); + // gcry_error = gcry_cipher_decrypt( + // tmp_hd, + // tc_sdls_processed_frame->tc_pdu, // plaintext output + // tc_sdls_processed_frame->tc_pdu_len, // length of data + // &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input + // tc_sdls_processed_frame->tc_pdu_len // in data length + // ); + // if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + // { + // OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + // status = OS_ERROR; + // return status; + // } + char *garbage_buff = malloc(tc_sdls_processed_frame->tc_pdu_len * sizeof(unsigned char)); + + gcry_error = gcry_cipher_encrypt( + tmp_hd, + // tc_sdls_processed_frame->tc_pdu, // plaintext output + garbage_buff, + tc_sdls_processed_frame->tc_pdu_len, // length of data + &(ingest[*len_ingest - tc_sdls_processed_frame->tc_pdu_len - sa_ptr->stmacf_len - 2]), // ciphertext input + tc_sdls_processed_frame->tc_pdu_len // in data length + ); + free(garbage_buff); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_encrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_gettag( + tmp_hd, + &(tc_sdls_processed_frame->tc_sec_trailer.mac[0]), // tag output + sa_ptr->stmacf_len // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_gettag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + } + + #ifdef MAC_DEBUG + OS_printf("TC_Process Expected MAC = 0x"); + for (int z = 0; z < sa_ptr->stmacf_len ; z++) + { + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[z]); + } + OS_printf("\n"); + OS_printf("TC_Process Actual MAC = 0x"); + for (int z = 0; z < sa_ptr->stmacf_len ; z++) + { + OS_printf("%02x",tc_sdls_processed_frame->tc_sec_trailer.mac[z]); + } + OS_printf("\n"); + #endif + + #ifdef DEBUG + OS_printf("Using PDU length of: %d\n", tc_sdls_processed_frame->tc_pdu_len); + OS_printf("Printing entire frame sans header in memory:\n\t0x"); + // for(int i=0; itc_header); i++) + // { + // OS_printf("%02x", tc_sdls_processed_frame->tc_header[i]); + // } + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.sh); + OS_printf("%04x", tc_sdls_processed_frame->tc_sec_header.spi); + for(int i=0; iiv_len; i++) + { + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.iv[i]); + } + for(int i=0; itc_pdu_len; i++) + { + OS_printf("%02x", tc_sdls_processed_frame->tc_pdu[i]); + } + for(int i=0; istmacf_len; i++) + { + OS_printf("%02x", tc_sdls_processed_frame->tc_sec_trailer.mac[i]); + } + OS_printf("%04x\n", tc_sdls_processed_frame->tc_sec_trailer.fecf); + #endif + + status = OS_ERROR; + report.bmacf = 1; + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + return status; + gcry_cipher_close(tmp_hd); + + // Increment the IV for next time + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, sa_ptr->shivf_len); + #endif + + } + else + { // Clear + #ifdef DEBUG + OS_printf(KBLU "CLEAR TC Received!\n" RESET); + #endif + + for (y = 10; y <= (tc_sdls_processed_frame->tc_header.fl -1); y++) //tfhdr+seghdr+sechdr=5+1+6=12 + { + tc_sdls_processed_frame->tc_pdu[y - 10] = (uint8)ingest[y]; + } + // FECF + tc_sdls_processed_frame->tc_sec_trailer.fecf = ((uint8)ingest[y] << 8) | ((uint8)ingest[y+1]); + Crypto_FECF((int) tc_sdls_processed_frame->tc_sec_trailer.fecf, ingest, (tc_sdls_processed_frame->tc_header.fl),tc_sdls_processed_frame); + } + + #ifdef TC_DEBUG + Crypto_tcPrint(tc_sdls_processed_frame); + #endif + + // // Zero ingest + // for (x = 0; x < *len_ingest; x++) + // { + // ingest[x] = 0; + // } + + + if(crypto_config->process_sdls_pdus==TC_PROCESS_SDLS_PDUS_FALSE) //If we don't want to process frame data for SDLS PDUs, only reverse security & return content. + { + // CCSDS Pass-through + #ifdef DEBUG + OS_printf(KGRN "CCSDS Pass-through \n" RESET); + #endif + if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR) { + for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl - 11); x++) { + ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; + #ifdef CCSDS_DEBUG + OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); + #endif + *len_ingest = x; + } + } else { + for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl); x++) { //with no PUS header, entire PDU is data + ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; + #ifdef CCSDS_DEBUG + OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); + #endif + *len_ingest = x; + } + } + } + else //Process SDLS PDU + { + if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR) + { + if ((tc_sdls_processed_frame->tc_pdu[0] == 0x18) && (tc_sdls_processed_frame->tc_pdu[1] == 0x80)) + // Crypto Lib Application ID + { + #ifdef DEBUG + OS_printf(KGRN "Received SDLS command: " RESET); + #endif + // CCSDS Header + sdls_frame.hdr.pvn = (tc_sdls_processed_frame->tc_pdu[0] & 0xE0) >> 5; + sdls_frame.hdr.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x10) >> 4; + sdls_frame.hdr.shdr = (tc_sdls_processed_frame->tc_pdu[0] & 0x08) >> 3; + sdls_frame.hdr.appID = + ((tc_sdls_processed_frame->tc_pdu[0] & 0x07) << 8) | tc_sdls_processed_frame->tc_pdu[1]; + sdls_frame.hdr.seq = (tc_sdls_processed_frame->tc_pdu[2] & 0xC0) >> 6; + sdls_frame.hdr.pktid = + ((tc_sdls_processed_frame->tc_pdu[2] & 0x3F) << 8) | tc_sdls_processed_frame->tc_pdu[3]; + sdls_frame.hdr.pkt_length = (tc_sdls_processed_frame->tc_pdu[4] << 8) | tc_sdls_processed_frame->tc_pdu[5]; + + // CCSDS PUS + sdls_frame.pus.shf = (tc_sdls_processed_frame->tc_pdu[6] & 0x80) >> 7; + sdls_frame.pus.pusv = (tc_sdls_processed_frame->tc_pdu[6] & 0x70) >> 4; + sdls_frame.pus.ack = (tc_sdls_processed_frame->tc_pdu[6] & 0x0F); + sdls_frame.pus.st = tc_sdls_processed_frame->tc_pdu[7]; + sdls_frame.pus.sst = tc_sdls_processed_frame->tc_pdu[8]; + sdls_frame.pus.sid = (tc_sdls_processed_frame->tc_pdu[9] & 0xF0) >> 4; + sdls_frame.pus.spare = (tc_sdls_processed_frame->tc_pdu[9] & 0x0F); + + // SDLS TLV PDU + sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[10] & 0x80) >> 7; + sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[10] & 0x40) >> 6; + sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[10] & 0x30) >> 4; + sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[10] & 0x0F); + sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[11] << 8) | tc_sdls_processed_frame->tc_pdu[12]; + for (x = 13; x < (13 + sdls_frame.hdr.pkt_length); x++) { + sdls_frame.pdu.data[x - 13] = tc_sdls_processed_frame->tc_pdu[x]; + } + + #ifdef CCSDS_DEBUG + Crypto_ccsdsPrint(&sdls_frame); + #endif + + // Determine type of PDU + *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); + } + } + else if (tc_sdls_processed_frame->tc_header.vcid == TC_SDLS_EP_VCID) //TC SDLS PDU with no packet layer + { + #ifdef DEBUG + OS_printf(KGRN "Received SDLS command: " RESET); + #endif + // No Packet HDR or PUS in these frames + // SDLS TLV PDU + sdls_frame.pdu.type = (tc_sdls_processed_frame->tc_pdu[0] & 0x80) >> 7; + sdls_frame.pdu.uf = (tc_sdls_processed_frame->tc_pdu[0] & 0x40) >> 6; + sdls_frame.pdu.sg = (tc_sdls_processed_frame->tc_pdu[0] & 0x30) >> 4; + sdls_frame.pdu.pid = (tc_sdls_processed_frame->tc_pdu[0] & 0x0F); + sdls_frame.pdu.pdu_len = (tc_sdls_processed_frame->tc_pdu[1] << 8) | tc_sdls_processed_frame->tc_pdu[2]; + for (x = 3; x < (3 + tc_sdls_processed_frame->tc_header.fl); x++) { + //Todo - Consider how this behaves with large OTAR PDUs that are larger than 1 TC in size. Most likely fails. Must consider Uplink Sessions (sequence numbers). + sdls_frame.pdu.data[x - 3] = tc_sdls_processed_frame->tc_pdu[x]; + } + + #ifdef CCSDS_DEBUG + Crypto_ccsdsPrint(&sdls_frame); + #endif + + // Determine type of PDU + *len_ingest = Crypto_PDU(ingest, tc_sdls_processed_frame); + } + else { + //TODO - Process SDLS PDU with Packet Layer without PUS_HDR + } + }//End Process SDLS PDU + + // Zero ingest + memset(ingest, 0, *len_ingest); + // for (x = 0; x < *len_ingest; x++) + // { + // ingest[x] = 0; + // } + + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_TC_ProcessSecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_TM_ApplySecurity( char* ingest, int* len_ingest) +// Accepts CCSDS message in ingest, and packs into TM before encryption +{ + int32 status = CRYPTO_LIB_SUCCESS; + int count = 0; + int pdu_loc = 0; + int pdu_len = *len_ingest - TM_MIN_SIZE; + int pad_len = 0; + int mac_loc = 0; + int fecf_loc = 0; + uint8 tempTM[TM_SIZE]; + int x = 0; + int y = 0; + uint8 aad[20]; + uint16 spi = tm_frame.tm_sec_header.spi; + uint16 spp_crc = 0x0000; + SecurityAssociation_t* sa_ptr; + SecurityAssociation_t sa; + + gcry_cipher_hd_t tmp_hd; + gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + CFE_PSP_MemSet(&tempTM, 0, TM_SIZE); + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_TM_ApplySecurity START -----\n" RESET); + #endif + + // Check for idle frame trigger + if (((uint8)ingest[0] == 0x08) && ((uint8)ingest[1] == 0x90)) + { // Zero ingest + for (x = 0; x < *len_ingest; x++) + { + ingest[x] = 0; + } + // Update TM First Header Pointer + tm_frame.tm_header.fhp = 0xFE; + } + else + { // Update the length of the ingest from the CCSDS header + *len_ingest = (ingest[4] << 8) | ingest[5]; + ingest[5] = ingest[5] - 5; + // Remove outgoing secondary space packet header flag + ingest[0] = 0x00; + // Change sequence flags to 0xFFFF + ingest[2] = 0xFF; + ingest[3] = 0xFF; + // Add 2 bytes of CRC to space packet + spp_crc = Crypto_Calc_CRC16((char*) ingest, *len_ingest); + ingest[*len_ingest] = (spp_crc & 0xFF00) >> 8; + ingest[*len_ingest+1] = (spp_crc & 0x00FF); + *len_ingest = *len_ingest + 2; + // Update TM First Header Pointer + tm_frame.tm_header.fhp = tm_offset; + #ifdef TM_DEBUG + OS_printf("tm_offset = %d \n", tm_offset); + #endif + } + + // Update Current Telemetry Frame in Memory + // Counters + tm_frame.tm_header.mcfc++; + tm_frame.tm_header.vcfc++; + // Operational Control Field + Crypto_TM_updateOCF(); + // Payload Data Unit + Crypto_TM_updatePDU(ingest, *len_ingest); + + if(sadb_routine->sadb_get_sa_from_spi(spi,&sa_ptr) != OS_SUCCESS){ + //TODO - Error handling + return OS_ERROR; //Error -- unable to get SA from SPI. + } + + + // Check test flags + if (badSPI == 1) + { + tm_frame.tm_sec_header.spi++; + } + if (badIV == 1) + { + sa_ptr->iv[IV_SIZE-1]++; + } + if (badMAC == 1) + { + tm_frame.tm_sec_trailer.mac[MAC_SIZE-1]++; + } + + // Initialize the temporary TM frame + // Header + tempTM[count++] = (uint8) ((tm_frame.tm_header.tfvn << 6) | ((tm_frame.tm_header.scid & 0x3F0) >> 4)); + tempTM[count++] = (uint8) (((tm_frame.tm_header.scid & 0x00F) << 4) | (tm_frame.tm_header.vcid << 1) | (tm_frame.tm_header.ocff)); + tempTM[count++] = (uint8) (tm_frame.tm_header.mcfc); + tempTM[count++] = (uint8) (tm_frame.tm_header.vcfc); + tempTM[count++] = (uint8) ((tm_frame.tm_header.tfsh << 7) | (tm_frame.tm_header.sf << 6) | (tm_frame.tm_header.pof << 5) | (tm_frame.tm_header.slid << 3) | ((tm_frame.tm_header.fhp & 0x700) >> 8)); + tempTM[count++] = (uint8) (tm_frame.tm_header.fhp & 0x0FF); + // tempTM[count++] = (uint8) ((tm_frame.tm_header.tfshvn << 6) | tm_frame.tm_header.tfshlen); + // Security Header + tempTM[count++] = (uint8) ((spi & 0xFF00) >> 8); + tempTM[count++] = (uint8) ((spi & 0x00FF)); + CFE_PSP_MemCpy(tm_frame.tm_sec_header.iv, sa_ptr->iv, IV_SIZE); + + // Padding Length + pad_len = Crypto_Get_tmLength(*len_ingest) - TM_MIN_SIZE + IV_SIZE + TM_PAD_SIZE - *len_ingest; + + // Only add IV for authenticated encryption + if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) + { // Initialization Vector + #ifdef INCREMENT + Crypto_increment(sa_ptr->iv, IV_SIZE); + #endif + if ((sa_ptr->est == 1) || (sa_ptr->ast == 1)) + { for (x = 0; x < IV_SIZE; x++) + { + tempTM[count++] = sa_ptr->iv[x]; + } + } + pdu_loc = count; + pad_len = pad_len - IV_SIZE - TM_PAD_SIZE + OCF_SIZE; + pdu_len = *len_ingest + pad_len; + } + else + { // Include padding length bytes - hard coded per ESA testing + tempTM[count++] = 0x00; // pad_len >> 8; + tempTM[count++] = 0x1A; // pad_len + pdu_loc = count; + pdu_len = *len_ingest + pad_len; + } + + // Payload Data Unit + for (x = 0; x < (pdu_len); x++) + { + tempTM[count++] = (uint8) tm_frame.tm_pdu[x]; + } + // Message Authentication Code + mac_loc = count; + for (x = 0; x < MAC_SIZE; x++) + { + tempTM[count++] = 0x00; + } + // Operational Control Field + for (x = 0; x < OCF_SIZE; x++) + { + tempTM[count++] = (uint8) tm_frame.tm_sec_trailer.ocf[x]; + } + // Frame Error Control Field + fecf_loc = count; + tm_frame.tm_sec_trailer.fecf = Crypto_Calc_FECF((char*) tempTM, count); + tempTM[count++] = (uint8) ((tm_frame.tm_sec_trailer.fecf & 0xFF00) >> 8); + tempTM[count++] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); + + // Determine Mode + // Clear + if ((sa_ptr->est == 0) && + (sa_ptr->ast == 0)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TM - CLEAR! \n" RESET); + #endif + // Copy temporary frame to ingest + CFE_PSP_MemCpy(ingest, tempTM, count); + } + // Authenticated Encryption + else if ((sa_ptr->est == 1) && + (sa_ptr->ast == 1)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TM - AUTHENTICATED ENCRYPTION! \n" RESET); + #endif + + // Copy TM to ingest + CFE_PSP_MemCpy(ingest, tempTM, pdu_loc); + + #ifdef MAC_DEBUG + OS_printf("AAD = 0x"); + #endif + // Prepare additional authenticated data + for (y = 0; y < sa_ptr->abm_len; y++) + { + aad[y] = ingest[y] & sa_ptr->abm[y]; + #ifdef MAC_DEBUG + OS_printf("%02x", aad[y]); + #endif + } + #ifdef MAC_DEBUG + OS_printf("\n"); + #endif + + gcry_error = gcry_cipher_open( + &(tmp_hd), + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + GCRY_CIPHER_CBC_MAC + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_open error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setkey( + tmp_hd, + &(ek_ring[sa_ptr->ekid].value[0]), + KEY_SIZE + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setkey error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_setiv( + tmp_hd, + &(sa_ptr->iv[0]), + sa_ptr->iv_len + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_setiv error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_encrypt( + tmp_hd, + &(ingest[pdu_loc]), // ciphertext output + pdu_len, // length of data + &(tempTM[pdu_loc]), // plaintext input + pdu_len // in data length + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_decrypt error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_authenticate( + tmp_hd, + &(aad[0]), // additional authenticated data + sa_ptr->abm_len // length of AAD + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_authenticate error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + gcry_error = gcry_cipher_gettag( + tmp_hd, + &(ingest[mac_loc]), // tag output + MAC_SIZE // tag size + ); + if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) + { + OS_printf(KRED "ERROR: gcry_cipher_checktag error code %d\n" RESET,gcry_error & GPG_ERR_CODE_MASK); + status = OS_ERROR; + return status; + } + + #ifdef MAC_DEBUG + OS_printf("MAC = 0x"); + for(x = 0; x < MAC_SIZE; x++) + { + OS_printf("%02x", (uint8) ingest[x + mac_loc]); + } + OS_printf("\n"); + #endif + + // Update OCF + y = 0; + for (x = OCF_SIZE; x > 0; x--) + { + ingest[fecf_loc - x] = tm_frame.tm_sec_trailer.ocf[y++]; + } + + // Update FECF + tm_frame.tm_sec_trailer.fecf = Crypto_Calc_FECF((char*) ingest, fecf_loc - 1); + ingest[fecf_loc] = (uint8) ((tm_frame.tm_sec_trailer.fecf & 0xFF00) >> 8); + ingest[fecf_loc + 1] = (uint8) (tm_frame.tm_sec_trailer.fecf & 0x00FF); + } + // Authentication + else if ((sa_ptr->est == 0) && + (sa_ptr->ast == 1)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TM - AUTHENTICATED! \n" RESET); + #endif + // TODO: Future work. Operationally same as clear. + CFE_PSP_MemCpy(ingest, tempTM, count); + } + // Encryption + else if ((sa_ptr->est == 1) && + (sa_ptr->ast == 0)) + { + #ifdef DEBUG + OS_printf(KBLU "Creating a TM - ENCRYPTED! \n" RESET); + #endif + // TODO: Future work. Operationally same as clear. + CFE_PSP_MemCpy(ingest, tempTM, count); + } + + #ifdef TM_DEBUG + Crypto_tmPrint(&tm_frame); + #endif + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_TM_ApplySecurity END -----\n" RESET); + #endif + + *len_ingest = count; + return status; +} + +int32 Crypto_TM_ProcessSecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_TM_ProcessSecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_TM_ProcessSecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_AOS_ApplySecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_AOS_ApplySecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_AOS_ApplySecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_AOS_ProcessSecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_AOS_ProcessSecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_AOS_ProcessSecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_ApplySecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_ApplySecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_ApplySecurity END -----\n" RESET); + #endif + + return status; +} + +int32 Crypto_ProcessSecurity(char* ingest, int* len_ingest) +{ + // Local Variables + int32 status = OS_SUCCESS; + + #ifdef DEBUG + OS_printf(KYEL "\n----- Crypto_ProcessSecurity START -----\n" RESET); + #endif + + // TODO: This whole function! + len_ingest = len_ingest; + ingest[0] = ingest[0]; + + #ifdef DEBUG + OS_printf(KYEL "----- Crypto_ProcessSecurity END -----\n" RESET); + #endif + + return status; +} + #endif \ No newline at end of file diff --git a/fsw/src/crypto_print.c b/fsw/src/crypto_print.c index 5427b0f2..0bf6f0af 100644 --- a/fsw/src/crypto_print.c +++ b/fsw/src/crypto_print.c @@ -232,17 +232,19 @@ void Crypto_binprint(void *c, size_t n) printf("\n"); } -void Crypto_mpPrint(GvcidManagedParameters_t* managed_parameters) +void Crypto_mpPrint(GvcidManagedParameters_t* managed_parameters, uint8 print_children) //Prints the currently configured Managed Parameters { - while(managed_parameters != NULL){ + if(managed_parameters != NULL){ OS_printf("Managed Parameter: \n"); OS_printf("\t tfvn: %d", managed_parameters->tfvn); OS_printf("\t scid: %d", managed_parameters->scid); OS_printf("\t vcid: %d", managed_parameters->vcid); OS_printf("\t has_fecf: %d", managed_parameters->has_fecf); OS_printf("\t has_segmentation_headers: %d\n", managed_parameters->has_segmentation_hdr); - managed_parameters = managed_parameters->next; + } + if(managed_parameters->next!=NULL && print_children!=0){ + Crypto_mpPrint(managed_parameters->next,print_children); } } #endif \ No newline at end of file From d2c19a4ea317ec609a6f3bd989a8ba7b544008c6 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Wed, 8 Dec 2021 16:28:32 -0800 Subject: [PATCH 056/184] Add stub definition of MySQL sadb routine for when building without MySQL --- fsw/CMakeLists.txt | 3 +++ .../mysql_stub/sadb_routine_mariadb.stub.c | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 fsw/src_feature_stubs/mysql_stub/sadb_routine_mariadb.stub.c diff --git a/fsw/CMakeLists.txt b/fsw/CMakeLists.txt index 2219b961..f78837fa 100644 --- a/fsw/CMakeLists.txt +++ b/fsw/CMakeLists.txt @@ -20,6 +20,9 @@ aux_source_directory(src LIB_SRC_FILES) if(MYSQL) aux_source_directory(src_mysql LIB_SRC_MYSQL_FILES) list(APPEND LIB_SRC_FILES ${LIB_SRC_MYSQL_FILES}) +else() + aux_source_directory(src_feature_stubs/mysql_stub LIB_SRC_MYSQL_FILES) + list(APPEND LIB_SRC_FILES ${LIB_SRC_MYSQL_FILES}) endif() diff --git a/fsw/src_feature_stubs/mysql_stub/sadb_routine_mariadb.stub.c b/fsw/src_feature_stubs/mysql_stub/sadb_routine_mariadb.stub.c new file mode 100644 index 00000000..5ea812ab --- /dev/null +++ b/fsw/src_feature_stubs/mysql_stub/sadb_routine_mariadb.stub.c @@ -0,0 +1,22 @@ +/* + * Copyright 2021, by the California Institute of Technology. + * ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged. + * Any commercial use must be negotiated with the Office of Technology + * Transfer at the California Institute of Technology. + * + * This software may be subject to U.S. export control laws. By accepting + * this software, the user agrees to comply with all applicable U.S. + * export laws and regulations. User has the responsibility to obtain + * export licenses, or other export authority as may be required before + * exporting such information to foreign countries or providing access to + * foreign persons. + */ + +#include "sadb_routine.h" + +static SadbRoutineStruct sadb_routine; + +SadbRoutine get_sadb_routine_mariadb(void) +{ + return &sadb_routine; +} \ No newline at end of file From 09c30fe496ed070c2abfa75665fa4e4edfbb627a Mon Sep 17 00:00:00 2001 From: IbraheemYSaleh Date: Thu, 9 Dec 2021 19:49:06 -0800 Subject: [PATCH 057/184] Fix etdt test after Managed Params Changes (#29) * WIP - fixing ET DT test after Managed Params changes * More ET test WIP length calculation changes * More WIP Unit Test fixes and length calculation adjustments * Modified Encryption test to not use Seg Header * Continuing Unit Test fixes with Seg Headers * Fixed ETDT Tests Co-authored-by: Robert Brown --- fsw/crypto_util/app/et_dt_validation.c | 144 +++++++++++++++-------- fsw/crypto_util/app/ut_tc_apply.c | 2 +- fsw/public_inc/crypto.h | 2 +- fsw/public_inc/crypto_config_structs.h | 2 + fsw/public_inc/crypto_structs.h | 3 +- fsw/src/crypto.c | 84 +++++++------ fsw/src/sadb_routine_inmemory.template.c | 3 +- python/encryption_test.py | 14 ++- 8 files changed, 169 insertions(+), 85 deletions(-) diff --git a/fsw/crypto_util/app/et_dt_validation.c b/fsw/crypto_util/app/et_dt_validation.c index c905e39e..ee4be7ba 100644 --- a/fsw/crypto_util/app/et_dt_validation.c +++ b/fsw/crypto_util/app/et_dt_validation.c @@ -21,7 +21,7 @@ #include "et_dt_validation.h" #include "utest.h" -#include +#include #include "sadb_routine.h" #include "crypto_error.h" @@ -82,20 +82,19 @@ void python_auth_encryption(char* data, char* key, char* iv, char* header, char* UTEST(ET_VALIDATION, AUTH_ENCRYPTION_TEST) { //Setup & Initialize CryptoLib - Crypto_Init(); + Crypto_Init_Unit_Test(); uint8* expected = NULL; long expected_length = 0; char *activate_sa4_h = "2003002000ff000100001880d2c9000e197f0b001b0004000400003040d95ea61a"; - char *enc_test_ping_h = "20030415001880d2ca0008197f0b0031000039c5a111"; + char *enc_test_ping_h = "2003041600ff1880d2ca0008197f0b0031000039c5082d"; uint8 *activate_sa4_b, *enc_test_ping_b = NULL; int activate_sa4_len, enc_test_ping_len = 0; hex_conversion(activate_sa4_h, &activate_sa4_b, &activate_sa4_len); hex_conversion(enc_test_ping_h, &enc_test_ping_b, &enc_test_ping_len); - SecurityAssociation_t* test_association = NULL; test_association = malloc(sizeof(SecurityAssociation_t) * sizeof(unsigned char)); @@ -106,16 +105,12 @@ UTEST(ET_VALIDATION, AUTH_ENCRYPTION_TEST) TC_t *tc_sdls_processed_frame; tc_sdls_processed_frame = malloc(sizeof(uint8) * TC_SIZE); memset(tc_sdls_processed_frame, 0, (sizeof(uint8) * TC_SIZE)); - // Ensure that Process Security can activate SA 4 Crypto_TC_ProcessSecurity(activate_sa4_b, &activate_sa4_len, tc_sdls_processed_frame); - // Expose SA 1 for testing expose_sadb_get_sa_from_spi(1,&test_association); - // Deactive SA 1 test_association->sa_state = SA_NONE; - // Expose SA 4 for testing expose_sadb_get_sa_from_spi(4, &test_association); test_association->arc_len = 0; @@ -123,17 +118,16 @@ UTEST(ET_VALIDATION, AUTH_ENCRYPTION_TEST) test_association->iv[11] = 1; test_association->ast = 1; test_association->est = 1; - Crypto_TC_ApplySecurity(enc_test_ping_b, enc_test_ping_len, &ptr_enc_frame, &enc_frame_len); - + + int32 ret_status = Crypto_TC_ApplySecurity(enc_test_ping_b, enc_test_ping_len, &ptr_enc_frame, &enc_frame_len); // Get Truth Baseline python_auth_encryption("1880d2ca0008197f0b0031000039c5", "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210", "000000000000000000000001", "2003043400FF0004", "00", &expected, &expected_length); for(int i = 0; i < expected_length; i++) { - //printf("[%d]: %02x -> %02x \n", i, expected[i], ptr_enc_frame[i]); + printf("[%d]: %02x -> %02x \n", i, expected[i], ptr_enc_frame[i]); ASSERT_EQ(expected[i], ptr_enc_frame[i]); } - free(activate_sa4_b); free(enc_test_ping_b); free(ptr_enc_frame); @@ -145,11 +139,11 @@ UTEST(ET_VALIDATION, AUTH_ENCRYPTION_TEST) UTEST(DT_VALIDATION, AUTH_DECRYPTION_TEST) { //Setup & Initialize CryptoLib - Crypto_Init(); + Crypto_Init_Unit_Test(); char *activate_sa4_h = "2003002000ff000100001880d2c9000e197f0b001b0004000400003040d95ea61a"; - char *dec_test_ping_h = "2003043400FF00040000000000000000000000017E1D8EEA8D45CEBA17888E0CDCD747DC78E5F372F997F2A63AA5DFC168395DC987"; - char *enc_test_ping_h = "1880d2ca0008197f0b0031000039c5"; + char *dec_test_ping_h = "2003043400FF00040000000000000000000000017E1D8EEA8D45CEBA17888E0CDCD747DC78E5F372F997F2A63AA5DFC168395DC987"; + char *enc_test_ping_h = "1880d2ca0008197f0b0031000039c5"; uint8 *activate_sa4_b, *dec_test_ping_b, *enc_test_ping_b = NULL; int activate_sa4_len, dec_test_ping_len, enc_test_ping_len = 0; @@ -186,6 +180,7 @@ UTEST(DT_VALIDATION, AUTH_DECRYPTION_TEST) Crypto_TC_ProcessSecurity(dec_test_ping_b, &dec_test_ping_len, tc_sdls_processed_frame); + Crypto_Shutdown(); for(int i = 0; i < tc_sdls_processed_frame->tc_pdu_len; i++) { ASSERT_EQ(enc_test_ping_b[i], tc_sdls_processed_frame->tc_pdu[i]); @@ -204,11 +199,15 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; // Setup & Initialize CryptoLib - Crypto_Init(); + //Crypto_Init_Unit_Test(); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, 0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,1,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Init(); // NIST supplied vectors // NOTE: Added Transfer Frame header to the plaintext char *buffer_nist_key_h = "ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8"; - char *buffer_nist_pt_h = "2003001100722ee47da4b77424733546c2d400c4e51069"; + char *buffer_nist_pt_h = "2003001600722ee47da4b77424733546c2d400c4e567a8"; char *buffer_nist_iv_h = "b6ac8e4963f49207ffd6374c"; char *buffer_nist_ct_h = "1224dfefb72a20d49e09256908874979"; uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; @@ -242,8 +241,10 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) // Calc payload index: total length - pt length uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + Crypto_Shutdown(); for (int i=0; i %02x \n", i, *(ptr_enc_frame+enc_data_idx), buffer_nist_ct_b[i]); ASSERT_EQ(*(ptr_enc_frame+enc_data_idx), buffer_nist_ct_b[i]); enc_data_idx++; } @@ -261,11 +262,14 @@ UTEST(NIST_DEC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; // Setup & Initialize CryptoLib - Crypto_Init(); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, 0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,1,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); + Crypto_Init(); // NIST supplied vectors // NOTE: Added Transfer Frame header to the plaintext char *buffer_nist_key_h = "ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8"; - char *buffer_nist_pt_h = "2003001100722ee47da4b77424733546c2d400c4e51069"; + char *buffer_nist_pt_h = "2003001600722ee47da4b77424733546c2d400c4e567a8"; char *buffer_nist_iv_h = "b6ac8e4963f49207ffd6374c"; char *buffer_nist_et_h = "2003002500FF0009B6AC8E4963F49207FFD6374C1224DFEFB72A20D49E09256908874979AD6F"; uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_et_b, *buffer_nist_key_b = NULL; @@ -301,8 +305,11 @@ UTEST(NIST_DEC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) Crypto_TC_ProcessSecurity(buffer_nist_et_b, &buffer_nist_et_len, tc_nist_processed_frame); + Crypto_Shutdown(); + for(int i = 0; i < tc_nist_processed_frame->tc_pdu_len; i++) { + printf("[%d]: %02x -> %02x \n", i, buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); } @@ -318,11 +325,14 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_1) uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; // Setup & Initialize CryptoLib - Crypto_Init(); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, 0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,1,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Init(); // NIST supplied vectors // NOTE: Added Transfer Frame header to the plaintext char *buffer_nist_key_h = "e9ccd6eef27f740d1d5c70b187734e11e76a8ac0ad1702ff02180c5c1c9e5399"; - char *buffer_nist_pt_h = "2003001100419635e6e12b257a8ecae411f94480ffa02a"; + char *buffer_nist_pt_h = "2003001600419635e6e12b257a8ecae411f94480ff56be"; char *buffer_nist_iv_h = "1af2613c4184dbd101fcedce"; char *buffer_nist_ct_h = "9cd21f414f1f54d5f6f58b1f2f77e5b6"; uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; @@ -356,6 +366,7 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_1) // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) // Calc payload index: total length - pt length uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + Crypto_Shutdown(); for (int i=0; itc_pdu_len; i++) { ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); @@ -430,11 +445,14 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_2) uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; // Setup & Initialize CryptoLib - Crypto_Init(); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, 0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,1,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Init(); // NIST supplied vectors // NOTE: Added Transfer Frame header to the plaintext char *buffer_nist_key_h = "7ecc9dcb3d5b413cadc3af7b7812758bd869295f8aaf611ba9935de76bd87013"; - char *buffer_nist_pt_h = "200300110073d4d7984ce422ac983797c0526ac6f9ba60"; + char *buffer_nist_pt_h = "200300160073d4d7984ce422ac983797c0526ac6f9446b"; char *buffer_nist_iv_h = "6805be41e983717bf6781052"; char *buffer_nist_ct_h = "487211dd440f4d09d00bc5c3158a822c"; uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; @@ -468,6 +486,7 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_2) // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) // Calc payload index: total length - pt length uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + Crypto_Shutdown(); for (int i=0; itc_pdu_len; i++) { ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); @@ -542,11 +565,14 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_3) uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; // Setup & Initialize CryptoLib - Crypto_Init(); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, 0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,1,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Init(); // NIST supplied vectors // NOTE: Added Transfer Frame header to the plaintext char *buffer_nist_key_h = "a881373e248615e3d6576f5a5fb68883515ae72d6a2938e3a6f0b8dcb639c9c0"; - char *buffer_nist_pt_h = "200300110007d1dc9930e710b1ebe533c81f671101ba60"; + char *buffer_nist_pt_h = "200300160007d1dc9930e710b1ebe533c81f671101e43c"; char *buffer_nist_iv_h = "f0b744f157087df4e41818a9"; char *buffer_nist_ct_h = "b65a2878b9dddbd4a0204dae6a6a6fc0"; uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; @@ -580,6 +606,7 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_3) // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) // Calc payload index: total length - pt length uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + Crypto_Shutdown(); for (int i=0; itc_pdu_len; i++) { ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); @@ -654,11 +685,14 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_4) uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; // Setup & Initialize CryptoLib - Crypto_Init(); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, 0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,1,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Init(); // NIST supplied vectors // NOTE: Added Transfer Frame header to the plaintext char *buffer_nist_key_h = "84c90349539c2a7989cb24dfae5e4182382ae94ba717d385977017f74f0d87d6"; - char *buffer_nist_pt_h = "200300110031c4e1d0ccece6b7a999bfc31f38559ab87b"; + char *buffer_nist_pt_h = "200300160031c4e1d0ccece6b7a999bfc31f38559af5dd"; char *buffer_nist_iv_h = "eeddeaf4355c826dfd153393"; char *buffer_nist_ct_h = "5c6cfbdd06c19445ecf500c21aeca173"; uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_ct_b, *buffer_nist_key_b = NULL; @@ -692,6 +726,7 @@ UTEST(NIST_ENC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_4) // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) // Calc payload index: total length - pt length uint16 enc_data_idx = enc_frame_len - buffer_nist_ct_len - 2; + Crypto_Shutdown(); for (int i=0; itc_pdu_len; i++) { ASSERT_EQ(buffer_nist_pt_b[i+5], tc_nist_processed_frame->tc_pdu[i]); @@ -778,14 +817,17 @@ UTEST(NIST_ENC_MAC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) uint8 *ptr_enc_frame = NULL; uint16 enc_frame_len = 0; // Setup & Initialize CryptoLib - Crypto_Init(); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, 0x3F); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,1,TC_HAS_FECF,TC_NO_SEGMENT_HDRS); + Crypto_Init(); // NIST supplied vectors // NOTE: Added Transfer Frame header to the plaintext char *buffer_nist_key_h = "78dc4e0aaf52d935c3c01eea57428f00ca1fd475f5da86a49c8dd73d68c8e223"; - char *buffer_nist_pt_h = "200300040028C2"; // Empty Transfer frame + char *buffer_nist_pt_h = "200300060028C2"; // Empty Transfer frame char *buffer_nist_iv_h = "d79cf22d504cc793c3fb6c8a"; char *buffer_nist_aad_h = "b96baa8c1c75a671bfb2d08d06be5f36"; // Zeroed out by abm - char *buffer_cyber_chef_mac_h = "79238ca36970658073f5d59d7aa874ef"; + char *buffer_cyber_chef_mac_h = "77e98911a1704df3d9745bc7b97cc66d"; uint8 *buffer_nist_pt_b, *buffer_nist_iv_b, *buffer_nist_key_b, *buffer_nist_aad_b, *buffer_cyber_chef_mac_b = NULL; int buffer_nist_pt_len, buffer_nist_iv_len, buffer_nist_key_len, buffer_nist_aad_len, buffer_cyber_chef_mac_len = 0; @@ -801,7 +843,7 @@ UTEST(NIST_ENC_MAC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) test_association->est = 0; test_association->arc_len = 0; test_association->shivf_len = 12; - test_association->abm_len = 20; + test_association->abm_len = 19; test_association->stmacf_len = 16; test_association->sa_state = SA_OPERATIONAL; @@ -824,6 +866,7 @@ UTEST(NIST_ENC_MAC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) // Note: For comparison, interested in the TF payload (exclude headers and FECF if present) // Calc payload index: total length - pt length uint16 enc_data_idx = enc_frame_len - buffer_cyber_chef_mac_len - 2; + Crypto_Shutdown(); for (int i=0; iest = 0; test_association->arc_len = 0; test_association->shivf_len = 12; - test_association->abm_len = 20; + test_association->abm_len = 19; memset(test_association->abm, 0xFF, (test_association->abm_len*sizeof(unsigned char))); // Bitmask test_association->stmacf_len = 16; test_association->sa_state = SA_OPERATIONAL; @@ -892,9 +938,11 @@ UTEST(NIST_ENC_MAC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_1) // Note: For comparison, primarily interested in the MAC // Calc payload index: total length - pt length uint16 enc_data_idx = enc_frame_len - buffer_cyber_chef_mac_len - 2; + Crypto_Shutdown(); + for (int i=0; itc_pdu_len; i++) { @@ -995,5 +1047,5 @@ UTEST(NIST_DEC_MAC_VALIDATION, AES_GCM_256_IV_96_PT_128_TEST_0) free(buffer_nist_mac_frame_b); free(buffer_nist_cp_b); } - + UTEST_MAIN(); diff --git a/fsw/crypto_util/app/ut_tc_apply.c b/fsw/crypto_util/app/ut_tc_apply.c index 88982a44..34beec5a 100644 --- a/fsw/crypto_util/app/ut_tc_apply.c +++ b/fsw/crypto_util/app/ut_tc_apply.c @@ -39,7 +39,7 @@ UTEST(TC_APPLY_SECURITY, NO_CRYPTO_INIT) int raw_tc_sdls_ping_len = 0; hex_conversion(raw_tc_sdls_ping_h, &raw_tc_sdls_ping_b, &raw_tc_sdls_ping_len); - Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE,0x3F); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_TRUE, 0x3F); Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); uint8 *ptr_enc_frame = NULL; diff --git a/fsw/public_inc/crypto.h b/fsw/public_inc/crypto.h index 0117b747..65113223 100644 --- a/fsw/public_inc/crypto.h +++ b/fsw/public_inc/crypto.h @@ -41,7 +41,7 @@ */ // Crypto Library Configuration functions -extern int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 process_sdls_pdus, uint8 has_pus_hdr, uint8 ignore_sa_state, uint8 ignore_anti_replay, uint8 vcid_bitmask); +extern int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 process_sdls_pdus, uint8 has_pus_hdr, uint8 ignore_sa_state, uint8 ignore_anti_replay, uint8 unique_sa_per_mapid, uint8 vcid_bitmask); extern int32 Crypto_Config_MariaDB(char* mysql_username, char* mysql_password, char* mysql_hostname, char* mysql_database, uint16 mysql_port); extern int32 Crypto_Config_Add_Gvcid_Managed_Parameter(uint8 tfvn, uint16 scid, uint8 vcid, uint8 has_fecf, uint8 has_segmentation_hdr); diff --git a/fsw/public_inc/crypto_config_structs.h b/fsw/public_inc/crypto_config_structs.h index 808ade46..4f3d22de 100644 --- a/fsw/public_inc/crypto_config_structs.h +++ b/fsw/public_inc/crypto_config_structs.h @@ -35,6 +35,7 @@ typedef enum { TC_PROCESS_SDLS_PDUS_FALSE, TC_PROCESS_SDLS_PDUS_TRUE } TcProcess typedef enum { TC_NO_PUS_HDR, TC_HAS_PUS_HDR } TcPusHdrPresent; typedef enum { TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_SA_STATE_TRUE } TcIgnoreSaState; typedef enum { TC_IGNORE_ANTI_REPLAY_FALSE, TC_IGNORE_ANTI_REPLAY_TRUE } TcIgnoreAntiReplay; +typedef enum { TC_UNIQUE_SA_PER_MAP_ID_FALSE, TC_UNIQUE_SA_PER_MAP_ID_TRUE } TcUniqueSaPerMapId; /* ** Main Crypto Configuration Block @@ -47,6 +48,7 @@ typedef struct TcPusHdrPresent has_pus_hdr; TcIgnoreSaState ignore_sa_state; //TODO - add logic that uses this configuration TcIgnoreAntiReplay ignore_anti_replay; //TODO - add logic that uses this configuration + TcUniqueSaPerMapId unique_sa_per_mapid; uint8 vcid_bitmask; } CryptoConfig_t; #define CRYPTO_CONFIG_SIZE (sizeof(CryptoConfig_t)) diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index fce80e88..61c07012 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -250,7 +250,8 @@ typedef struct uint16 fl :10; // The whole transfer frame length (max 1024) uint8 fsn :8; // Frame sequence number, also N(S), zeroed on Type-B frames } TC_FramePrimaryHeader_t; -#define TC_FRAME_PRIMARYHEADER_SIZE (sizeof(TC_FramePrimaryHeader_t)) +#define TC_FRAME_PRIMARYHEADER_STRUCT_SIZE (sizeof(TC_FramePrimaryHeader_t)) +#define TC_FRAME_HEADER_SIZE 5 typedef struct { diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index c302540c..2da3bc1d 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -129,8 +129,9 @@ static uint16 crc16Table[256]; int32 Crypto_Init_Unit_Test(void) { int32 status = OS_SUCCESS; - Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE,0x3F); + Crypto_Config_CryptoLib(SADB_TYPE_INMEMORY,CRYPTO_TC_CREATE_FECF_TRUE,TC_PROCESS_SDLS_PDUS_TRUE,TC_HAS_PUS_HDR,TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_FALSE, TC_UNIQUE_SA_PER_MAP_ID_FALSE, 0x3F); Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,0,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); + Crypto_Config_Add_Gvcid_Managed_Parameter(0,0x0003,1,TC_HAS_FECF,TC_HAS_SEGMENT_HDRS); status = Crypto_Init(); return status; } @@ -233,7 +234,7 @@ int32 Crypto_Shutdown(void) } -int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 process_sdls_pdus, uint8 has_pus_hdr, uint8 ignore_sa_state, uint8 ignore_anti_replay, uint8 vcid_bitmask) +int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 process_sdls_pdus, uint8 has_pus_hdr, uint8 ignore_sa_state, uint8 ignore_anti_replay, uint8 unique_sa_per_mapid, uint8 vcid_bitmask) { int32 status = OS_SUCCESS; crypto_config = (CryptoConfig_t*) calloc(1, CRYPTO_CONFIG_SIZE); @@ -243,6 +244,7 @@ int32 Crypto_Config_CryptoLib(uint8 sadb_type, uint8 crypto_create_fecf, uint8 p crypto_config->has_pus_hdr=has_pus_hdr; crypto_config->ignore_sa_state=ignore_sa_state; crypto_config->ignore_anti_replay=ignore_anti_replay; + crypto_config->unique_sa_per_mapid = unique_sa_per_mapid; crypto_config->vcid_bitmask=vcid_bitmask; return status; } @@ -843,7 +845,7 @@ static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame, SecurityAssociation_t *s int seg_hdr = 0;if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){seg_hdr=1;} int fecf = 0;if(current_managed_parameters->has_fecf==TC_HAS_FECF){fecf=FECF_SIZE;} int spi = 2; - int iv_size = sa_ptr->shivf_len; if(crypto_config->has_pus_hdr==TC_HAS_PUS_HDR){iv_size=sa_ptr->shivf_len - 1;} //For some reason, the interoperability tests with PUS header frames work with a 12 byte TC IV, so we'll use that for those. + int iv_size = sa_ptr->shivf_len; int mac_size = sa_ptr->stmacf_len; #ifdef TC_DEBUG @@ -858,7 +860,7 @@ static int32 Crypto_Get_tcPayloadLength(TC_t* tc_frame, SecurityAssociation_t *s OS_printf("\tTOTAL LENGTH: %d\n", (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + fecf))); #endif - return (tc_frame->tc_header.fl - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + fecf) ); + return (tc_frame->tc_header.fl + 1 - (tf_hdr + seg_hdr + spi + iv_size ) - (mac_size + fecf) ); } static int32 Crypto_Get_tmLength(int len) @@ -2263,6 +2265,7 @@ static int32 Crypto_Get_Managed_Parameters_For_Gvcid(uint8 tfvn,uint16 scid,uint } else { + OS_printf(KRED "Error: Managed Parameters for GVCID(TFVN: %d, SCID: %d, VCID: %d) not found. \n" RESET,tfvn,scid,vcid); return status; } } @@ -2294,6 +2297,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len uint8 aad[20]; gcry_cipher_hd_t tmp_hd; gcry_error_t gcry_error = GPG_ERR_NO_ERROR; + uint16 new_enc_frame_header_field_length = 0; #ifdef DEBUG OS_printf(KYEL "\n----- Crypto_TC_ApplySecurity START -----\n" RESET); @@ -2437,27 +2441,31 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len { case SA_PLAINTEXT: // Ingest length + spi_index (2) + some variable length fields - *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shplf_len; + *p_enc_frame_len = temp_tc_header.fl + 1 + 2 + sa_ptr->shplf_len; + new_enc_frame_header_field_length = (*p_enc_frame_len) - 1; case SA_AUTHENTICATION: // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size + stmacf_len - *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + *p_enc_frame_len = temp_tc_header.fl + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; + new_enc_frame_header_field_length = (*p_enc_frame_len) - 1; case SA_ENCRYPTION: // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size - *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + *p_enc_frame_len = temp_tc_header.fl + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE; + new_enc_frame_header_field_length = (*p_enc_frame_len) - 1; case SA_AUTHENTICATED_ENCRYPTION: // Ingest length + spi_index (2) + shivf_len (varies) + shsnf_len (varies) \ // + shplf_len + arc_len + pad_size + stmacf_len - *p_enc_frame_len = in_frame_length + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ + *p_enc_frame_len = temp_tc_header.fl + 1 + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + \ sa_ptr->shplf_len + sa_ptr->arc_len + TC_PAD_SIZE + sa_ptr->stmacf_len; + new_enc_frame_header_field_length = (*p_enc_frame_len) - 1; } #ifdef TC_DEBUG OS_printf(KYEL "DEBUG - Total TC Buffer to be malloced is: %d bytes\n" RESET, *p_enc_frame_len); - OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, in_frame_length); + OS_printf(KYEL "\tlen of TF\t = %d\n" RESET, temp_tc_header.fl); //OS_printf(KYEL "\tsegment hdr\t = 1\n" RESET); // TODO: Determine presence of this so not hard-coded OS_printf(KYEL "\tspi len\t\t = 2\n" RESET); OS_printf(KYEL "\tshivf_len\t = %d\n" RESET, sa_ptr->shivf_len); @@ -2467,9 +2475,9 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len OS_printf(KYEL "\tpad_size\t = %d\n" RESET, TC_PAD_SIZE); OS_printf(KYEL "\tstmacf_len\t = %d\n" RESET, sa_ptr->stmacf_len); #endif - + // Accio buffer - p_new_enc_frame = (uint8 *)malloc(*p_enc_frame_len * sizeof (unsigned char)); + p_new_enc_frame = (uint8 *)malloc((*p_enc_frame_len) * sizeof (unsigned char)); if(!p_new_enc_frame) { OS_printf(KRED "Error: Malloc for encrypted output buffer failed! \n" RESET); @@ -2479,27 +2487,27 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len CFE_PSP_MemSet(p_new_enc_frame, 0, *p_enc_frame_len); // Copy original TF header - CFE_PSP_MemCpy(p_new_enc_frame, p_in_frame, TC_FRAME_PRIMARYHEADER_SIZE); + CFE_PSP_MemCpy(p_new_enc_frame, p_in_frame, TC_FRAME_PRIMARYHEADER_STRUCT_SIZE); // Set new TF Header length // Recall: Length field is one minus total length per spec - *(p_new_enc_frame+2) = ((*(p_new_enc_frame+2) & 0xFC) | (((*p_enc_frame_len - 1) & (0x0300)) >> 8)); - *(p_new_enc_frame+3) = ((*p_enc_frame_len - 1) & (0x00FF)); + *(p_new_enc_frame+2) = ((*(p_new_enc_frame + 2) & 0xFC) | (((new_enc_frame_header_field_length) & (0x0300)) >> 8)); + *(p_new_enc_frame+3) = ((new_enc_frame_header_field_length) & (0x00FF)); #ifdef TC_DEBUG OS_printf(KYEL "Printing updated TF Header:\n\t"); - for (int i=0; ihas_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ index++; //Add 1 byte to index because segmentation header used for this gvcid. @@ -2585,11 +2593,11 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len // Will be over-written if using encryption later // and if it was present in the original TCTF //if FECF - // Even though FECF is not part of apply_security payload, we still have to subtract the length from the in_frame_length since that includes FECF length & segment header length. - tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE - segment_hdr_len - fecf_len; + // Even though FECF is not part of apply_security payload, we still have to subtract the length from the temp_tc_header.fl since that includes FECF length & segment header length. + tf_payload_len = temp_tc_header.fl - TC_FRAME_HEADER_SIZE - segment_hdr_len - fecf_len + 1; //if no FECF - //tf_payload_len = in_frame_length - TC_FRAME_PRIMARYHEADER_SIZE; - CFE_PSP_MemCpy((p_new_enc_frame+index), (p_in_frame+TC_FRAME_PRIMARYHEADER_SIZE), tf_payload_len); + //tf_payload_len = temp_tc_header.fl - TC_FRAME_PRIMARYHEADER_STRUCT_SIZE; + CFE_PSP_MemCpy((p_new_enc_frame+index), (p_in_frame+TC_FRAME_PRIMARYHEADER_STRUCT_SIZE), tf_payload_len); //index += tf_payload_len; /* @@ -2691,12 +2699,12 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) { // TODO: More robust calculation of this location - // uint16 output_loc = TC_FRAME_PRIMARYHEADER_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; + // uint16 output_loc = TC_FRAME_PRIMARYHEADER_STRUCT_SIZE + 1 + 2 + temp_SA.shivf_len + temp_SA.shsnf_len + temp_SA.shplf_len; #ifdef TC_DEBUG OS_printf("Encrypted bytes output_loc is %d\n", index); OS_printf("tf_payload_len is %d\n", tf_payload_len); OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); - for(int i=0; i < *p_enc_frame_len; i++) + for(int i=0; i < new_enc_frame_header_field_length; i++) { OS_printf("%02X", *(p_new_enc_frame + i)); } @@ -2707,7 +2715,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len tmp_hd, &p_new_enc_frame[index], // ciphertext output tf_payload_len, // length of data - (p_in_frame + TC_FRAME_PRIMARYHEADER_SIZE + segment_hdr_len), // plaintext input + (p_in_frame + TC_FRAME_HEADER_SIZE + segment_hdr_len), // plaintext input tf_payload_len // in data length ); @@ -2722,7 +2730,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len OS_printf("Encrypted bytes output_loc is %d\n", index); OS_printf("tf_payload_len is %d\n", tf_payload_len); OS_printf(KYEL "Printing TC Frame after encryption:\n\t"); - for(int i=0; i < *p_enc_frame_len; i++) + for(int i=0; i < new_enc_frame_header_field_length; i++) { OS_printf("%02X", *(p_new_enc_frame + i)); } @@ -2734,7 +2742,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) { // TODO - Know if FECF exists - mac_loc = *p_enc_frame_len - sa_ptr->stmacf_len - FECF_SIZE; + mac_loc = TC_FRAME_HEADER_SIZE + segment_hdr_len + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + sa_ptr->shplf_len + tf_payload_len; #ifdef MAC_DEBUG OS_printf(KYEL "MAC location is: %d\n" RESET, mac_loc); OS_printf(KYEL "MAC size is: %d\n" RESET, MAC_SIZE); @@ -2776,11 +2784,11 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len { // Set FECF Field if present #ifdef FECF_DEBUG - OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, *p_enc_frame_len - 2); + OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, new_enc_frame_header_field_length - 1); #endif - new_fecf = Crypto_Calc_FECF(p_new_enc_frame, *p_enc_frame_len - 2); - *(p_new_enc_frame + *p_enc_frame_len - 2) = (uint8) ((new_fecf & 0xFF00) >> 8); - *(p_new_enc_frame + *p_enc_frame_len - 1) = (uint8) (new_fecf & 0x00FF); + new_fecf = Crypto_Calc_FECF(p_new_enc_frame, new_enc_frame_header_field_length - 1); + *(p_new_enc_frame + new_enc_frame_header_field_length - 1) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(p_new_enc_frame + new_enc_frame_header_field_length ) = (uint8) (new_fecf & 0x00FF); index += 2; } @@ -2790,7 +2798,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len { OS_printf("%02X", *(p_new_enc_frame + i)); } - OS_printf("\n\tThe returned length is: %d\n" RESET, *p_enc_frame_len); + OS_printf("\n\tThe returned length is: %d\n" RESET, new_enc_frame_header_field_length); #endif *pp_in_frame = p_new_enc_frame; @@ -2816,6 +2824,13 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro gcry_error_t gcry_error = GPG_ERR_NO_ERROR; SecurityAssociation_t* sa_ptr = NULL; + if(crypto_config == NULL) + { + OS_printf(KRED "ERROR: CryptoLib Configuration Not Set! -- CRYPTO_LIB_ERR_NO_CONFIG, Will Exit\n" RESET); + status = CRYPTO_LIB_ERR_NO_CONFIG; + return status; + } + #ifdef DEBUG OS_printf(KYEL "\n----- Crypto_TC_ProcessSecurity START -----\n" RESET); #endif @@ -3202,7 +3217,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro } tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); - + x = x + tc_sdls_processed_frame->tc_pdu_len; #ifdef TC_DEBUG @@ -3375,6 +3390,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro #ifdef TC_DEBUG OS_printf(KYEL "IV: \n\t"); #endif + for (x = byte_idx; x < (byte_idx + sa_ptr->shivf_len); x++) { tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx] = (uint8)ingest[x]; @@ -3382,6 +3398,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro OS_printf("%02x", tc_sdls_processed_frame->tc_sec_header.iv[x-byte_idx]); #endif } + #ifdef TC_DEBUG OS_printf("\n"RESET); #endif @@ -3453,14 +3470,13 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro return status; } tc_sdls_processed_frame->tc_pdu_len = Crypto_Get_tcPayloadLength(tc_sdls_processed_frame, sa_ptr); - + // Copy pdu data from ingest into memory for(int i=0; itc_pdu_len; i++) { tc_sdls_processed_frame->tc_pdu[i] = ingest[x]; x++; } - // x = x + tc_sdls_processed_frame->tc_pdu_len; #ifdef TC_DEBUG diff --git a/fsw/src/sadb_routine_inmemory.template.c b/fsw/src/sadb_routine_inmemory.template.c index a9fad1e3..bea0fc91 100644 --- a/fsw/src/sadb_routine_inmemory.template.c +++ b/fsw/src/sadb_routine_inmemory.template.c @@ -290,7 +290,8 @@ static int32 sadb_get_operational_sa_from_gvcid(uint8 tfvn,uint16 scid,uint16 vc for (int i=0; i<10; i++) { - if ((sa[i].gvcid_tc_blk.tfvn == tfvn) && (sa[i].gvcid_tc_blk.scid == scid) && (sa[i].gvcid_tc_blk.vcid == vcid) && (sa[i].gvcid_tc_blk.mapid == mapid && sa[i].sa_state == SA_OPERATIONAL)) + if ((sa[i].gvcid_tc_blk.tfvn == tfvn) && (sa[i].gvcid_tc_blk.scid == scid) && (sa[i].gvcid_tc_blk.vcid == vcid) && (sa[i].sa_state == SA_OPERATIONAL) && + (crypto_config->unique_sa_per_mapid==TC_UNIQUE_SA_PER_MAP_ID_FALSE || sa[i].gvcid_tc_blk.mapid == mapid)) //only require MapID match is unique SA per MapID set (only relevant when using segmentation hdrs) { *security_association = &sa[i]; diff --git a/python/encryption_test.py b/python/encryption_test.py index a03933ba..0380fffd 100644 --- a/python/encryption_test.py +++ b/python/encryption_test.py @@ -2,7 +2,13 @@ import codecs import sys - +""" +Function: crc16 +Calculates the CRC16 for a set of byte data +@param data: byte array +@param offset: int +@param length: int +""" def crc16(data : bytearray, offset , length): if data is None or offset < 0 or offset > len(data)- 1 and offset+length > len(data): return 0 @@ -16,6 +22,11 @@ def crc16(data : bytearray, offset , length): crc = crc << 1 return crc & 0xFFFF +""" +Class: Encryption +This class is used to perform AES, GCM encryption in order to provide a truth baseline. +The baseline is compared against output created by gcrypt within TC_ApplySecurity +""" class Encryption: def __init__(self): self.results = 0x00 @@ -51,6 +62,7 @@ def encrypt(self, data, key, iv, header, bitmask): check_sum = crc16(bytearray(final_val), 0, len(final_val)) final_val += check_sum.to_bytes(2, byteorder = "big") + print(final_val.hex()) # Padding for Later # while (len(final_val.hex()) %8) != 0: # final_val += bytes.fromhex("00") From 24c2234cdf859a4fe54a780d8dfd900526737183 Mon Sep 17 00:00:00 2001 From: Ibraheem Saleh Date: Mon, 13 Dec 2021 10:11:11 -0800 Subject: [PATCH 058/184] Minor mariadb SADB and crypto config changes --- .../create_sadb.sql | 20 +- ...db_jpl_unit_test_security_associations.sql | 22 ++ ...e_sadb_unit_test_security_associations.sql | 16 +- fsw/public_inc/crypto_config.h | 1 + fsw/public_inc/crypto_config_structs.h | 2 +- fsw/src/crypto.c | 242 ++++++++++-------- fsw/src_mysql/sadb_routine_mariadb.template.c | 2 +- 7 files changed, 174 insertions(+), 131 deletions(-) create mode 100644 fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_jpl_unit_test_security_associations.sql diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql index 00c2b8d9..f3c62743 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb.sql @@ -10,17 +10,17 @@ CREATE TABLE security_associations ,ekid MEDIUMINT NOT NULL DEFAULT spi ,akid MEDIUMINT NOT NULL DEFAULT spi ,sa_state SMALLINT NOT NULL DEFAULT 0 - ,tfvn TINYINT - ,scid SMALLINT - ,vcid TINYINT - ,mapid TINYINT + ,tfvn TINYINT NOT NULL + ,scid SMALLINT NOT NULL + ,vcid TINYINT NOT NULL + ,mapid TINYINT NOT NULL DEFAULT 0 ,lpid SMALLINT - ,est SMALLINT - ,ast SMALLINT - ,shivf_len SMALLINT - ,shsnf_len SMALLINT - ,shplf_len SMALLINT - ,stmacf_len SMALLINT + ,est SMALLINT NOT NULL DEFAULT 0 + ,ast SMALLINT NOT NULL DEFAULT 0 + ,shivf_len SMALLINT NOT NULL DEFAULT 0 + ,shsnf_len SMALLINT NOT NULL DEFAULT 0 + ,shplf_len SMALLINT NOT NULL DEFAULT 0 + ,stmacf_len SMALLINT NOT NULL DEFAULT 0 ,ecs_len SMALLINT ,ecs BINARY(4) NOT NULL DEFAULT X'00000000' -- ECS_SIZE=4 ,iv_len SMALLINT NOT NULL DEFAULT 12 diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_jpl_unit_test_security_associations.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_jpl_unit_test_security_associations.sql new file mode 100644 index 00000000..045e5310 --- /dev/null +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_jpl_unit_test_security_associations.sql @@ -0,0 +1,22 @@ +USE sadb; + +-- SA 1 - CLEAR MODE +INSERT INTO security_associations (spi,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) +VALUES (1,0,0,0,1,X'0000000000000000000000000000000000000000',1,X'05',0,3,0,0); + +-- SA 2 - OPERATIONAL; ARCW:5; AES-GCM; IV:00...01; IV-len:12; MAC-len:16; Key-ID: 130, SCID 44, VC-0 +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +-- VALUES (2,130,3,1,1,12,12,X'000000000000000000000001',20,X'0000000000000000000000000000000000000000',1,X'05',11,0,44,0,0); +VALUES (2,130,3,1,0,12,12,X'000000000000000000000001',19,X'00000000000000000000000000000000000000',1,X'05',0,0,44,0,0); + +-- SA 3 - OPERATIONAL; ARCW:5; AES-GCM; IV:00...01; IV-len:12; MAC-len:16; Key-ID: 130, SCID 44, VC-1 +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +VALUES (3,130,3,1,0,12,12,X'000000000000000000000001',19,X'00000000000000000000000000000000000000',1,X'05',0,0,44,1,0); + +-- SA 4 - OPERATIONAL; ARCW:5; AES-GCM; IV:00...01; IV-len:12; MAC-len:16; Key-ID: 130, SCID 44, VC-2 +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +VALUES (4,130,3,1,0,12,12,X'000000000000000000000001',19,X'00000000000000000000000000000000000000',1,X'05',0,0,44,2,0); + +-- SA 5 - OPERATIONAL; ARCW:5; AES-GCM; IV:00...01; IV-len:12; MAC-len:16; Key-ID: 130, SCID 44, VC-3 +INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) +VALUES (4,130,3,1,0,12,12,X'000000000000000000000001',19,X'00000000000000000000000000000000000000',1,X'05',0,0,44,3,0); \ No newline at end of file diff --git a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql index acd92c60..af2efccf 100644 --- a/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql +++ b/fsw/crypto_sadb/sadb_mariadb_admin_scripts/create_sadb_unit_test_security_associations.sql @@ -2,32 +2,32 @@ USE sadb; -- SA 1 - CLEAR MODE INSERT INTO security_associations (spi,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) -VALUES (1,3,0,0,1,X'0000000000000000000000000000000000000000',1,X'0101',0,3,0,0); +VALUES (1,3,0,0,1,X'0000000000000000000000000000000000000000',1,X'05',0,3,0,0); -- SA 2 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 128 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) -VALUES (2,128,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11); +VALUES (2,128,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,X'05',11); -- SA 3 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 129 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,stmacf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) -VALUES (3,129,2,1,1,12,16,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11); +VALUES (3,129,2,1,1,12,16,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,X'05',11); -- SA 4 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) -VALUES (4,130,2,1,1,12,12,X'000000000000000000000001',20,X'0000000000000000000000000000000000000000',1,5,11,0,3,0,0); +VALUES (4,130,2,1,1,12,12,X'000000000000000000000001',20,X'0000000000000000000000000000000000000000',1,X'05',11,0,3,0,0); -- SA 5 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 131 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) -VALUES (5,131,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11); +VALUES (5,131,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,X'05',11); -- SA 6 - UNKEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: - INSERT INTO security_associations (spi,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len) -VALUES (6,1,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11); +VALUES (6,1,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,X'05',11); -- SA 7 - KEYED; ARCW:5; AES-GCM; IV:00...00; IV-len:12; MAC-len:16; Key-ID: 130 INSERT INTO security_associations (spi,ekid,sa_state,est,ast,shivf_len,iv_len,iv,abm_len,abm,arcw_len,arcw,arc_len,tfvn,scid,vcid,mapid) -VALUES (7,130,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,5,11,0,3,1,0); +VALUES (7,130,2,1,1,12,12,X'000000000000000000000000',20,X'0000000000000000000000000000000000000000',1,X'05',11,0,3,1,0); -- SA 8 - CLEAR MODE INSERT INTO security_associations (spi,sa_state,est,ast,arc_len,arc,arcw_len,arcw,tfvn,scid,vcid,mapid) -VALUES (8,3,0,0,1,X'0000000000000000000000000000000000000000',1,5,0,3,1,0); +VALUES (8,3,0,0,1,X'0000000000000000000000000000000000000000',1,X'05',0,3,1,0); diff --git a/fsw/public_inc/crypto_config.h b/fsw/public_inc/crypto_config.h index 5a04977e..677a0da0 100644 --- a/fsw/public_inc/crypto_config.h +++ b/fsw/public_inc/crypto_config.h @@ -101,6 +101,7 @@ // Generic Defines #define NUM_SA 64 + #define SPI_LEN 2 /* bytes */ #define KEY_SIZE 32 #define KEY_ID_SIZE 8 #define NUM_KEYS 256 diff --git a/fsw/public_inc/crypto_config_structs.h b/fsw/public_inc/crypto_config_structs.h index 4f3d22de..9e8c6cf2 100644 --- a/fsw/public_inc/crypto_config_structs.h +++ b/fsw/public_inc/crypto_config_structs.h @@ -47,7 +47,7 @@ typedef struct TcProcessSdlsPdus process_sdls_pdus; //Config to process SDLS extended procedure PDUs in CryptoLib TcPusHdrPresent has_pus_hdr; TcIgnoreSaState ignore_sa_state; //TODO - add logic that uses this configuration - TcIgnoreAntiReplay ignore_anti_replay; //TODO - add logic that uses this configuration + TcIgnoreAntiReplay ignore_anti_replay; TcUniqueSaPerMapId unique_sa_per_mapid; uint8 vcid_bitmask; } CryptoConfig_t; diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 2da3bc1d..5f9bbab3 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -2704,7 +2704,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len OS_printf("Encrypted bytes output_loc is %d\n", index); OS_printf("tf_payload_len is %d\n", tf_payload_len); OS_printf(KYEL "Printing TC Frame prior to encryption:\n\t"); - for(int i=0; i < new_enc_frame_header_field_length; i++) + for(int i=0; i < *p_enc_frame_len; i++) { OS_printf("%02X", *(p_new_enc_frame + i)); } @@ -2730,7 +2730,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len OS_printf("Encrypted bytes output_loc is %d\n", index); OS_printf("tf_payload_len is %d\n", tf_payload_len); OS_printf(KYEL "Printing TC Frame after encryption:\n\t"); - for(int i=0; i < new_enc_frame_header_field_length; i++) + for(int i=0; i < *p_enc_frame_len; i++) { OS_printf("%02X", *(p_new_enc_frame + i)); } @@ -2742,7 +2742,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) { // TODO - Know if FECF exists - mac_loc = TC_FRAME_HEADER_SIZE + segment_hdr_len + 2 + sa_ptr->shivf_len + sa_ptr->shsnf_len + sa_ptr->shplf_len + tf_payload_len; + mac_loc = TC_FRAME_HEADER_SIZE + segment_hdr_len + SPI_LEN + sa_ptr->shivf_len + sa_ptr->shsnf_len + sa_ptr->shplf_len + tf_payload_len; #ifdef MAC_DEBUG OS_printf(KYEL "MAC location is: %d\n" RESET, mac_loc); OS_printf(KYEL "MAC size is: %d\n" RESET, MAC_SIZE); @@ -2750,7 +2750,7 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len gcry_error = gcry_cipher_gettag( tmp_hd, &p_new_enc_frame[mac_loc], // tag output - MAC_SIZE // tag size + MAC_SIZE // tag size // TODO - use sa_ptr->abm_len instead of hardcoded mac size? ); if((gcry_error & GPG_ERR_CODE_MASK) != GPG_ERR_NO_ERROR) { @@ -2779,16 +2779,24 @@ int32 Crypto_TC_ApplySecurity(const uint8* p_in_frame, const uint16 in_frame_len */ //Only calculate & insert FECF if CryptoLib is configured to do so & gvcid includes FECF. - if( crypto_config->crypto_create_fecf==CRYPTO_TC_CREATE_FECF_TRUE && - current_managed_parameters->has_fecf==TC_HAS_FECF) + if( current_managed_parameters->has_fecf==TC_HAS_FECF ) { // Set FECF Field if present #ifdef FECF_DEBUG OS_printf(KCYN "Calcing FECF over %d bytes\n" RESET, new_enc_frame_header_field_length - 1); #endif - new_fecf = Crypto_Calc_FECF(p_new_enc_frame, new_enc_frame_header_field_length - 1); - *(p_new_enc_frame + new_enc_frame_header_field_length - 1) = (uint8) ((new_fecf & 0xFF00) >> 8); - *(p_new_enc_frame + new_enc_frame_header_field_length ) = (uint8) (new_fecf & 0x00FF); + if ( crypto_config->crypto_create_fecf==CRYPTO_TC_CREATE_FECF_TRUE ) + { + new_fecf = Crypto_Calc_FECF(p_new_enc_frame, new_enc_frame_header_field_length - 1); + *(p_new_enc_frame + new_enc_frame_header_field_length - 1) = (uint8) ((new_fecf & 0xFF00) >> 8); + *(p_new_enc_frame + new_enc_frame_header_field_length ) = (uint8) (new_fecf & 0x00FF); + } + else // CRYPTO_TC_CREATE_FECF_FALSE + { + *(p_new_enc_frame + new_enc_frame_header_field_length - 1) = (uint8) 0x00; + *(p_new_enc_frame + new_enc_frame_header_field_length ) = (uint8) 0x00; + } + index += 2; } @@ -2881,7 +2889,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro report.lspiu = tc_sdls_processed_frame->tc_sec_header.spi; // Verify - if (tc_sdls_processed_frame->tc_header.scid != (SCID & 0x3FF)) + if (tc_sdls_processed_frame->tc_header.scid != current_managed_parameters->scid) { OS_printf(KRED "Error: SCID incorrect! \n" RESET); status = OS_ERROR; @@ -2988,58 +2996,64 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro #endif // Check IV is in ARCW - if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, - sa_ptr->arcw[sa_ptr->arcw_len-1]) != CRYPTO_LIB_SUCCESS ) + if ( crypto_config->ignore_anti_replay==TC_IGNORE_ANTI_REPLAY_FALSE ) { - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) + + if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != CRYPTO_LIB_SUCCESS ) { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_WINDOW_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV not in window! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { - if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == CRYPTO_LIB_SUCCESS ) - { // Replay - IV value lower than expected report.af = 1; report.bsnf = 1; if (log_summary.rs > 0) { Crypto_increment((uint8*)&log_summary.num_se, 4); log_summary.rs--; - log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; log.blk[log_count].emv[0] = 0x4E; log.blk[log_count].emv[1] = 0x41; log.blk[log_count].emv[2] = 0x53; log.blk[log_count].emv[3] = 0x41; log.blk[log_count++].em_len = 4; } - OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + OS_printf(KRED "Error: IV not in window! \n" RESET); #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); + Crypto_fsrPrint(&report); #endif status = OS_ERROR; - } + } else - { // Adjust expected IV to acceptable received value - for (int i = 0; i < (sa_ptr->shivf_len); i++) - { - sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + { + if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == CRYPTO_LIB_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value // TODO - separate ground processing from fsw processing + for (int i = 0; i < (sa_ptr->shivf_len); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } } } + + } if ( status != CRYPTO_LIB_SUCCESS ) @@ -3155,61 +3169,64 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro OS_printf("\t sa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); #endif - // Check IV is in ARCW - if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, - sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) + if ( crypto_config->ignore_anti_replay==TC_IGNORE_ANTI_REPLAY_FALSE ) { - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) + // Check IV is in ARCW + if ( Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_WINDOW_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV not in window! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { - if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) - { // Replay - IV value lower than expected report.af = 1; report.bsnf = 1; if (log_summary.rs > 0) { Crypto_increment((uint8*)&log_summary.num_se, 4); log_summary.rs--; - log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; log.blk[log_count].emv[0] = 0x4E; log.blk[log_count].emv[1] = 0x41; log.blk[log_count].emv[2] = 0x53; log.blk[log_count].emv[3] = 0x41; log.blk[log_count++].em_len = 4; } - OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + OS_printf(KRED "Error: IV not in window! \n" RESET); #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); + Crypto_fsrPrint(&report); #endif status = OS_ERROR; - } + } else - { // Adjust expected IV to acceptable received value - for (int i = 0; i < (sa_ptr->shivf_len); i++) - { - sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + { + if ( Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value + for (int i = 0; i < (sa_ptr->shivf_len); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } } } } - + if ( status == OS_ERROR ) { // Exit *len_ingest = 0; @@ -3410,57 +3427,60 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro OS_printf("\tsa[%d].iv[%d] = 0x%02x \n", tc_sdls_processed_frame->tc_sec_header.spi, sa_ptr->shivf_len-1, sa_ptr->iv[sa_ptr->shivf_len-1]); #endif - // Check IV is in ARCW - if (Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, - sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) + if ( crypto_config->ignore_anti_replay==TC_IGNORE_ANTI_REPLAY_FALSE ) { - report.af = 1; - report.bsnf = 1; - if (log_summary.rs > 0) + // Check IV is in ARCW + if (Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]) != OS_SUCCESS ) { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = IV_WINDOW_ERR_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; - } - OS_printf(KRED "Error: IV not in window! \n" RESET); - #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); - #endif - status = OS_ERROR; - } - else - { - if (Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) - { // Replay - IV value lower than expected report.af = 1; report.bsnf = 1; if (log_summary.rs > 0) { Crypto_increment((uint8*)&log_summary.num_se, 4); log_summary.rs--; - log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emt = IV_WINDOW_ERR_EID; log.blk[log_count].emv[0] = 0x4E; log.blk[log_count].emv[1] = 0x41; log.blk[log_count].emv[2] = 0x53; log.blk[log_count].emv[3] = 0x41; log.blk[log_count++].em_len = 4; } - OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + OS_printf(KRED "Error: IV not in window! \n" RESET); #ifdef OCF_DEBUG - Crypto_fsrPrint(&report); + Crypto_fsrPrint(&report); #endif status = OS_ERROR; - } + } else - { // Adjust expected IV to acceptable received value - for (int i = 0; i < (sa_ptr->shivf_len); i++) - { - sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + { + if (Crypto_compare_less_equal(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len) == OS_SUCCESS ) + { // Replay - IV value lower than expected + report.af = 1; + report.bsnf = 1; + if (log_summary.rs > 0) + { + Crypto_increment((uint8*)&log_summary.num_se, 4); + log_summary.rs--; + log.blk[log_count].emt = IV_REPLAY_ERR_EID; + log.blk[log_count].emv[0] = 0x4E; + log.blk[log_count].emv[1] = 0x41; + log.blk[log_count].emv[2] = 0x53; + log.blk[log_count].emv[3] = 0x41; + log.blk[log_count++].em_len = 4; + } + OS_printf(KRED "Error: IV replay! Value lower than expected! \n" RESET); + #ifdef OCF_DEBUG + Crypto_fsrPrint(&report); + #endif + status = OS_ERROR; + } + else + { // Adjust expected IV to acceptable received value + for (int i = 0; i < (sa_ptr->shivf_len); i++) + { + sa_ptr->iv[i] = tc_sdls_processed_frame->tc_sec_header.iv[i]; + } } } } @@ -3703,10 +3723,10 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro { // CCSDS Pass-through #ifdef DEBUG - OS_printf(KGRN "CCSDS Pass-through \n" RESET); + OS_printf(KGRN "CCSDS Pass-through (No Extended Procedure PDU Processing) \n" RESET); #endif if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR) { - for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl - 11); x++) { + for (x = 0; x < (tc_sdls_processed_frame->tc_header.fl - 11); x++) { //TODO - Need to account for security header! ingest[x] = tc_sdls_processed_frame->tc_pdu[x]; #ifdef CCSDS_DEBUG OS_printf("tc_sdls_processed_frame->tc_pdu[%d] = 0x%02x\n", x, tc_sdls_processed_frame->tc_pdu[x]); diff --git a/fsw/src_mysql/sadb_routine_mariadb.template.c b/fsw/src_mysql/sadb_routine_mariadb.template.c index 11d5b367..cd75e25d 100644 --- a/fsw/src_mysql/sadb_routine_mariadb.template.c +++ b/fsw/src_mysql/sadb_routine_mariadb.template.c @@ -283,7 +283,7 @@ static char* convert_byte_array_to_hexstring(void* src_buffer, size_t buffer_len static int32 finish_with_error(MYSQL *con, int err) { - fprintf(stderr, "%s%s%s\n", KRED,mysql_error(con),RESET); // todo - if query fails, need to push failure message to error stack + fprintf(stderr, "%s\n", mysql_error(con)); // todo - if query fails, need to push failure message to error stack mysql_close(con); return err; } \ No newline at end of file From 2e2349e0f9843994154d4da1c96b7a61395d3243 Mon Sep 17 00:00:00 2001 From: Robert Brown <91291114+rjbrown2@users.noreply.github.com> Date: Mon, 13 Dec 2021 14:57:01 -0500 Subject: [PATCH 059/184] =?UTF-8?q?Updated=20CMake=20to=20contain=20warnin?= =?UTF-8?q?g=20and=20error=20message=20if=20proper=20packages=E2=80=A6=20(?= =?UTF-8?q?#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updated CMake to contain warning and error message if proper packages are not installed for ENCTEST * Update CMakeLists.txt * Fixing if flag issue with module message Co-authored-by: Robert Brown --- fsw/crypto_util/CMakeLists.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fsw/crypto_util/CMakeLists.txt b/fsw/crypto_util/CMakeLists.txt index 0dfc1734..4aed428e 100644 --- a/fsw/crypto_util/CMakeLists.txt +++ b/fsw/crypto_util/CMakeLists.txt @@ -19,9 +19,13 @@ include_directories(include) include_directories(../crypto/public_inc) -if(ENCTEST) +if(${ENCTEST}) find_package (Python3 REQUIRED COMPONENTS Interpreter Development) -endif(ENCTEST) + execute_process(COMMAND pip show pycryptodome RESULT_VARIABLE EXIT_CODE OUTPUT_QUIET) + if(NOT ${EXIT_CODE} EQUAL 0) + message(FATAL_ERROR "The \"pycryptodome\" Python3 package is not installed, and is required for ENCTEST.") + endif() +endif(${ENCTEST}) aux_source_directory(src UTIL_SRC_FILES) aux_source_directory(app APP_SRC_FILES) @@ -41,6 +45,8 @@ foreach(SOURCE_PATH ${SOURCE_FILES}) if(${ENCTEST} AND ${EXECUTABLE_NAME} STREQUAL et_dt_validation) target_link_libraries(${EXECUTABLE_NAME} PUBLIC ${Python3_LIBRARIES}) target_include_directories(${EXECUTABLE_NAME} PUBLIC ${Python3_INCLUDE_DIRS}) + find_library(${Python3_LIBRARIES} pycryptodome) + endif() add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD @@ -50,4 +56,4 @@ foreach(SOURCE_PATH ${SOURCE_FILES}) ) endforeach(SOURCE_PATH ${SOURCE_FILES}) -target_include_directories (Crypto PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file +target_include_directories (Crypto PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) From 1197d21992822fa804b93f9ca31cd4e0ed3a4c38 Mon Sep 17 00:00:00 2001 From: "D. Cody Cutright" Date: Tue, 14 Dec 2021 13:51:02 -0500 Subject: [PATCH 060/184] WIP on TC_Process header/field parsing --- fsw/public_inc/crypto_config_structs.h | 2 + fsw/public_inc/crypto_error.h | 2 + fsw/public_inc/crypto_structs.h | 4 +- fsw/src/crypto.c | 184 ++++++++++++++----------- 4 files changed, 112 insertions(+), 80 deletions(-) diff --git a/fsw/public_inc/crypto_config_structs.h b/fsw/public_inc/crypto_config_structs.h index 9e8c6cf2..e6474ff8 100644 --- a/fsw/public_inc/crypto_config_structs.h +++ b/fsw/public_inc/crypto_config_structs.h @@ -36,6 +36,7 @@ typedef enum { TC_NO_PUS_HDR, TC_HAS_PUS_HDR } TcPusHdrPresent; typedef enum { TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_SA_STATE_TRUE } TcIgnoreSaState; typedef enum { TC_IGNORE_ANTI_REPLAY_FALSE, TC_IGNORE_ANTI_REPLAY_TRUE } TcIgnoreAntiReplay; typedef enum { TC_UNIQUE_SA_PER_MAP_ID_FALSE, TC_UNIQUE_SA_PER_MAP_ID_TRUE } TcUniqueSaPerMapId; +typedef enum { TC_CHECK_FECF_FALSE, TC_CHECK_FECF_TRUE } TcCheckFecfBool; /* ** Main Crypto Configuration Block @@ -49,6 +50,7 @@ typedef struct TcIgnoreSaState ignore_sa_state; //TODO - add logic that uses this configuration TcIgnoreAntiReplay ignore_anti_replay; TcUniqueSaPerMapId unique_sa_per_mapid; + TcCheckFecfBool crypto_check_fecf; uint8 vcid_bitmask; } CryptoConfig_t; #define CRYPTO_CONFIG_SIZE (sizeof(CryptoConfig_t)) diff --git a/fsw/public_inc/crypto_error.h b/fsw/public_inc/crypto_error.h index 9432242b..dfb3a2dd 100644 --- a/fsw/public_inc/crypto_error.h +++ b/fsw/public_inc/crypto_error.h @@ -38,5 +38,7 @@ #define CRYPTO_LIB_ERR_NULL_BUFFER (-9) #define CRYPTO_LIB_ERR_UT_BYTE_MISMATCH (-10) #define CRYPTO_LIB_ERR_NO_CONFIG (-11) +#define CRYPTO_LIB_ERR_INVALID_FECF (-12) +#define CRYPTO_LIB_ERR_BAD_ANTIREPLAY_WINDOW (-13) #endif //_crypto_error_h_ diff --git a/fsw/public_inc/crypto_structs.h b/fsw/public_inc/crypto_structs.h index 61c07012..0a554349 100644 --- a/fsw/public_inc/crypto_structs.h +++ b/fsw/public_inc/crypto_structs.h @@ -258,8 +258,8 @@ typedef struct uint8 sh:TC_SH_SIZE; // Segment Header uint16 spi; // Security Parameter Index uint8 iv[IV_SIZE]; // Initialization Vector for encryption - //uint8 sn[TC_SN_SIZE]; // Sequence Number for anti-replay - //uint8 pad[TC_PAD_SIZE]; // Count of the used fill Bytes + uint8 sn[TC_SN_SIZE]; // Sequence Number for anti-replay + uint8 pad[TC_PAD_SIZE]; // Count of the used fill Bytes } TC_FrameSecurityHeader_t; #define TC_FRAME_SECHEADER_SIZE (sizeof(TC_FrameSecurityHeader_t)) diff --git a/fsw/src/crypto.c b/fsw/src/crypto.c index 5f9bbab3..be6f0933 100644 --- a/fsw/src/crypto.c +++ b/fsw/src/crypto.c @@ -1066,7 +1066,7 @@ int32 Crypto_increment(uint8 *num, int length) static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int window) { - int status = OS_ERROR; + int status = CRYPTO_LIB_ERR_BAD_ANTIREPLAY_WINDOW; int result = 0; uint8 temp[length]; @@ -1085,7 +1085,7 @@ static int32 Crypto_window(uint8 *actual, uint8 *expected, int length, int windo } if (result == length) { - status = OS_SUCCESS; + status = CRYPTO_LIB_SUCCESS; break; } Crypto_increment(&temp[0], length); @@ -2831,6 +2831,7 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro gcry_cipher_hd_t tmp_hd; gcry_error_t gcry_error = GPG_ERR_NO_ERROR; SecurityAssociation_t* sa_ptr = NULL; + uint8 sa_service_type = -1; if(crypto_config == NULL) { @@ -2867,11 +2868,12 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro if(status != OS_SUCCESS) {return status;} //Unable to get necessary Managed Parameters for TC TF -- return with error. - // Security Header + // Segment Header if(current_managed_parameters->has_segmentation_hdr==TC_HAS_SEGMENT_HDRS){ tc_sdls_processed_frame->tc_sec_header.sh = (uint8)ingest[byte_idx]; byte_idx++; } + // Security Header tc_sdls_processed_frame->tc_sec_header.spi = ((uint8)ingest[byte_idx] << 8) | (uint8)ingest[byte_idx+1]; byte_idx+=2; #ifdef TC_DEBUG @@ -2879,97 +2881,123 @@ int32 Crypto_TC_ProcessSecurity( char* ingest, int* len_ingest,TC_t* tc_sdls_pro OS_printf("spi = %d \n", tc_sdls_processed_frame->tc_sec_header.spi); #endif - // Checks - if (crypto_config->has_pus_hdr==TC_HAS_PUS_HDR && ((uint8)ingest[18] == 0x0B) && ((uint8)ingest[19] == 0x00) && (((uint8)ingest[20] & 0xF0) == 0x40)) - { - // User packet check only used for ESA Testing! + status = sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi,&sa_ptr); + // If no valid SPI, return + if(status != CRYPTO_LIB_SUCCESS){ + return status; + } + + // Determine SA Service Type + if ((sa_ptr->est == 0) && (sa_ptr->ast == 0)) + { + sa_service_type = SA_PLAINTEXT; + } + else if ((sa_ptr->est == 0) && (sa_ptr->ast == 1)) + { + sa_service_type = SA_AUTHENTICATION; + } + else if ((sa_ptr->est == 1) && (sa_ptr->ast == 0)) + { + sa_service_type = SA_ENCRYPTION; + } + else if ((sa_ptr->est == 1) && (sa_ptr->ast == 1)) + { + sa_service_type = SA_AUTHENTICATED_ENCRYPTION; } else - { // Update last spi used - report.lspiu = tc_sdls_processed_frame->tc_sec_header.spi; + { + // Probably unnecessary check + // Leaving for now as it would be cleaner in SA to have an association enum returned I believe + OS_printf(KRED "Error: SA Service Type is not defined! \n" RESET); + status = OS_ERROR; + return status; + } - // Verify - if (tc_sdls_processed_frame->tc_header.scid != current_managed_parameters->scid) + #ifdef TC_DEBUG + switch(sa_service_type) { - OS_printf(KRED "Error: SCID incorrect! \n" RESET); - status = OS_ERROR; - } - else - { - switch (report.lspiu) - { // Invalid SPIs fall through to trigger flag in FSR - case 0x0000: - case 0xFFFF: - status = OS_ERROR; - report.ispif = 1; - OS_printf(KRED "Error: SPI invalid! \n" RESET); - break; - default: - break; - } + case SA_PLAINTEXT: + OS_printf(KBLU "Processing a TC - CLEAR!\n" RESET); + break; + case SA_AUTHENTICATION: + OS_printf(KBLU "Processing a TC - AUTHENTICATED!\n" RESET); + break; + case SA_ENCRYPTION: + OS_printf(KBLU "Processing a TC - ENCRYPTED!\n" RESET); + break; + case SA_AUTHENTICATED_ENCRYPTION: + OS_printf(KBLU "Processing a TC - AUTHENTICATED ENCRYPTION!\n" RESET); + break; } + #endif - if ((report.lspiu > NUM_SA) && (status == OS_SUCCESS)) - { - report.ispif = 1; - OS_printf(KRED "Error: SPI value greater than NUM_SA! \n" RESET); - status = OS_ERROR; - } - if (status == OS_SUCCESS) - { - if(sadb_routine->sadb_get_sa_from_spi(report.lspiu,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - status = OS_ERROR; //Error -- unable to get SA from SPI. - } - } - if (status == OS_SUCCESS) + // TODO: Calculate lengths when needed + uint8 fecf_len = FECF_SIZE; + if(current_managed_parameters->has_fecf==TC_NO_FECF) { fecf_len = 0; } + + uint8 segment_hdr_len = SEGMENT_HDR_SIZE; + if(current_managed_parameters->has_segmentation_hdr==TC_NO_SEGMENT_HDRS) { segment_hdr_len = 0; } + + // Check FECF + if(current_managed_parameters->has_fecf==TC_HAS_FECF) + { + if(crypto_config->crypto_check_fecf == TC_CHECK_FECF_TRUE) { - if (sa_ptr->gvcid_tc_blk.mapid != TYPE_TC) - { - OS_printf(KRED "Error: SA invalid type! \n" RESET); - status = OS_ERROR; + uint16 received_fecf = (tc_sdls_processed_frame->tc_header.fl-1 & 0xFF00) || (tc_sdls_processed_frame->tc_header.fl & 0x00FF); + // Calculate our own + uint16 calculated_fecf = Crypto_Calc_FECF(ingest, len_ingest-2); + // Compare + if (received_fecf != calculated_fecf) + { + status = CRYPTO_LIB_ERR_INVALID_FECF; + return status; } } - // TODO: I don't think this is needed. - //if (status == OS_SUCCESS) - //{ - // if (sa_ptr->gvcid_tc_blk.vcid != tc_sdls_processed_frame->tc_header.vcid) - // { - // OS_printf(KRED "Error: VCID not mapped to provided SPI! \n" RESET); - // status = OS_ERROR; - // } - //} - if (status == OS_SUCCESS) + } + + // Parse the security header + tc_sdls_processed_frame->tc_sec_header.spi = (uint16)ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len]; + // Get SA via SPI + status = sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi, &sa_ptr); + if(status != CRYPTO_LIB_SUCCESS){ return status; } + // Parse IV + memcpy(&(tc_sdls_processed_frame->tc_sec_header.iv)+(IV_SIZE-sa_ptr->shivf_len), ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len + SPI_LEN], sa_ptr->shivf_len); + // Parse Sequence Number + memcpy(&(tc_sdls_processed_frame->tc_sec_header.sn)+(TC_SN_SIZE-sa_ptr->shsnf_len), ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len + SPI_LEN + sa_ptr->shivf_len], sa_ptr->shsnf_len); + // Parse pad length + memcpy(&(tc_sdls_processed_frame->tc_sec_header.pad)+(TC_PAD_SIZE-sa_ptr->shplf_len), ingest[TC_FRAME_HEADER_SIZE + segment_hdr_len + SPI_LEN + sa_ptr->shivf_len + sa_ptr->shsnf_len] , sa_ptr->shplf_len); + + // Check MAC, if applicable + if((sa_service_type == SA_AUTHENTICATION) || + (sa_service_type == SA_AUTHENTICATED_ENCRYPTION)) + { + if (crypto_config->ignore_anti_replay==TC_IGNORE_ANTI_REPLAY_FALSE ) { - if (sa_ptr->sa_state != SA_OPERATIONAL) + // If sequence number field is greater than zero, use as arsn + if(sa_ptr->shsnf_len > 0) { - OS_printf(KRED "Error: SA state not operational! \n" RESET); - status = OS_ERROR; + // Check Sequence Number is in ARCW + status = Crypto_window(tc_sdls_processed_frame->tc_sec_header.sn, sa_ptr->arc, sa_ptr->shsnf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]); + if (status != CRYPTO_LIB_SUCCESS) { return status; } + // TODO: Update SA ARC through SADB_Routine function call } - } - if (status != OS_SUCCESS) - { - report.af = 1; - if (log_summary.rs > 0) + else { - Crypto_increment((uint8*)&log_summary.num_se, 4); - log_summary.rs--; - log.blk[log_count].emt = SPI_INVALID_EID; - log.blk[log_count].emv[0] = 0x4E; - log.blk[log_count].emv[1] = 0x41; - log.blk[log_count].emv[2] = 0x53; - log.blk[log_count].emv[3] = 0x41; - log.blk[log_count++].em_len = 4; + // Check IV is in ARCW + status = Crypto_window(tc_sdls_processed_frame->tc_sec_header.iv, sa_ptr->iv, sa_ptr->shivf_len, + sa_ptr->arcw[sa_ptr->arcw_len-1]); + if (status != CRYPTO_LIB_SUCCESS) { return status; } + // TODO: Update SA IV through SADB_Routine function call } - *len_ingest = 0; - return status; + } } - if(sadb_routine->sadb_get_sa_from_spi(tc_sdls_processed_frame->tc_sec_header.spi,&sa_ptr) != OS_SUCCESS){ - //TODO - Error handling - status = OS_ERROR; //Error -- unable to get SA from SPI. - return status; - } + + // Decrypt, if applicable + + // Extended PDU processing, if applicable + if((sa_ptr->est == 1) && (sa_ptr->ast == 0)) { // Encryption Only From 60a65d61884e5f6b30e3d43a27c24b42b00f9212 Mon Sep 17 00:00:00 2001 From: Robert Brown <91291114+rjbrown2@users.noreply.github.com> Date: Tue, 14 Dec 2021 14:25:54 -0500 Subject: [PATCH 061/184] Doxygen updates (#32) * Start of Doxygen docs * Doxygen Comments Co-authored-by: Robert Brown --- CryptoLib-Doxyfile | 2579 ++++++++++++++++++++++ fsw/crypto_util/app/et_dt_validation.c | 119 +- fsw/crypto_util/app/ut_tc_apply.c | 37 +- fsw/crypto_util/src/shared_util.c | 46 +- fsw/src/crypto.c | 347 ++- fsw/src/crypto_print.c | 53 +- fsw/src/sadb_routine.c | 5 + fsw/src/sadb_routine_inmemory.template.c | 76 + python/encryption_test.py | 14 +- 9 files changed, 3191 insertions(+), 85 deletions(-) create mode 100644 CryptoLib-Doxyfile diff --git a/CryptoLib-Doxyfile b/CryptoLib-Doxyfile new file mode 100644 index 00000000..578a21e3 --- /dev/null +++ b/CryptoLib-Doxyfile @@ -0,0 +1,2579 @@ +# Doxyfile 1.8.17 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "CryptoLib" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 1.0.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +# PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +# PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./docs + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# (including Cygwin) ands Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ./fsw ./fsw/crypto_util/ut_tc_apply.c + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen +# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.doc \ + *.txt \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /