Skip to content
Permalink
Browse files

Linux: Support keys in config file (#1093)

- Signing and encryption keys are set through the configuration file.
- SoftEeprom update.
  • Loading branch information...
marceloaqno authored and mfalkvidd committed Apr 4, 2018
1 parent 4d90c00 commit 3c0b2727a56907277d4d04c985fd72b14e4a483c
Showing with 230 additions and 127 deletions.
  1. +40 −20 configure
  2. +4 −4 core/MySigning.h
  3. +20 −17 drivers/Linux/SoftEeprom.cpp
  4. +61 −6 drivers/Linux/config.c
  5. +3 −0 drivers/Linux/config.h
  6. +102 −80 hal/architecture/Linux/MyMainLinuxGeneric.cpp
@@ -113,8 +113,20 @@ MySensors options:
EOF
}

# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
LIGHT_BLUE='\033[1;34m'
NO_COLOR='\033[0m'

OK="${GREEN}[OK]${NO_COLOR}"
ERROR="${RED}[ERROR]${NO_COLOR}"
FAILED="${YELLOW}[FAILED]${NO_COLOR}"
SECTION="${LIGHT_BLUE}[SECTION]${NO_COLOR}"

function die {
echo "[ERROR] $1"
printf "${ERROR} $1 \n"
exit $2
}

@@ -497,12 +509,12 @@ CC=${CC:-gcc}
CXX=${CXX:-g++}

if [ -z "${SOC}" ]; then
echo "[SECTION] Detecting target machine."
printf "${SECTION} Detecting target machine.\n"
info=($(detect_machine))
SOC=${info[0]}
TYPE=${info[1]}
CPU=${info[2]}
echo " [OK] machine detected: SoC=${SOC}, Type=${TYPE}, CPU=${CPU}."
printf " ${OK} machine detected: SoC=${SOC}, Type=${TYPE}, CPU=${CPU}.\n"
fi

if [ -z "${CPUFLAGS}" ]; then
@@ -512,23 +524,23 @@ fi
if [[ $SOC == "BCM2835" || $SOC == "BCM2836" || $SOC == "BCM2837" ]]; then
CPPFLAGS="-DLINUX_ARCH_RASPBERRYPI $CPPFLAGS"
else
echo "[SECTION] Checking GPIO Sysfs."
printf "${SECTION} Checking GPIO Sysfs.\n"
if [[ $(eval 'ls /sys/class/gpio/export 2>/dev/null') ]]; then
echo " [OK] /sys/class/gpio/export found"
printf " ${OK} /sys/class/gpio/export found.\n"
else
echo " [WARNING] /sys/class/gpio/export not found."
fi
fi

if [ -z "${SPI_DRIVER}" ]; then
echo "[SECTION] Detecting SPI driver."
printf "${SECTION} Detecting SPI driver.\n"
if [[ $SOC == "BCM2835" || $SOC == "BCM2836" || $SOC == "BCM2837" ]]; then
SPI_DRIVER=BCM
elif [[ $(eval 'ls /dev/spidev* 2>/dev/null') ]]; then
SPI_DRIVER=SPIDEV
fi
if [ -n "${SPI_DRIVER}" ]; then
echo " [OK] SPI driver detected:${SPI_DRIVER}."
printf " ${OK} SPI driver detected:${SPI_DRIVER}.\n"
else
echo " [WARNING] No supported SPI driver detected. Using SPIDEV."
SPI_DRIVER=SPIDEV
@@ -551,6 +563,8 @@ if [ -n "${SPI_DRIVER}" ]; then
esac
fi

printf "${SECTION} Gateway configuration.\n"

if [[ ${debug} == "enable" ]]; then
CPPFLAGS="-DMY_DEBUG $CPPFLAGS"
fi
@@ -567,6 +581,7 @@ elif [[ ${gateway_type} == "mqtt" ]]; then
else
die "Invalid gateway type." 2
fi
printf " ${OK} Type: ${gateway_type}.\n"

if [[ ${transport_type} == "none" ]]; then
# Transport disabled
@@ -582,20 +597,22 @@ elif [[ ${transport_type} == "rfm95" ]]; then
else
die "Invalid transport type." 3
fi
printf " ${OK} Transport: ${transport_type}.\n"

