galois embedded crypto module and secure transport (#2205)

* Added RNG for NPS, cleaned up telemetry config files
* Added Rust submodules
* Added simple status message
* Updated gec transport and key exchange
* Update pprzink
* Compilation fix for Travis
This commit is contained in:
Michal Podhradsky
2018-01-18 15:09:17 -08:00
committed by Gautier Hattenberger
parent 90c2c33b02
commit d66fc0c3b7
24 changed files with 943 additions and 101 deletions
+6
View File
@@ -31,3 +31,9 @@
[submodule "sw/ext/hacl-c"] [submodule "sw/ext/hacl-c"]
path = sw/ext/hacl-c path = sw/ext/hacl-c
url = https://github.com/paparazzi/hacl-c.git url = https://github.com/paparazzi/hacl-c.git
[submodule "sw/ext/rustlink"]
path = sw/ext/rustlink
url = https://github.com/paparazzi/rustlink.git
[submodule "sw/ext/key_generator"]
path = sw/ext/key_generator
url = https://github.com/paparazzi/key_generator.git
+1 -1
View File
@@ -9,7 +9,7 @@ before_install:
- sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa -y - sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa -y
- sudo apt-get update -q - sudo apt-get update -q
install: install:
- sudo apt-get install -y --force-yes paparazzi-dev paparazzi-jsbsim gcc-arm-embedded gcc-arm-linux-gnueabi libipc-run-perl cmake - sudo apt-get install -y --force-yes paparazzi-dev paparazzi-jsbsim gcc-arm-embedded gcc-arm-linux-gnueabi libipc-run-perl rustc cargo
script: script:
- arm-none-eabi-gcc --version - arm-none-eabi-gcc --version
- if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then if [ "${TRAVIS_EVENT_TYPE}" == "cron" ]; then make test_all_confs; else make test; fi; fi - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then if [ "${TRAVIS_EVENT_TYPE}" == "cron" ]; then make test_all_confs; else make test; fi; fi
+13 -1
View File
@@ -70,6 +70,7 @@ MODULES_H=$(AC_GENERATED)/modules.h
MODULES_DIR=$(PAPARAZZI_HOME)/conf/modules/ MODULES_DIR=$(PAPARAZZI_HOME)/conf/modules/
AUTOPILOT_DIR=$(AC_GENERATED)/ AUTOPILOT_DIR=$(AC_GENERATED)/
AIRCRAFT_MD5=$(AIRCRAFT_CONF_DIR)/aircraft.md5 AIRCRAFT_MD5=$(AIRCRAFT_CONF_DIR)/aircraft.md5
GENERATE_KEYS ?= 0
UNAME = $(shell uname -s) UNAME = $(shell uname -s)
ifeq ("$(UNAME)","Darwin") ifeq ("$(UNAME)","Darwin")
@@ -176,6 +177,17 @@ else
$(Q)cd $(PAPARAZZI_SRC) ; ./sw/tools/find_vpaths.py $(CXX) $(TMP_LIST) $(PAPARAZZI_SRC) >> $(SRCS_LIST) $(Q)cd $(PAPARAZZI_SRC) ; ./sw/tools/find_vpaths.py $(CXX) $(TMP_LIST) $(PAPARAZZI_SRC) >> $(SRCS_LIST)
endif endif
CARGO=$(shell which cargo)
generate_keys:
ifeq ($(GENERATE_KEYS),1)
ifneq ($(CARGO),)
@echo GENERATE KEYS
$(Q)cargo run --manifest-path $(PAPARAZZI_SRC)/sw/ext/key_generator/Cargo.toml --release $(AC_GENERATED)
else
@echo "Error: Cargo (Rust) is not found, keys are not generated. Please install cargo."
endif
endif
qt_project : $(SRCS_LIST) qt_project : $(SRCS_LIST)
ifneq ($(PAPARAZZI_QT_GEN),) ifneq ($(PAPARAZZI_QT_GEN),)
$(Q)./sw/tools/qt_project.py $(AIRCRAFT) $(CONF_XML) $(SRCS_LIST) $(Q)./sw/tools/qt_project.py $(AIRCRAFT) $(CONF_XML) $(SRCS_LIST)
@@ -187,7 +199,7 @@ flight_plan_ac_h : $(FLIGHT_PLAN_H) $(FLIGHT_PLAN_XML)
makefile_ac: $(MAKEFILE_AC) makefile_ac: $(MAKEFILE_AC)
$(AIRFRAME_H) : $(CONF)/$(AIRFRAME_XML) $(CONF_XML) $(AIRCRAFT_MD5) $(AIRFRAME_H) : $(CONF)/$(AIRFRAME_XML) $(CONF_XML) $(AIRCRAFT_MD5) generate_keys
$(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED) $(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED)
@echo GENERATE $@ from $(AIRFRAME_XML) @echo GENERATE $@ from $(AIRFRAME_XML)
$(eval $@_TMP := $(shell $(MKTEMP))) $(eval $@_TMP := $(shell $(MKTEMP)))
@@ -26,6 +26,7 @@ Aggie Air ARK
<module name="radio_control" type="spektrum"/> <module name="radio_control" type="spektrum"/>
</target> </target>
<!-- hitl currently not supported for secure link comms
<target name="hitl" board="pc"> <target name="hitl" board="pc">
<module name="fdm" type="jsbsim"/> <module name="fdm" type="jsbsim"/>
<module name="imu" type="nps"/> <module name="imu" type="nps"/>
@@ -35,13 +36,14 @@ Aggie Air ARK
<configure name="AP_DEV" value="/dev/ttyUSB2"/> <configure name="AP_DEV" value="/dev/ttyUSB2"/>
<configure name="AP_BAUD" value="B921600"/> <configure name="AP_BAUD" value="B921600"/>
</target> </target>
-->
<module name="motor_mixing"/> <module name="motor_mixing"/>
<module name="actuators" type="pwm"> <module name="actuators" type="pwm">
<define name="SERVO_HZ" value="160"/> <define name="SERVO_HZ" value="160"/>
</module> </module>
<module name="telemetry" type="transparent"> <module name="telemetry" type="transparent_gec">
<configure name="MODEM_PORT" value="UART3"/> <configure name="MODEM_PORT" value="UART3"/>
<configure name="MODEM_BAUD" value="B57600"/> <configure name="MODEM_BAUD" value="B57600"/>
</module> </module>
@@ -56,7 +58,7 @@ Aggie Air ARK
<modules> <modules>
<module name="sys_mon"/> <module name="sys_mon"/>
<module name="rng"/> <!--module name="rng"/-->
<module name="copilot"/> <module name="copilot"/>
<module name="extra_dl"> <module name="extra_dl">
<!-- in order to use uart1 without chibios we need to remap the peripheral--> <!-- in order to use uart1 without chibios we need to remap the peripheral-->
+1 -1
View File
@@ -7,7 +7,7 @@
telemetry="telemetry/AGGIEAIR/aggieair_rotorcraft.xml" telemetry="telemetry/AGGIEAIR/aggieair_rotorcraft.xml"
flight_plan="flight_plans/rotorcraft_basic_geofence.xml" flight_plan="flight_plans/rotorcraft_basic_geofence.xml"
settings="settings/rotorcraft_basic.xml settings/nps.xml" settings="settings/rotorcraft_basic.xml settings/nps.xml"
settings_modules="modules/battery_monitor.xml modules/gps.xml modules/stabilization_float_euler.xml modules/nav_basic_rotorcraft.xml modules/guidance_rotorcraft.xml modules/imu_common.xml" settings_modules="modules/battery_monitor.xml modules/gps.xml modules/stabilization_float_euler.xml modules/nav_basic_rotorcraft.xml modules/guidance_rotorcraft.xml"
gui_color="#ffff954c0000" gui_color="#ffff954c0000"
/> />
<aircraft <aircraft
@@ -13,6 +13,16 @@
<program name="Data Link" command="sw/ground_segment/tmtc/link"> <program name="Data Link" command="sw/ground_segment/tmtc/link">
<arg flag="-d" constant="/dev/ttyUSB0"/> <arg flag="-d" constant="/dev/ttyUSB0"/>
</program> </program>
<program name="RustLink" command="sw/ext/rustlink/link">
<arg flag="-d" constant="/dev/ttyUSB0"/>
<arg flag="-a" constant="@AC_ID"/>
</program>
<program name="Secure Link" command="sw/ext/rustlink/link">
<arg flag="-d" constant="/dev/ttyUSB0"/>
<arg flag="-a" constant="@AC_ID"/>
<arg flag="-n" constant="@ACIRCRAFT"/>
<arg flag="-c" />
</program>
<program name="Link Combiner" command="sw/ground_segment/python/redundant_link/link_combiner.py"/> <program name="Link Combiner" command="sw/ground_segment/python/redundant_link/link_combiner.py"/>
<program name="GCS" command="sw/ground_segment/cockpit/gcs"/> <program name="GCS" command="sw/ground_segment/cockpit/gcs"/>
<program name="Flight Plan Editor" command="sw/ground_segment/cockpit/gcs"> <program name="Flight Plan Editor" command="sw/ground_segment/cockpit/gcs">
+5 -3
View File
@@ -7,18 +7,20 @@
see https://github.com/mitls/hacl-star for details see https://github.com/mitls/hacl-star for details
</description> </description>
</doc> </doc>
<makefile target="!fbw|sim|nps|hitl"> <makefile target="!fbw|sim">
<file name="Hacl_Chacha20Poly1305.c" dir="../ext/hacl-c"/> <file name="Hacl_Chacha20Poly1305.c" dir="../ext/hacl-c"/>
<file name="kremlib.c" dir="../ext/hacl-c"/> <file name="kremlib.c" dir="../ext/hacl-c"/>
<file name="FStar.c" dir="../ext/hacl-c"/>
<file name="Hacl_Policies.c" dir="../ext/hacl-c"/> <file name="Hacl_Policies.c" dir="../ext/hacl-c"/>
<file name="AEAD_Poly1305_64.c" dir="../ext/hacl-c"/> <file name="AEAD_Poly1305_64.c" dir="../ext/hacl-c"/>
<file name="Hacl_Chacha20.c" dir="../ext/hacl-c"/> <file name="Hacl_Chacha20.c" dir="../ext/hacl-c"/>
<file name="Hacl_Curve25519.c" dir="../ext/hacl-c"/> <file name="Hacl_Curve25519.c" dir="../ext/hacl-c"/>
<file name="Hacl_Ed25519.c" dir="../ext/hacl-c"/> <file name="Hacl_Ed25519.c" dir="../ext/hacl-c"/>
<file name="Hacl_SHA2_512.c" dir="../ext/hacl-c"/> <file name="Hacl_SHA2_512.c" dir="../ext/hacl-c"/>
<define name="KRML_NOUINT128"/>
<raw> <raw>
# to not use 128 bit arithmetic # tell Makefile.ac to generate keys
ap.CFLAGS += -DKRML_NOUINT128 GENERATE_KEYS = 1
</raw> </raw>
</makefile> </makefile>
</module> </module>
+1 -1
View File
@@ -9,7 +9,7 @@
<header> <header>
<file name="rng.h" dir="mcu_periph"/> <file name="rng.h" dir="mcu_periph"/>
</header> </header>
<makefile target="ap|fbw"> <makefile target="!fbw|sim">
<define name="USE_RNG"/> <define name="USE_RNG"/>
<file_arch name="rng_arch.c" dir="mcu_periph"/> <file_arch name="rng_arch.c" dir="mcu_periph"/>
</makefile> </makefile>
+43
View File
@@ -0,0 +1,43 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="telemetry_nps_secure" dir="datalink" task="datalink">
<doc>
<description>
Telemetry module for NPS simulation
Common parts of comms, not to be used as a stadalone module. Instead, this module
is autoloaded where appropriate.
</description>
<configure name="MODEM_DEV" value="UDPx" description="UDP port used for communication"/>
<configure name="MODEM_HOST" value="192.168.1.255" description="IP address of the ground station (can be a broadcast address)"/>
<configure name="MODEM_PORT_OUT" value="4242" description="output UDP port"/>
<configure name="MODEM_PORT_IN" value="4243" description="input UDP port"/>
<configure name="MODEM_BROADCAST" value="TRUE|FALSE" description="UDP socket in broadcast mode"/>
</doc>
<makefile target="nps|hitl">
<configure name="MODEM_DEV" default="UDP0" case="upper|lower"/>
<configure name="MODEM_PORT_OUT" default="4242"/>
<configure name="MODEM_PORT_IN" default="4243"/>
<configure name="MODEM_BROADCAST" default="TRUE"/>
<define name="USE_$(MODEM_DEV_UPPER)"/>
<define name="$(MODEM_DEV_UPPER)_HOST" value="$(MODEM_HOST)"/>
<define name="$(MODEM_DEV_UPPER)_PORT_OUT" value="$(MODEM_PORT_OUT)"/>
<define name="$(MODEM_DEV_UPPER)_PORT_IN" value="$(MODEM_PORT_IN)"/>
<define name="$(MODEM_DEV_UPPER)_BROADCAST" value="$(MODEM_BROADCAST)"/>
<define name="DOWNLINK_DEVICE" value="$(MODEM_DEV_LOWER)"/>
<define name="PPRZ_UART" value="$(MODEM_DEV_LOWER)"/>
<raw>
include $(CFG_SHARED)/udp.makefile
</raw>
</makefile>
<makefile target="nps|hitl" firmware="fixedwing">
<file name="fixedwing_datalink.c" dir="$(SRC_FIRMWARE)"/>
<file name="ap_downlink.c" dir="$(SRC_FIRMWARE)"/>
<file name="fbw_downlink.c" dir="$(SRC_FIRMWARE)"/>
</makefile>
<makefile target="nps|hitl" firmware="rotorcraft">
<file name="rotorcraft_datalink.c" dir="$(SRC_FIRMWARE)"/>
<file name="rotorcraft_telemetry.c" dir="$(SRC_FIRMWARE)"/>
</makefile>
</module>
+46
View File
@@ -0,0 +1,46 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="telemetry_secure_common" dir="datalink" task="datalink">
<doc>
<description>
Telemetry using secure PPRZ protocol - common parts
</description>
<configure name="MODEM_PORT" value="UARTx" description="UART where the modem is connected to (UART1, UART2, etc)"/>
<configure name="MODEM_BAUD" value="B57600" description="UART baud rate"/>
</doc>
<autoload name="telemetry" type="nps_secure"/>
<autoload name="telemetry" type="sim"/>
<makefile target="!fbw|sim|nps|hitl">
<configure name="MODEM_PORT" case="upper|lower"/>
<define name="USE_$(MODEM_PORT_UPPER)"/>
<define name="$(MODEM_PORT_UPPER)_BAUD" value="$(MODEM_BAUD)"/>
<define name="DOWNLINK"/>
<define name="PERIODIC_TELEMETRY"/>
<define name="DOWNLINK_DEVICE" value="$(MODEM_PORT_LOWER)"/>
<define name="PPRZ_UART" value="$(MODEM_PORT_LOWER)"/>
</makefile>
<makefile target="!fbw|sim">
<define name="DOWNLINK"/>
<define name="PERIODIC_TELEMETRY"/>
<define name="DATALINK" value="PPRZ"/>
<file name="downlink.c" dir="subsystems/datalink"/>
<file name="datalink.c" dir="subsystems/datalink"/>
<file name="telemetry.c" dir="subsystems/datalink"/>
<file name="pprz_transport.c" dir="pprzlink/src"/>
</makefile>
<makefile target="ap" firmware="fixedwing">
<file name="fixedwing_datalink.c" dir="$(SRC_FIRMWARE)"/>
<file name="ap_downlink.c" dir="$(SRC_FIRMWARE)"/>
</makefile>
<makefile target="ap|fbw" firmware="fixedwing">
<file name="fbw_downlink.c" dir="$(SRC_FIRMWARE)"/>
</makefile>
<makefile target="ap" firmware="rotorcraft">
<file name="rotorcraft_datalink.c" dir="$(SRC_FIRMWARE)"/>
<file name="rotorcraft_telemetry.c" dir="$(SRC_FIRMWARE)"/>
</makefile>
</module>
@@ -0,0 +1,27 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="telemetry_transparent_gec" dir="datalink" task="datalink">
<doc>
<description>
Galois Embedded Crypto over transparent datalink
</description>
</doc>
<autoload name="telemetry" type="secure_common"/>
<autoload name="rng"/>
<autoload name="haclc"/>
<header>
<file name="gec_dl.h"/>
</header>
<init fun="gec_dl_init()"/>
<event fun="gec_dl_event()"/>
<makefile target="!fbw|sim">
<define name="DOWNLINK_TRANSPORT" value="gec_tp"/>
<file name="gec_dl.c"/>
<file name="gec.c" dir="modules/datalink/gec"/>
</makefile>
</module>
@@ -33,6 +33,7 @@
<message name="GPS_LLA" period="1.0"/> <message name="GPS_LLA" period="1.0"/>
<message name="ATTITUDE" period="1.0"/> <message name="ATTITUDE" period="1.0"/>
<message name="SECURE_LINK_STATUS" period="1.0"/>
</mode> </mode>
<mode name="ppm"> <mode name="ppm">
@@ -174,6 +175,7 @@
<message name="ROTORCRAFT_FP" period="0.1"/> <message name="ROTORCRAFT_FP" period="0.1"/>
<message name="ATTITUDE" period="0.1"/> <message name="ATTITUDE" period="0.1"/>
<message name="VECTORNAV_INFO" period="0.1"/> <message name="VECTORNAV_INFO" period="0.1"/>
<message name="SECURE_LINK_STATUS" period="1.0"/>
</mode> </mode>
</process> </process>
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2017 Michal Podhradsky <mpodhradsky@galois.com>
*
* This file is part of Paparazzi.
*
* Paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* Paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
/** \file rng_arch.c
* \brief arch specific Random Number Generator API
*
*/
#include "mcu_periph/rng.h"
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
void rng_init(void) {}
void rng_deinit(void) {}
// Return true only if we got a new number
// that is different from the previous one
bool rng_get(uint32_t *rand_nr)
{
int fd = open("/dev/urandom", O_RDONLY);
if (fd == -1) {
printf("Cannot open /dev/urandom\n");
return false;
}
uint8_t len = sizeof(uint32_t);
uint8_t res = read(fd, rand_nr, len);
if (res != len) {
printf("Error on reading, expected %u bytes, got %u bytes\n",
len, res);
return false;
}
close(fd);
return true;
}
// Wait until we get a new number that is different
// from the previous one. We can wait forever here if
// the clocks are not setup properly.
uint32_t rng_wait_and_get(void) {
uint32_t tmp = 0;
while (!rng_get(&tmp)) {};
return tmp;
}
+127
View File
@@ -0,0 +1,127 @@
/*
* Copyright (C) 2017 Michal Podhradsky <mpodhradsky@galois.com>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file datalink/gec/gec.c
*
* Galois embedded crypto iplementation
*
*/
#include "modules/datalink/gec/gec.h"
void gec_sts_init(struct gec_sts_ctx * sts)
{
clear_sts(sts);
uint8_t theirPublicKey[PPRZ_KEY_LEN] = GCS_PUBLIC;
memcpy(&sts->theirPublicKey, theirPublicKey, PPRZ_KEY_LEN);
uint8_t myPublicKey[PPRZ_KEY_LEN] = UAV_PUBLIC;
memcpy(&sts->myPrivateKey.pub, myPublicKey, PPRZ_KEY_LEN);
uint8_t myPrivateKey[PPRZ_KEY_LEN] = UAV_PRIVATE;
memcpy(&sts->myPrivateKey.priv, myPrivateKey, PPRZ_KEY_LEN);
}
void clear_sts(struct gec_sts_ctx * sts)
{
memset(&sts->theirPublicKeyEphemeral, 0, sizeof(struct gec_pubkey));
memset(&sts->myPrivateKeyEphemeral, 0, sizeof(struct gec_privkey));
memset(&sts->theirSymmetricKey, 0, sizeof(struct gec_sym_key));
memset(&sts->mySymmetricKey, 0, sizeof(struct gec_sym_key));
sts->protocol_stage = WAIT_MSG1;
sts->party = RESPONDER;
sts->last_error = ERROR_NONE;
}
/**
* Generate private and public key pairs for future use.
*/
void generate_ephemeral_keys(struct gec_privkey *sk)
{
for (uint16_t i = 0; i < (PPRZ_KEY_LEN / sizeof(uint32_t)); i++) {
uint32_t tmp = rng_wait_and_get();
sk->priv[i] = (uint8_t) tmp;
sk->priv[i + 1] = (uint8_t) (tmp >> 8);
sk->priv[i + 2] = (uint8_t) (tmp >> 16);
sk->priv[i + 3] = (uint8_t) (tmp >> 24);
}
uint8_t basepoint[32] = {0};
basepoint[0] = 9; // default basepoint
Hacl_Curve25519_crypto_scalarmult(sk->pub, sk->priv, basepoint);
}
/**
* Derive key material for both sender and receiver
*/
void derive_key_material(struct gec_sts_ctx *ctx, uint8_t* z) {
uint8_t tmp[PPRZ_KEY_LEN*2] = {0};
uint8_t input[PPRZ_KEY_LEN+1] = {0};
// Ka|| Sa = kdf(z,0)
memcpy(input, z, PPRZ_KEY_LEN);
input[PPRZ_KEY_LEN] = 0;
Hacl_SHA2_512_hash(tmp, input, sizeof(input));
memcpy(ctx->theirSymmetricKey.key, tmp, PPRZ_KEY_LEN); // K_a
memcpy(ctx->theirSymmetricKey.nonce, &tmp[PPRZ_KEY_LEN], PPRZ_NONCE_LEN); // S_a
// Kb|| Sb = kdf(z,1)
input[PPRZ_KEY_LEN] = 1;
Hacl_SHA2_512_hash(tmp, input, sizeof(input));
memcpy(ctx->mySymmetricKey.key, tmp, PPRZ_KEY_LEN); // K_b
memcpy(ctx->mySymmetricKey.nonce, &tmp[PPRZ_KEY_LEN], PPRZ_NONCE_LEN); // S_b
}
/**
* Decrypt a message, no AAD for now
* if res == 0 everything OK
*/
uint32_t gec_decrypt(struct gec_sym_key *k, uint8_t *plaintext, uint8_t *ciphertext, uint8_t len, uint8_t *mac){
uint32_t res = Hacl_Chacha20Poly1305_aead_decrypt(plaintext,
ciphertext,
len,
mac,
NULL,
0,
k->key,
k->nonce);
return res;
}
/**
* Encrypt a message, no AAD for now
* if res == 0 everything OK
*/
uint32_t gec_encrypt(struct gec_sym_key *k, uint8_t *ciphertext, uint8_t *plaintext, uint8_t len, uint8_t *mac) {
uint32_t res = Hacl_Chacha20Poly1305_aead_encrypt(ciphertext, // ciphertext
mac, // mac
plaintext, // plaintext
len, // plaintext len
NULL, // aad
0, // aad len
k->key, // key
k->nonce); // nonce
return res;
}
+130
View File
@@ -0,0 +1,130 @@
/*
* Copyright (C) 2017 Michal Podhradsky <mpodhradsky@galois.com>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file datalink/gec/gec.h
*
* Galois embedded crypto iplementation
*
*/
#ifndef SPPRZ_GEC_H
#define SPPRZ_GEC_H
#include "std.h"
#include "mcu_periph/rng.h"
#include "generated/keys_uav.h"
#include "../ext/hacl-c/Hacl_Ed25519.h"
#include "../ext/hacl-c/Hacl_Curve25519.h"
#include "../ext/hacl-c/Hacl_SHA2_512.h"
#include "../ext/hacl-c/Hacl_Chacha20Poly1305.h"
#define PPRZ_SIGN_LEN 64
#define PPRZ_KEY_LEN 32
#define PPRZ_NONCE_LEN 12
#define PPRZ_MAC_LEN 16
typedef unsigned char ed25519_signature[64];
struct gec_privkey
{
uint8_t priv[PPRZ_KEY_LEN];
uint8_t pub[PPRZ_KEY_LEN];
};
struct gec_pubkey
{
uint8_t pub[PPRZ_KEY_LEN];
};
struct gec_sym_key
{
uint8_t key[PPRZ_KEY_LEN];
uint8_t nonce[PPRZ_NONCE_LEN];
uint32_t ctr;
};
typedef enum
{
INIT, WAIT_MSG1, WAIT_MSG2, WAIT_MSG3, CRYPTO_OK,
} stage_t;
typedef enum
{
INITIATOR, RESPONDER, CLIENT, INVALID_PARTY
} party_t;
typedef enum
{
P_AE, P_BE, SIG,
} gec_sts_msg_type_t;
typedef enum
{
ERROR_NONE,
// RESPONDER ERRORS
MSG1_TIMEOUT_ERROR,
MSG1_ENCRYPT_ERROR,
MSG3_TIMEOUT_ERROR,
MSG3_DECRYPT_ERROR,
MSG3_SIGNVERIFY_ERROR,
// INITIATOR ERRORS
MSG2_TIMEOUT_ERROR,
MSG2_DECRYPT_ERROR,
MSG2_SIGNVERIFY_ERROR,
MSG3_ENCRYPT_ERROR,
// BOTH PARTIES
UNEXPECTED_MSG_TYPE_ERROR,
UNEXPECTED_STS_STAGE_ERROR,
UNEXPECTED_MSG_ERROR
} sts_error_t;
// Intermediate data structure containing information relating to the stage of
// the STS protocol.
struct gec_sts_ctx
{
struct gec_pubkey theirPublicKey;
struct gec_privkey myPrivateKey;
struct gec_pubkey theirPublicKeyEphemeral;
struct gec_privkey myPrivateKeyEphemeral;
struct gec_sym_key theirSymmetricKey;
struct gec_sym_key mySymmetricKey;
stage_t protocol_stage;
party_t party;
sts_error_t last_error;
uint32_t counter_err;
uint32_t encrypt_err;
uint32_t decrypt_err;
};
void gec_sts_init(struct gec_sts_ctx * sts);
void clear_sts(struct gec_sts_ctx * sts);
void generate_ephemeral_keys(struct gec_privkey *sk);
void derive_key_material(struct gec_sts_ctx *sts, uint8_t* z);
uint32_t gec_encrypt(struct gec_sym_key *k, uint8_t *ciphertext,
uint8_t *plaintext, uint8_t len, uint8_t *mac);
uint32_t gec_decrypt(struct gec_sym_key *k, uint8_t *plaintext,
uint8_t *ciphertext, uint8_t len, uint8_t *mac);
#endif /* SPPRZ_GEC_H */
+372
View File
@@ -0,0 +1,372 @@
/*
* Copyright (C) 2017 Michal Podhradsky <michal.podhradsky@aggiemail.usu.edu>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
/** \file modules/datalink/spprz_dl.c
* \brief Datalink using Galois Embedded Crypto
*/
#include "gec_dl.h"
#include "modules/datalink/gec/gec.h"
#include "subsystems/datalink/datalink.h"
#include "pprzlink/messages.h"
#include <string.h> // for memset()
#if PPRZLINK_DEFAULT_VER != 2
#error "Secure link is only for Pprzlink v 2.0"
#endif
struct gec_transport gec_tp;
#if PERIODIC_TELEMETRY
#include "subsystems/datalink/telemetry.h"
static void send_secure_link_info(struct transport_tx *trans, struct link_device *dev)
{
pprz_msg_send_SECURE_LINK_STATUS(trans, dev, AC_ID,
(uint8_t*)&gec_tp.sts.protocol_stage,
(uint8_t*)&gec_tp.sts.last_error,
&gec_tp.sts.counter_err,
&gec_tp.sts.decrypt_err,
&gec_tp.sts.encrypt_err);
}
#endif
static struct gec_transport * get_trans(struct pprzlink_msg *msg)
{
return (struct gec_transport *)(msg->trans->impl);
}
static inline void insert_byte(struct gec_transport *t, const uint8_t byte) {
t->tx_msg[t->tx_msg_idx] = byte;
t->tx_msg_idx++;
}
static void put_bytes(struct pprzlink_msg *msg,
long fd __attribute__((unused)),
enum TransportDataType type __attribute__((unused)),
enum TransportDataFormat format __attribute__((unused)),
const void *bytes, uint16_t len)
{
const uint8_t *b = (const uint8_t *) bytes;
int i;
for (i = 0; i < len; i++) {
insert_byte(get_trans(msg), b[i]);
}
}
static void put_named_byte(struct pprzlink_msg *msg,
long fd __attribute__((unused)),
enum TransportDataType type __attribute__((unused)),
enum TransportDataFormat format __attribute__((unused)),
uint8_t byte, const char *name __attribute__((unused)))
{
insert_byte(get_trans(msg), byte);
}
/**
* TODO
*/
static uint8_t size_of(struct pprzlink_msg *msg, uint8_t len)
{
// message length: payload + crypto overhead
return len + get_trans(msg)->pprz_tp.trans_tx.size_of(msg, len);
// + ???; TODO depends on crypto header size
}
/**
* TODO
*/
static void start_message(struct pprzlink_msg *msg,
long fd __attribute__((unused)),
uint8_t payload_len)
{
PPRZ_MUTEX_LOCK(get_trans(msg)->mtx_tx); // lock mutex
memset(get_trans(msg)->tx_msg, _FD, TRANSPORT_PAYLOAD_LEN); // erase message data
get_trans(msg)->tx_msg_idx = 0; // reset index
// TODO add crypto header to buffer if needed
}
/**
* TODO
*/
static void end_message(struct pprzlink_msg *msg, long fd)
{
// TODO apply crypto on buffer here, or a part of it
// if valid
// encapsulated encrypted data with pprz
get_trans(msg)->pprz_tp.trans_tx.start_message(msg, fd, get_trans(msg)->tx_msg_idx);
for (int i = 0; i < get_trans(msg)->tx_msg_idx; i++) {
// add byte one by one for now
get_trans(msg)->pprz_tp.trans_tx.put_bytes(msg, _FD, DL_TYPE_UINT8, DL_FORMAT_SCALAR,
&(get_trans(msg)->tx_msg[i]), 1);
// TODO: replace with one put_bytes() call
}
get_trans(msg)->pprz_tp.trans_tx.end_message(msg, fd);
// unlock mutex
PPRZ_MUTEX_UNLOCK(get_trans(msg)->mtx_tx);
}
/**
* TODO
*/
static void overrun(struct pprzlink_msg *msg)
{
get_trans(msg)->pprz_tp.trans_tx.overrun(msg);
}
static void count_bytes(struct pprzlink_msg *msg, uint8_t bytes)
{
get_trans(msg)->pprz_tp.trans_tx.count_bytes(msg, bytes);
}
static int check_available_space(struct pprzlink_msg *msg, long *fd, uint16_t bytes)
{
return get_trans(msg)->pprz_tp.trans_tx.check_available_space(msg, fd, bytes);
}
// Init pprz transport structure
static void gec_transport_init(struct gec_transport *t)
{
t->trans_rx.msg_received = false;
t->trans_tx.size_of = (size_of_t) size_of;
t->trans_tx.check_available_space = (check_available_space_t) check_available_space;
t->trans_tx.put_bytes = (put_bytes_t) put_bytes;
t->trans_tx.put_named_byte = (put_named_byte_t) put_named_byte;
t->trans_tx.start_message = (start_message_t) start_message;
t->trans_tx.end_message = (end_message_t) end_message;
t->trans_tx.overrun = (overrun_t) overrun;
t->trans_tx.count_bytes = (count_bytes_t) count_bytes;
t->trans_tx.impl = (void *)(t);
PPRZ_MUTEX_INIT(t->mtx_tx); // init mutex, check if correct pointer
}
void gec_process_sts_msg(struct link_device *dev, struct gec_transport *trans, uint8_t *buf)
{
uint8_t sender_id = SenderIdOfPprzMsg(buf);
uint8_t msg_id = IdOfPprzMsg(buf);
if (sender_id != 0) {
// process only messages from GCS
// log an error
return;
}
uint8_t msg_type = DL_KEY_EXCHANGE_GCS_msg_type(buf);
switch (msg_id) {
case DL_KEY_EXCHANGE_GCS:
switch (trans->sts.protocol_stage) {
case WAIT_MSG1:
if (msg_type == P_AE) {
respond_sts(dev, trans, buf);
} else {
// log an error
trans->sts.last_error = UNEXPECTED_MSG_TYPE_ERROR;
}
break;
case WAIT_MSG3:
if (msg_type == SIG) {
finish_sts(dev, trans, buf);
} else {
// log an error
trans->sts.last_error = UNEXPECTED_MSG_TYPE_ERROR;
}
break;
default:
// INIT, WAIT_MSG2, CRYPTO_OK
// do nothing or log an error
trans->sts.last_error = UNEXPECTED_STS_STAGE_ERROR;
break;
}
break;
default:
// process only KEY_EXCHANGE for now
// log an error
trans->sts.last_error = UNEXPECTED_MSG_ERROR;
break;
}
}
void gec_dl_init(void)
{
// init pprz transport
pprz_transport_init(&gec_tp.pprz_tp);
// init crypto transport
gec_transport_init(&gec_tp);
// initialize keys
gec_sts_init(&gec_tp.sts);
#if PERIODIC_TELEMETRY
register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_SECURE_LINK_STATUS, send_secure_link_info);
#endif
}
void gec_dl_event(void)
{
pprz_check_and_parse(&DOWNLINK_DEVICE.device, &gec_tp.pprz_tp, gec_tp.trans_rx.payload,
(bool*) &gec_tp.trans_rx.msg_received);
if (gec_tp.trans_rx.msg_received) {
if (gec_tp.sts.protocol_stage != CRYPTO_OK) {
// message is in plaintext, treat is as such
// TODO: check for decryption
// don't pass through
gec_process_sts_msg(&DOWNLINK_DEVICE.device, &gec_tp, gec_tp.trans_rx.payload);
} else {
// attempt decryption, pass data if all good
// process decrypted message if needed
// store in dl_buffer (see macro in datalink.h)
DatalinkFillDlBuffer(gec_tp.trans_rx.payload, TRANSPORT_PAYLOAD_LEN);
// pass to datalink
DlCheckAndParse(&DOWNLINK_DEVICE.device, &gec_tp.trans_tx, dl_buffer, &dl_msg_available);
}
// reset flag
gec_tp.trans_rx.msg_received = false;
}
}
/**
* message1 = [ Pae (32 bytes) ]
* 2. B generates ephemeral curve25519 key pair (Pbe, Qbe).
* 3. B computes the shared secret: z = scalar_multiplication(Qbe, Pae)
* 4. B uses the key derivation function kdf(z,1) to compute Kb || Sb,
* kdf(z,0) to compute Ka || Sa, and kdf(z,2) to compute Kclient || Sclient.
* 5. B computes the ed25519 signature: sig = signQb(Pbe || Pae)
* 6. B computes and sends the message Pbe || Ekey=Kb,IV=Sb||zero(sig)
*
* Sends: message2 = [ Pbe (32 bytes) | Encrypted Signature (64 bytes) ] + MAC (16bytes)
*/
void respond_sts(struct link_device *dev, struct gec_transport *trans, uint8_t *buf) {
// TODO: check message length
// copy P_ae over
memcpy(trans->sts.theirPublicKeyEphemeral.pub, DL_KEY_EXCHANGE_GCS_msg_data(buf), sizeof(struct gec_pubkey));
// 2. B generates ephemeral curve25519 key pair (Pbe, Qbe).
generate_ephemeral_keys(&trans->sts.myPrivateKeyEphemeral);
// 3. B computes the shared secret: z = scalar_multiplication(Qbe, Pae)
uint8_t z[32] = {0};
Hacl_Curve25519_crypto_scalarmult(z, trans->sts.myPrivateKeyEphemeral.priv, trans->sts.theirPublicKeyEphemeral.pub);
// 4. B uses the key derivation function kdf(z,1) to compute Kb || Sb,
// kdf(z,0) to compute Ka || Sa, and kdf(z,2) to compute Kclient || Sclient.
derive_key_material(&trans->sts, z);
// 5. B computes the ed25519 signature: sig = signQb(Pbe || Pae)
uint8_t sig[PPRZ_SIGN_LEN] = {0};
uint8_t pbe_concat_p_ae[PPRZ_KEY_LEN*2] = {0};
memcpy(pbe_concat_p_ae, trans->sts.myPrivateKeyEphemeral.pub, PPRZ_KEY_LEN);
memcpy(&pbe_concat_p_ae[PPRZ_KEY_LEN], trans->sts.theirPublicKeyEphemeral.pub, PPRZ_KEY_LEN);
Hacl_Ed25519_sign(sig, trans->sts.myPrivateKey.priv, pbe_concat_p_ae, PPRZ_KEY_LEN*2);
// 6. B computes and sends the message Pbe || Ekey=Kb,IV=Sb||zero(sig)
uint8_t msg_data[PPRZ_KEY_LEN + PPRZ_SIGN_LEN + PPRZ_MAC_LEN] = {0};
memcpy(msg_data, &trans->sts.myPrivateKeyEphemeral.pub, PPRZ_KEY_LEN);
if (gec_encrypt(&trans->sts.mySymmetricKey, &msg_data[PPRZ_KEY_LEN], sig, PPRZ_SIGN_LEN, &msg_data[PPRZ_KEY_LEN + PPRZ_SIGN_LEN])) {
// log error here and return
trans->sts.last_error = MSG1_ENCRYPT_ERROR;
return;
}
// all good, send message and increment status
uint8_t msg_type = P_BE;
uint8_t nb_msg_data = PPRZ_KEY_LEN + PPRZ_SIGN_LEN + PPRZ_MAC_LEN;
pprz_msg_send_KEY_EXCHANGE_UAV(&trans->trans_tx, dev, AC_ID, &msg_type, nb_msg_data, msg_data);
// update protocol stage
trans->sts.protocol_stage = WAIT_MSG3;
// TODO: add timeout
}
/**
* Finalize STS exchange
*
* message3 = [ Encrypted Signature (64 bytes) ] + MAC(16 bytes) = Ekey=Ka,IV=Sa||zero(sig)
* where sig = signQa(Pae || Pbe)
* 13. B decrypts the message and verifies the signature.
*/
void finish_sts(struct link_device *dev __attribute__((__unused__)),
struct gec_transport *trans,
uint8_t *buf){
// TODO: check message length
// decrypt
uint8_t sign[PPRZ_SIGN_LEN] = {0};
if (gec_decrypt(&trans->sts.theirSymmetricKey, sign, DL_KEY_EXCHANGE_GCS_msg_data(buf),
PPRZ_SIGN_LEN, DL_KEY_EXCHANGE_GCS_msg_data(buf)+PPRZ_SIGN_LEN)) {
// log error and return
// MSG3 decrypt error
trans->sts.last_error = MSG3_DECRYPT_ERROR;
return;
}
// verify
uint8_t pbe_concat_p_ae[PPRZ_KEY_LEN*2] = {0};
memcpy(pbe_concat_p_ae, trans->sts.myPrivateKeyEphemeral.pub, PPRZ_KEY_LEN);
memcpy(&pbe_concat_p_ae[PPRZ_KEY_LEN], trans->sts.theirPublicKeyEphemeral.pub, PPRZ_KEY_LEN);
// returns true if verified properly
if (!Hacl_Ed25519_verify(trans->sts.theirPublicKey.pub, pbe_concat_p_ae, PPRZ_SIGN_LEN, sign)) {
// log error and return
// MSG3 sign verify error
trans->sts.last_error = MSG3_SIGNVERIFY_ERROR;
return;
}
/*
// update the transport
// tx key => my symm key
memcpy(trans->tx_key, sts.mySymmetricKey.key, PPRZ_KEY_LEN);
// tx nonce (12 bytes, first 4 bytes will be overwritten by the counter)
memcpy(trans->tx_nonce, sts.mySymmetricKey.nonce, PPRZ_NONCE_LEN);
// rx key => their symm key
memcpy(trans->rx_key, sts.theirSymmetricKey.key, PPRZ_KEY_LEN);
// rx nonce (12 bytes, first 4 bytes will be overwritten by the counter)
memcpy(trans->rx_nonce, sts.theirSymmetricKey.nonce, PPRZ_NONCE_LEN);
*/
// if everything went OK, proceed to CRYPTO_OK status
trans->sts.protocol_stage = CRYPTO_OK;
}
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2017 Michal Podhradsky <michal.podhradsky@aggiemail.usu.edu>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
/** \file modules/datalink/gec_dl.h
* \brief Datalink using Galois Embedded Crypto
*/
#ifndef GEC_DL_H
#define GEC_DL_H
#include "pprzlink/pprzlink_transport.h"
#include "pprzlink/pprz_transport.h"
#include "modules/datalink/gec/gec.h"
#include "pprz_mutex.h"
#include "mcu_periph/uart.h"
#if USE_USB_SERIAL
#include "mcu_periph/usb_serial.h"
#endif
#if USE_UDP
#include "mcu_periph/udp.h"
#endif
struct gec_transport {
// pprz encapsulation layer
struct pprz_transport pprz_tp;
// generic reception interface
struct transport_rx trans_rx;
// generic transmission interface
struct transport_tx trans_tx;
// buffered tx message
uint8_t tx_msg[TRANSPORT_PAYLOAD_LEN];
volatile uint8_t tx_msg_idx;
// ecnryption primitives
struct gec_sts_ctx sts;
PPRZ_MUTEX(mtx_tx); // optional mutex
};
/** PPRZ transport structure */
extern struct gec_transport gec_tp;
/** Init function */
extern void gec_dl_init(void);
/** Datalink Event */
extern void gec_dl_event(void);
/** Parsing a frame data and copy the payload to the datalink buffer */
void gec_check_and_parse(struct link_device *dev, struct gec_transport *trans,
uint8_t *buf, bool *msg_available);
void gec_process_sts_msg(struct link_device *dev, struct gec_transport *trans, uint8_t *buf);
void respond_sts(struct link_device *dev, struct gec_transport *trans, uint8_t *buf);
void finish_sts(struct link_device *dev, struct gec_transport *trans, uint8_t *buf);
#endif /* GEC_DL_H */
-40
View File
@@ -1,40 +0,0 @@
/*
* Copyright (C) 2017 Michal Podhradsky <michal.podhradsky@aggiemail.usu.edu>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
/** \file modules/datalink/spprz_dl.c
* \brief Datalink using secure PPRZ protocol
*/
#include "modules/datalink/spprz_dl.h"
#include "subsystems/datalink/datalink.h"
struct spprz_transport spprz_tp;
void spprz_dl_init(void)
{
spprz_transport_init(&spprz_tp);
}
void spprz_dl_event(void)
{
spprz_check_and_parse(&DOWNLINK_DEVICE.device, &spprz_tp, dl_buffer, &dl_msg_available);
DlCheckAndParse(&DOWNLINK_DEVICE.device, &spprz_tp.trans_tx, dl_buffer, &dl_msg_available);
}
-49
View File
@@ -1,49 +0,0 @@
/*
* Copyright (C) 2017 Michal Podhradsky <michal.podhradsky@aggiemail.usu.edu>
*
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
/** \file modules/datalink/spprz_dl.h
* \brief Datalink using secure PPRZ protocol
*/
#ifndef SPPRZ_DL_H
#define SPPRZ_DL_H
#include "pprzlink/secure_pprz_transport.h"
#include "mcu_periph/uart.h"
#if USE_USB_SERIAL
#include "mcu_periph/usb_serial.h"
#endif
#if USE_UDP
#include "mcu_periph/udp.h"
#endif
/** PPRZ transport structure */
extern struct spprz_transport spprz_tp;
/** Init function */
extern void spprz_dl_init(void);
/** Datalink Event */
extern void spprz_dl_event(void);
#endif /* SPPRZ_DL_H */
+1 -1
View File
@@ -67,7 +67,7 @@ EXTERN bool datalink_enabled;
/** Convenience macro to fill dl_buffer */ /** Convenience macro to fill dl_buffer */
#define DatalinkFillDlBuffer(_buf, _len) { \ #define DatalinkFillDlBuffer(_buf, _len) { \
uint8_t _i = 0; \ uint16_t _i = 0; \
for (_i = 0; _i < _len; _i++) { \ for (_i = 0; _i < _len; _i++) { \
dl_buffer[_i] = _buf[_i]; \ dl_buffer[_i] = _buf[_i]; \
} \ } \
+3 -1
View File
@@ -33,7 +33,7 @@ EXT_DIR=$(PAPARAZZI_SRC)/sw/ext
include $(PAPARAZZI_SRC)/conf/Makefile.arm-embedded-toolchain include $(PAPARAZZI_SRC)/conf/Makefile.arm-embedded-toolchain
all: libopencm3 luftboot chibios fatfs libsbp mavlink TRICAL hacl-c all: libopencm3 luftboot chibios fatfs libsbp mavlink TRICAL hacl-c key_generator
# update (and init if needed) all submodules # update (and init if needed) all submodules
update_submodules: update_submodules:
@@ -67,6 +67,8 @@ luftboot_flash: luftboot.build
hacl-c: hacl-c.update hacl-c: hacl-c.update
key_generator: key_generator.update
chibios: chibios.update chibios: chibios.update
TRICAL: TRICAL.update TRICAL: TRICAL.update
+1
Submodule sw/ext/rustlink added at 1e70ae72d4