Galois Embedded Crypto module updates (#2235)

* Bump rustlink

* Changes in GEC, now communication and key exchange works. TODO is key renegotiation and some cleanup

* Bump pprzlink

* Update in GEC and related control panel configs

* Updated name

* Bump rustlink

* Changes in GEC, now communication and key exchange works. TODO is key renegotiation and some cleanup

* Bump pprzlink

* Update in GEC and related control panel configs

* Update atomic settings

* Minor changes, style fix

* Code style fix

* More code style fix
This commit is contained in:
Michal Podhradsky
2018-02-12 16:36:11 -08:00
committed by GitHub
parent 1f85390422
commit 4e80b97050
10 changed files with 742 additions and 369 deletions
@@ -11,8 +11,8 @@ AggieAir Atomic Tangerine
<module name="radio_control" type="sbus">
<configure name="SBUS_PORT" value="UART5"/>
</module>
<configure name="HAS_LUFTBOOT" value="0"/>
<configure name="FLASH_MODE" value="SWD"/>
<configure name="HAS_LUFTBOOT" value="1"/>
<configure name="FLASH_MODE" value="DFU"/>
</target>
<!-- NOTE: if you want to use extra_dl module for HITL
@@ -39,9 +39,10 @@ AggieAir Atomic Tangerine
<module name="control"/>
<module name="navigation"/>
<module name="telemetry" type="transparent">
<module name="telemetry" type="transparent_gec">
<configure name="MODEM_PORT" value="UART3"/>
<configure name="MODEM_BAUD" value="B57600"/>
<define name="GEC_STATUS_LED" value="5"/>
</module>
<module name="ins" type="vectornav">
@@ -31,7 +31,6 @@
settings="settings/fixedwing_basic.xml settings/nps.xml"
settings_modules="modules/battery_monitor.xml modules/lidar_sf11.xml modules/nav_skid_landing.xml modules/nav_survey_poly_osam.xml modules/gps.xml modules/nav_basic_fw.xml modules/guidance_basic_fw.xml modules/stabilization_attitude_fw.xml"
gui_color="#ffff42870000"
release=""
/>
<aircraft
name="BluJay_Goose"
@@ -20,7 +20,7 @@
<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="-n" constant="@AIRCRAFT"/>
<arg flag="-c" />
</program>
<program name="Link Combiner" command="sw/ground_segment/python/redundant_link/link_combiner.py"/>
@@ -107,6 +107,46 @@
<program name="Real-time Plotter"/>
</session>
<session name="Secure Flight USB-serial@57600">
<program name="Secure Link">
<arg flag="-d" constant="/dev/ttyUSB0"/>
<arg flag="-s" constant="57600"/>
<arg flag="-a" constant="@AC_ID"/>
<arg flag="-n" constant="@AIRCRAFT"/>
<arg flag="-c" />
</program>
<program name="Server"/>
<program name="GCS">
<arg flag="-layout" constant="AGGIEAIR/vertical.xml"/>
</program>
<program name="Messages"/>
<program name="Real-time Plotter"/>
</session>
<session name="Secure Simulation">
<program name="Secure Link">
<arg flag="--udp"/>
<arg flag="-a" constant="@AC_ID"/>
<arg flag="-n" constant="@AIRCRAFT"/>
<arg flag="-c" />
</program>
<program name="Server">
<arg flag="-n"/>
</program>
<program name="GCS">
<arg flag="-layout" constant="AGGIEAIR/vertical.xml"/>
</program>
<program name="Simulator">
<arg flag="-a" constant="@AIRCRAFT"/>
<arg flag="-f" constant="127.0.0.1"/>
<arg flag="-b" constant="127.255.255.255"/>
<arg flag="--fg_fdm"/>
<arg flag="--nodisplay"/>
</program>
<program name="Messages"/>
<program name="Environment Simulator"/>
</session>
<session name="Flight USB-serial@115200">
<program name="Data Link">
<arg flag="-d" constant="/dev/ttyUSB0"/>
@@ -1,49 +0,0 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="telemetry_transparent_secure" dir="datalink" task="datalink">
<doc>
<description>
Telemetry using secure PPRZ protocol over UART
Similar to telemetry_transparent, except it uses message scheduling and encryption
</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"/>
<autoload name="telemetry" type="sim"/>
<autoload name="haclc"/>
<header>
<file name="spprz_dl.h"/>
</header>
<init fun="spprz_dl_init()"/>
<periodic fun="spprz_dl_periodic()" freq="PERIODIC_FREQUENCY" autorun="TRUE"/>
<event fun="spprz_dl_event()"/>
<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)"/>
<define name="DOWNLINK_TRANSPORT" value="spprz_tp"/>
<define name="DATALINK" value="PPRZ"/>
<file name="spprz_dl.c"/>
<file name="downlink.c" dir="subsystems/datalink"/>
<file name="datalink.c" dir="subsystems/datalink"/>
<file name="telemetry.c" dir="subsystems/datalink"/>
<file name="secure_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>
+40 -57
View File
@@ -26,27 +26,38 @@
*/
#include "modules/datalink/gec/gec.h"
void gec_sts_init(struct gec_sts_ctx * sts)
void gec_sts_init(struct gec_sts_ctx *sts)
{
clear_sts(sts);
// reset all keys
gec_clear_sts(sts);
// load their public key
uint8_t theirPublicKey[PPRZ_KEY_LEN] = GCS_PUBLIC;
memcpy(&sts->theirPublicKey, theirPublicKey, PPRZ_KEY_LEN);
memcpy(&sts->their_public_key, theirPublicKey, PPRZ_KEY_LEN);
sts->their_public_key.ready = true;
// load my private key
uint8_t myPublicKey[PPRZ_KEY_LEN] = UAV_PUBLIC;
memcpy(&sts->myPrivateKey.pub, myPublicKey, PPRZ_KEY_LEN);
memcpy(&sts->my_private_key.pub, myPublicKey, PPRZ_KEY_LEN);
uint8_t myPrivateKey[PPRZ_KEY_LEN] = UAV_PRIVATE;
memcpy(&sts->myPrivateKey.priv, myPrivateKey, PPRZ_KEY_LEN);
memcpy(&sts->my_private_key.priv, myPrivateKey, PPRZ_KEY_LEN);
sts->my_private_key.ready = true;
// generate ephemeral key
gec_generate_ephemeral_keys(&sts->my_private_ephemeral);
}
void clear_sts(struct gec_sts_ctx * sts)
void gec_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));
memset(&sts->their_public_ephemeral, 0, sizeof(struct gec_pubkey));
sts->their_public_ephemeral.ready = false;
memset(&sts->my_private_ephemeral, 0, sizeof(struct gec_privkey));
sts->my_private_ephemeral.ready = false;
memset(&sts->rx_sym_key, 0, sizeof(struct gec_sym_key));
sts->rx_sym_key.ready = false;
memset(&sts->tx_sym_key, 0, sizeof(struct gec_sym_key));
sts->tx_sym_key.ready = false;
sts->protocol_stage = WAIT_MSG1;
sts->party = RESPONDER;
sts->last_error = ERROR_NONE;
@@ -55,73 +66,45 @@ void clear_sts(struct gec_sts_ctx * sts)
/**
* Generate private and public key pairs for future use.
*/
void generate_ephemeral_keys(struct gec_privkey *sk)
void gec_generate_ephemeral_keys(struct gec_privkey *sk)
{
for (uint16_t i = 0; i < (PPRZ_KEY_LEN / sizeof(uint32_t)); i++) {
for (uint16_t i = 0; i < PPRZ_KEY_LEN; i += sizeof(uint32_t)) {
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);
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);
sk->ready = true;
}
/**
* 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};
void gec_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
memcpy(ctx->rx_sym_key.key, tmp, PPRZ_KEY_LEN); // K_a
memcpy(ctx->rx_sym_key.nonce, &tmp[PPRZ_KEY_LEN], PPRZ_NONCE_LEN); // S_a
ctx->rx_sym_key.counter = 0;
ctx->rx_sym_key.ready = true;
// 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
memcpy(ctx->tx_sym_key.key, tmp, PPRZ_KEY_LEN); // K_b
memcpy(ctx->tx_sym_key.nonce, &tmp[PPRZ_KEY_LEN], PPRZ_NONCE_LEN); // S_b
ctx->tx_sym_key.counter = 0;
ctx->tx_sym_key.ready = true;
}
/**
* 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;
}
+58 -42
View File
@@ -34,50 +34,75 @@
#include "../ext/hacl-c/Hacl_Curve25519.h"
#include "../ext/hacl-c/Hacl_SHA2_512.h"
#include "../ext/hacl-c/Hacl_Chacha20Poly1305.h"
#include "../ext/hacl-c/kremlib.h"
#define PPRZ_MSG_TYPE_PLAINTEXT 0xaa
#define PPRZ_MSG_TYPE_ENCRYPTED 0x55
// index of encrypted/payload byte
#define PPRZ_GEC_IDX 0
// index of the beginning of the counter
#define PPRZ_CNTR_IDX 1
// index of the beginning of the authenticated bytes
#define PPRZ_AUTH_IDX 5
// index of the beginning of the ciphertex
#define PPRZ_CIPH_IDX 7
// legth of the message signature
#define PPRZ_SIGN_LEN 64
// lenght of a hash for key derivation
#define PPRZ_HASH_LEN 64
// length of the encryption keys
#define PPRZ_KEY_LEN 32
#define PPRZ_NONCE_LEN 12
// length of the authenticated data
#define PPRZ_AUTH_LEN 2
// length of the message authentication tag
#define PPRZ_MAC_LEN 16
// length of the message nonce
#define PPRZ_NONCE_LEN 12
// length of the counter
#define PPRZ_COUNTER_LEN 4
// index of the message ID for plaintext messages
#define PPRZ_PLAINTEXT_MSG_ID_IDX 4
// 4 bytes of MSG info (source_ID, dest_ID, class_byte, msg_ID) + 1 GEC byte
#define PPRZ_PLAINTEXT_MSG_MIN_LEN 5
// 20 bytes crypto overhead + 4 bytes MSG info + 1 GEC byte
#define PPRZ_ENCRYPTED_MSG_MIN_LEN 25
// length of the crypto overhead (4 bytes of counter + 16 bytes of tag)
#define PPRZ_CRYPTO_OVERHEAD 20
// basepoint value for the scalar curve multiplication
#define PPRZ_CURVE_BASEPOINT 9
// minimal size of the encrypted message
#define PPRZ_V2_MSG_ID 3
typedef unsigned char ed25519_signature[64];
struct gec_privkey
{
struct gec_privkey {
uint8_t priv[PPRZ_KEY_LEN];
uint8_t pub[PPRZ_KEY_LEN];
uint8_t pub[PPRZ_KEY_LEN]; bool ready;
};
struct gec_pubkey
{
uint8_t pub[PPRZ_KEY_LEN];
struct gec_pubkey {
uint8_t pub[PPRZ_KEY_LEN]; bool ready;
};
struct gec_sym_key
{
struct gec_sym_key {
uint8_t key[PPRZ_KEY_LEN];
uint8_t nonce[PPRZ_NONCE_LEN];
uint32_t ctr;
uint32_t counter; bool ready;
};
typedef enum
{
typedef enum {
INIT, WAIT_MSG1, WAIT_MSG2, WAIT_MSG3, CRYPTO_OK,
} stage_t;
typedef enum
{
typedef enum {
INITIATOR, RESPONDER, CLIENT, INVALID_PARTY
} party_t;
typedef enum
{
typedef enum {
P_AE, P_BE, SIG,
} gec_sts_msg_type_t;
typedef enum
{
typedef enum {
ERROR_NONE,
// RESPONDER ERRORS
MSG1_TIMEOUT_ERROR,
@@ -92,39 +117,30 @@ typedef enum
MSG3_ENCRYPT_ERROR,
// BOTH PARTIES
UNEXPECTED_MSG_TYPE_ERROR,
UNEXPECTED_STS_STAGE_ERROR,
UNEXPECTED_MSG_ERROR
UNEXPECTED_MSG_DATA_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;
struct gec_sts_ctx {
struct gec_pubkey their_public_key;
struct gec_privkey my_private_key;
struct gec_pubkey their_public_ephemeral;
struct gec_privkey my_private_ephemeral;
struct gec_sym_key rx_sym_key;
struct gec_sym_key tx_sym_key;
stage_t protocol_stage;
party_t party;
sts_error_t last_error;
uint32_t counter_err;
uint32_t rx_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);
void gec_sts_init(struct gec_sts_ctx *sts);
void gec_clear_sts(struct gec_sts_ctx *sts);
void gec_generate_ephemeral_keys(struct gec_privkey *sk);
void gec_derive_key_material(struct gec_sts_ctx *sts, uint8_t *z);
#endif /* SPPRZ_GEC_H */
File diff suppressed because it is too large Load Diff
+40 -3
View File
@@ -39,6 +39,33 @@
#include "mcu_periph/udp.h"
#endif
// TODO: a hack to to allow passing the key exchage messages before
// secure comlink is established
#define KEY_EXCHANGE_MSG_ID_UAV 239
#define KEY_EXCHANGE_MSG_ID_GCS 159
#define WHITELIST_LEN 20
/**
* Whitelist for sending and receiving
* unencrypted messages
* (mostly for KEY_EXCHANGE messages)
*/
struct gec_whitelist {
uint8_t whitelist[WHITELIST_LEN];
uint8_t idx;
bool init;
};
/**
* Auxilliary message buffer for storing
* precomputed key exchange messages
*/
struct message_buffer {
uint8_t msg[TRANSPORT_PAYLOAD_LEN];
uint8_t len;
bool message_ready;
};
struct gec_transport {
// pprz encapsulation layer
struct pprz_transport pprz_tp;
@@ -50,15 +77,16 @@ struct gec_transport {
struct transport_tx trans_tx;
// buffered tx message
uint8_t tx_msg[TRANSPORT_PAYLOAD_LEN];
volatile uint8_t tx_msg_idx;
uint8_t tx_msg_idx;
// ecnryption primitives
struct gec_sts_ctx sts;
struct gec_whitelist whitelist;
PPRZ_MUTEX(mtx_tx); // optional mutex
};
/** PPRZ transport structure */
extern struct gec_transport gec_tp;
@@ -70,7 +98,7 @@ 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);
uint8_t *buf, bool *msg_available);
void gec_process_sts_msg(struct link_device *dev, struct gec_transport *trans, uint8_t *buf);
@@ -78,5 +106,14 @@ void respond_sts(struct link_device *dev, struct gec_transport *trans, uint8_t *
void finish_sts(struct link_device *dev, struct gec_transport *trans, uint8_t *buf);
void gec_add_to_whitelist(struct gec_whitelist *whitelist, uint8_t id);
bool gec_is_in_the_whitelist(struct gec_whitelist *whitelist, uint8_t id);
bool gec_decrypt_message(uint8_t *buf, volatile uint8_t *payload_len);
bool gec_encrypt_message(uint8_t *buf, uint8_t *payload_len);
void gec_counter_to_bytes(uint32_t n, uint8_t *bytes);
uint32_t gec_bytes_to_counter(uint8_t *bytes);
void gec_process_msg1(uint8_t *buf);
bool gec_process_msg3(uint8_t *buf);
#endif /* GEC_DL_H */
@@ -66,6 +66,7 @@ EXTERN bool datalink_enabled;
#endif
/** Convenience macro to fill dl_buffer */
// TODO: replace with a memcpy for efficiency
#define DatalinkFillDlBuffer(_buf, _len) { \
uint16_t _i = 0; \
for (_i = 0; _i < _len; _i++) { \