if [[ ${signing} == "none" ]]; then
# Signing disabled
:
printf " ${OK} Signing: Disabled.\n"
elif [[ ${signing} == "software" ]]; then
CPPFLAGS="-DMY_SIGNING_SOFT $CPPFLAGS"
if [[ ${signing_request_signatures} == true ]]; then
CPPFLAGS="-DMY_SIGNING_REQUEST_SIGNATURES $CPPFLAGS"
fi
printf " ${OK} Signing: Enabled - Using key from config file.\n"
elif [[ ${signing} == "password" ]]; then
if [ -z "${security_password}" ]; then
die "You need to set the password for signing with --my-security-password= option" 6
die "You need to set the password for signing with --my-security-password option" 6
fi
echo "Simplified signing using password"
printf " ${OK} Signing: Enabled - Simplified signing using password.\n"
CPPFLAGS="-DMY_SIGNING_SIMPLE_PASSWD=\\\"${security_password}\\\" $CPPFLAGS"
else
die "Invalid signing type." 7
@@ -604,41 +621,44 @@ fi
if [[ ${encryption} == true ]]; then
# Encryption enabled on some transport
if [ -z "${security_password}" ]; then
echo "Encryption key from configuration"
printf " ${OK} Encryption: Enabled - Using key from config file.\n"
else
echo "Simplified encryption using password"
printf " ${OK} Encryption: Enabled - Simplified encryption using password.\n"
CPPFLAGS="-DMY_ENCRYPTION_SIMPLE_PASSWD=\\\"${security_password}\\\" $CPPFLAGS"
fi
else
printf " ${OK} Encryption: Disabled.\n"
fi

LDFLAGS="-pthread $LDFLAGS"
CPPFLAGS="$CPUFLAGS $CPPFLAGS"

echo "[SECTION] Detecting init system."
printf "${SECTION} Detecting init system.\n"
if [ "${NO_INIT}" ]; then
echo " [OK] no init system chosen."
printf " ${OK} No init system chosen.\n"
elif [ -x /usr/bin/systemctl ] || [ -x /bin/systemctl ]; then
INIT_SYSTEM=systemd
echo " [OK] init system detected: systemd."
printf " ${OK} Init system detected: systemd.\n"
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
INIT_SYSTEM=sysvinit
echo " [OK] init system detected: sysvinit."
printf " ${OK} Init system detected: sysvinit.\n"
else
echo " [FAILED] unknown init system."
printf " ${FAILED} Unknown init system."
fi

echo "[SECTION] Saving configuration."
printf "${SECTION} Saving configuration.\n"
echo -n "" > Makefile.inc
for param in ${params}; do
if [[ ${!param} ]]; then
echo "${param}=${!param}" >> Makefile.inc
fi
done
printf " ${OK} Saved.\n"

if [ -z "${NO_CLEAN}" ]; then
echo "[SECTION] Cleaning previous builds."
printf "${SECTION} Cleaning previous builds.\n"
make clean >/dev/null
fi


echo "[OK] Finished."
printf " ${OK} Finished.\n"
@@ -182,10 +182,10 @@
* * To generate HMAC key @verbatim --gen-soft-hmac-key @endverbatim
* * To generate %AES key @verbatim --gen-aes-key @endverbatim
* * To generate a soft serial number @verbatim --gen-soft-serial @endverbatim
* 2. Store keys/values to the gateway, execute @c mysgw with arguments
* * To store HMAC key @verbatim --set-soft-hmac-key=<DATA> @endverbatim
* * To store %AES key @verbatim --set-aes-key=<DATA> @endverbatim
* * To store soft serial number @verbatim --set-soft-serial-key=<DATA> @endverbatim
* 2. Update the gateway config file with the generated keys/valeus
* * For HMAC key @verbatim soft_hmac_key=<DATA> @endverbatim
* * For %AES key @verbatim aes_key=<DATA> @endverbatim
* * For soft serial number @verbatim soft_serial_key=<DATA> @endverbatim
*
* You are now set and ready to use message signing in your network.
* As of now, the following restrictions will be applied to your nodes:
@@ -60,9 +60,6 @@ int SoftEeprom::init(const char *fileName, size_t length)

_length = length;
_values = new uint8_t[_length];
for (size_t i = 0; i < _length; ++i) {
_values[i] = 0xFF;
}

if (stat(_fileName, &fileInfo) != 0) {
//File does not exist. Create it.
@@ -72,11 +69,16 @@ int SoftEeprom::init(const char *fileName, size_t length)
logError("Unable to create config file %s.\n", _fileName);
return -1;
}
// Fill the eeprom with 1s
for (size_t i = 0; i < _length; ++i) {
_values[i] = 0xFF;
}
myFile.write((const char*)_values, _length);
myFile.close();
} else if (fileInfo.st_size < 0 || (size_t)fileInfo.st_size != _length) {
logError("EEPROM file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n",
_fileName, _length);
destroy();
return -1;
} else {
//Read config into local memory.
@@ -100,27 +102,19 @@ void SoftEeprom::destroy()
if (_fileName) {
free(_fileName);
}
_length = 0;
}

void SoftEeprom::readBlock(void* buf, void* addr, size_t length)
{
static bool config_to_mem = false;
unsigned long int offs = reinterpret_cast<unsigned long int>(addr);

if (!config_to_mem && length) {
//Read config into local memory.
std::ifstream myFile(_fileName, std::ios::in | std::ios::binary);
if (!myFile) {
logError("Unable to open config to file %s for reading.\n", _fileName);
exit(1);
}
myFile.read((char*)_values, _length);
myFile.close();

config_to_mem = true;
if (!length) {
logError("EEPROM being read without being initialized!\n");
return;
}

if (length && offs + length <= _length) {
if (offs + length <= _length) {
memcpy(buf, _values+offs, length);
}
}
@@ -129,7 +123,16 @@ void SoftEeprom::writeBlock(void* buf, void* addr, size_t length)
{
unsigned long int offs = reinterpret_cast<unsigned long int>(addr);

if (length && offs + length <= _length) {
if (!length) {
logError("EEPROM being written without being initialized!\n");
return;
}

if (offs + length <= _length) {
if (memcmp(_values+offs, buf, length) == 0) {
return;
}

memcpy(_values+offs, buf, length);

std::ofstream myFile(_fileName, std::ios::out | std::ios::in | std::ios::binary);
@@ -49,12 +49,15 @@ int config_parse(const char *config_file)
return -1;
}

conf.verbose = 4;
conf.verbose = 7;
conf.log_pipe = 0;
conf.log_pipe_file = NULL;
conf.syslog = 0;
conf.eeprom_file = NULL;
conf.eeprom_size = 1024;
conf.eeprom_size = 0;
conf.soft_hmac_key = NULL;
conf.soft_serial_key = NULL;
conf.aes_key = NULL;

while (fgets(buf, 1024, fptr)) {
if (buf[0] != '#' && buf[0] != 10 && buf[0] != 13) {
@@ -145,6 +148,21 @@ int config_parse(const char *config_file)
return -1;
}
}
} else if (!strncmp(buf, "soft_hmac_key=", 14)) {
if (_config_parse_string(&(buf[14]), "soft_hmac_key", &conf.soft_hmac_key)) {
fclose(fptr);
return -1;
}
} else if (!strncmp(buf, "soft_serial_key=", 16)) {
if (_config_parse_string(&(buf[16]), "soft_serial_key", &conf.soft_serial_key)) {
fclose(fptr);
return -1;
}
} else if (!strncmp(buf, "aes_key=", 8)) {
if (_config_parse_string(&(buf[8]), "aes_key", &conf.aes_key)) {
fclose(fptr);
return -1;
}
} else {
logWarning("Unknown config option \"%s\".\n", buf);
}
@@ -172,36 +190,73 @@ int config_parse(const char *config_file)

void config_cleanup(void)
{
if (conf.eeprom_file) {
free(conf.eeprom_file);
if (conf.log_filepath) {
free(conf.log_filepath);
}
if (conf.log_pipe_file) {
free(conf.log_pipe_file);
}
if (conf.eeprom_file) {
free(conf.eeprom_file);
}
if (conf.soft_hmac_key) {
free(conf.soft_hmac_key);
}
if (conf.soft_serial_key) {
free(conf.soft_serial_key);
}
if (conf.aes_key) {
free(conf.aes_key);
}
}

int _config_create(const char *config_file)
{
FILE *myFile;
int ret;

const char default_conf[] = "# Logging verbosity: debug,info,notice,warn,err\n" \
const char default_conf[] = "# Logging\n" \
"# Verbosity: debug,info,notice,warn,err\n" \
"verbose=debug\n" \
"\n" \
"# Enable logging to a file.\n" \
"log_file=0\n" \
"# Log file path.\n" \
"log_filepath=/tmp/mysgw.log\n" \
"\n" \
"# Enable logging to a named pipe.\n" \
"# Use this option to view your gateway's log messages\n" \
"# from the log_pipe_file defined bellow.\n" \
"# To do so, run the following command on another terminal:\n" \
"# cat \"log_pipe_file\"\n" \
"log_pipe=0\n" \
"log_pipe_file=/tmp/mysgw.pipe\n" \
"\n" \
"# Enable logging to syslog.\n" \
"syslog=0\n" \
"\n" \
"# EEPROM settings\n" \
"eeprom_file=/etc/mysensors.eeprom\n" \
"eeprom_size=1024\n";
"eeprom_size=1024\n" \
"\n" \
"# Software signing settings\n" \
"# Note: The gateway must have been built with signing\n" \
"# support to use the options below.\n" \
"#\n" \
"# To generate a HMAC key run mysgw with: --gen-soft-hmac-key\n" \
"# copy the new key in the line below and uncomment it.\n" \
"#soft_hmac_key=\n" \
"# To generate a serial key run mysgw with: --gen-soft-serial-key\n" \
"# copy the new key in the line below and uncomment it.\n" \
"#soft_serial_key=\n" \
"\n" \
"# Encryption settings\n" \
"# Note: The gateway must have been built with encryption\n" \
"# support to use the options below.\n" \
"#\n" \
"# To generate a AES key run mysgw with: --gen-aes-key\n" \
"# copy the new key in the line below and uncomment it.\n" \
"#aes_key=\n";

myFile = fopen(config_file, "w");
if (!myFile) {
@@ -33,6 +33,9 @@ struct config {
int syslog;
char *eeprom_file;
int eeprom_size;
char *soft_hmac_key;
char *soft_serial_key;
char *aes_key;
} conf;

int config_parse(const char *config_file);
Oops, something went wrong.

0 comments on commit 3c0b272

Please sign in to comment.
You can’t perform that action at this time.