From PaparazziUAV
Revision as of 04:24, 16 January 2021 by Ghattenb (talk | contribs) (How to use it)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

PPRZLINK is the communication library used by the Paparazzi UAV project and other related projects.

It provides:

  • Bulleted list item
  • a set of messages definitions
  • various encapsulation protocols
  • several high-level access to physical layers (serial, udp, Ivy)
  • several language support (Ocaml, C, Python)

Source code can be download from Github: https://github.com/paparazzi/pprzlink

The creation of PPRZLINK as a separated project from the main Paparazzi source code is the result of the communication roadmap. At the moment it is released under GPL v2, but it may be changed to LGPL in order to ease integration into third-party projects.

A (not very complete) documentation is also available on the readthedocs platform.

Some useful related project:

Messages' definition

The messages are organized three main classes:

  • telemetry: messages sent by the aircraft, usually to the ground, a.k.a. downlink stream
  • datalink: messages sent by the ground to the aircraft, a.k.a. uplink
  • ground: messages exchanged between ground agents over the Ivy software bus

Pprz communication agents.gif

The generated documentation is available here: http://docs.paparazziuav.org/latest/paparazzi_messages.html

New messages can be integrated mainstream in the messages xml file from PPRZLINK. When using with Paparazzi, it is also possible to use an temporary file placed in the conf folder. If not present, the default set is used.



PPRZLINK is based on encapsulation. The first layer is the message level, mostly containing the data and the required information to decode them. The structure of this part is always the same. The second layer called transport can be changed according to the actual physical layer being used. The basic type (pprz) is just providing synchronization byte and checksum, but other transports offer more possibility of routing like the XBee' transport (especially the possibility to use point-to-point or broadcast).

The message formats are described here. A secured version is currently under development.

Differences between version 1 and 2

A new version (v2) have been developed to overcome several limitations. With version 1, only the message ID (1 byte) and the sender ID (1 byte) are provided in the message layer before the data part. It means that:

  • messages can't be addressed to a particular receiver unless the transport layer can provide the service
  • it is not possible to determine the class of messages, so it is assumed that telemetry messages are strictly downlink and datalink messages strictly uplink, thus preventing direct air-to-air communications

With the version two of the protocol, two extra bytes have been added to the message header:

  • the receiver ID (1 byte)
  • a class ID (4 bits)
  • a component ID (4 bits)

The class and component are part of the same byte. Even if the component ID is not really used at the moment (provision for future use), the class ID avoid ambiguities on messages. With the receiver ID, it is now possible to perform air-to-air communications and to broadcast messages from an aircraft (previously only possible from the ground).

See messages format page for more details.


Currently, the available interfaces are:

  • serial stream
  • udp packet
  • Ivy based messages (publisher/subscriber middelware over TCP/IP, should only be used on the ground side)

In addition a bridge to the ROS middleware is available at https://github.com/enacuavlab/pprzros

Language supports

The supported languages are:

  • C language
    • generation of code (header files) for sending and decoding messages
    • mostly used for the airborne code of Paparazzi
  • Ocaml
    • library based high-level functions for binding, subscribing and parsing messages
    • mostly used by the ground station agents: links, GCS, server, ...
  • Python
    • Provide similar functionality than the Ocaml implemetation
    • used in a large variety of smaller tools and ground agents
  • Rust
    • similar to Python implementation, plus added memory safety
    • used mainly for secure pprzlink (see below)

Secure Ppprzlink

Secure Paparazzi link uses symmetric key encryption with Chacha20 cipher.

s-pprzlink uses a formally verified cryptographic library HACL* developed by the Prosecco team at INRIA Paris in collaboration with Microsoft Research, as part of Project Everest.

Because certain data have to be sent in plaintext (such as the message counter), s-pprzlink uses Authenticated Encryption with Associated Data (AEAD) algorithm to authenticate such data before use. Authentication means that any unauthorized change in data is detected upon decryption. Authentication is important because if we decide to send SENDER_ID or DESTINATION_ID in plaintext - so the receiver can decide whether to decrypt the message - we don't want it to be tampered with. s-pprzlink uses a modified Galois Embedded Crypto algorithm for the symmetric key exchange.

The overhead for encrypted communication is 21 bytes (1 byte signaling crypto/plaintext message, 4 bytes of the counter, 16 bytes of the authentication tag), for plaintext messages (such as key-exchange and some info messages) is only one byte. s-pprzlink works with any STM32-F4 and higher autopilot (it requires a random number generator on chip), and doesn't have any other hardware dependecies (such as FPU etc.).

Encrypted communication should be used anytime there is a potential risk of an adversary listening and modyfing telemetry/datalink messages. While this risk is probably small for short hobby flights with very cheap drones, it might be non-negligible for a large remote sensing mission with expensive (tens of thousands of $) equipment. For sensitive missions, the RC commands should be run over datalink too (choose RC_datalink as your RC module), to close the security gap for RC controlled drones.

We hope that Paparazzi users will find s-pprzlink useful and convenient, and if you have any comments, suggestions or bug reports, please file an issue on github. podhrmic would like to acknowledge Galois for contributed time and experize, Senman for help with implementation and AggieAir for flight testing.

Encryption and Key exchange

Large parts of this text are from Galois Embedded Crypto, please consult there for more details.

GEC key exchange is accomplished by combining the Station-To-Station (STS) protocol with curve25519 for key exchange, ed25519 for authentication, SHA512 with a counter for key derivation, and finally Chacha20Poly1305 for the key confirmation. Assume parties A and B with ed25519 asymmetric key pairs (Pa,Qa) and (Pb,Qb). The protocol proceeds as:

  1. A generates an ephemeral (random) curve25519 key pair (Pae, Qae) and sends Pae.
  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)
  7. A computes the shared secret: z = scalar_multiplication(Qae, Pbe)
  8. A 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.
  9. A decrypts the remainder of the message, verifies the signature.
  10. A computes the ed25519 signature: sig = signQa(Pae || Pbe)
  11. A computes and sends the message Ekey=Ka,IV=Sa||zero(sig)
  12. A returns the values (Kclient,Sclient) to the callee as the resulting key material.
  13. B decrypts the message and verifies the signature. B then returns the tuple (Kclient,Sclient) to the callee as the resulting key material.

The wire-format is unsurprisingly a reproduction of the messages in the above computations:

   message1 = [ Pae (32 bytes) ]
   message2 = [ Pbe (32 bytes) | Encrypted Signature (64 bytes) ]
   message3 = [ Encrypted Signature (64 bytes) ]

The key derivation function is a SHA512 hash of the concatenation of a 16 bit big endian counter, the shared secret 'z', and a one byte party-specific identifier (0 for A, 1 for B and 2 for key material returned to the callee). The requested sizes are all under the output size of SHA512 so the counter is always zero and the return values are the first N bytes of the hash depending on the amount requested.

   kdf(z,partyIdent) = SHA512( 0 || z || partyIdent)

N.B. This key derivation technique is a common one, appearing in NIST SP 800-56A and other standards.


Secure link requires Rust. The recommended way to install Rust on your computer is via rustup.rs. The rest is handled by the paparazzi build system.

How to use it

For start, we recommend using one of the existing configurations. You can then modify your own airfame as needed. Us aggieair_control_panel.xml as your control panel and aggieair_conf.xml as shown below:

Aggieair conf

Choose Atomic airframe. If you are using your own airframe, simply change your telemetry module to telemetry_gec with optional GEC_STATUS_LED indicator (if your autopilot has an extra LED):

      <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"/>

The HACL-C library requires at least 2 kBytes of memory for all the stacks sending messages. If you don't use an RTOS (e.g. ChibiOS), You don't have anything to do. If yes, you need to increase the stack size of the FBW thread by adding to the firmware section (only fixedwing firmware):

      <define name="FBW_THREAD_STACK_SIZE" value="1024*4"/>

You should have enough space already with the threads AP (fixedwing) and MAIN (rotorcraft).

Build and upload your code. Secure link works for NP targets, as well as for regular AP targets. Currently STM32-F4 autopilots are supported (you need a random number generator on chip), in bare metal version (ChibiOS will come later).

NOTE: If you are planning to use HITL and secure link for telemetry at the same time, do not clean before building the target, because then you would remove the generated keys, needed for the key exchange (as described below).

Choose either Secure Simulation (for NPS target) or Secure USB-serial@57600 for regular flight, or Secure HITL USB-serial@57600 for HITL target. If it is your first time running secure datalink, cargo will download and compile rustlink which takes care of the ground part of secure communication. Once it is built, the keys are exchanged and you should see something like this:

Rustlink initiating secure communication

Going OK means the secure connection was established. You should see your regular telemetry, and you can check the connection status in SECURE_LINK_STATUS message:

HITL mission with secure link

NOTE: If either the UAV or rustlink resets, the secure connection is lost and has to be renegotiated. There is currently no mechanism for such, as allowing key renegotiation could introduce a security vulnerability.


The 21 byte overhead at each message is the cost of secure communication. The exact effect on the message bandwidth depends on the length of messages being transmitted. The biggest difference is for short messages (such as PING or SETTING) sent often. On the other hand, larger messages (such as ATTITUDE or GPS) are proportionally less affected.

For example, the following measurements were taken for nominal rotorcraft and fixedwing airframes:

Type Standard downlink Secure downlink Difference
nominal rotocraft 911 bytes/s 1450 bytes/s 1.59x
nominal fixedwing 678 bytes/s 1250 bytes/s 1.84x
fixedwing with sonar 1865 bytes/s 4500 bytes/s 2.4x

For typical configuration the increase in transmitted data is from 1.6 to 1.9, so depending on the channel bandwith the frequency of some messages might have to be adjusted. In the extreme case (such as sending a short SONAR message at high frequency), secure link can increase the amount of transferred data more than 2.5 times.

Chacha20 is a cipher that is fast in software, and is faster than software implementation of AES, but slower than a hardware implementation of AES. Nonetheless, the additional CPU from secure link is negligible (tested on Lisa MX).

Message Format

Secure link is simply a wrapper around pprzlink message. The main difference is an additional CRYPTO BYTE which determines whether the message is encrypted (CRYPTO BYTE=0xaa) or not (CRYPTO BYTE=0x55). If the message is not encrypted, the rest of the message is identical to a standard pprzlink message (SOURCE_ID .. optional MSG Payload) as shown below.

If the message is encrypted, we add 4 bytes of message counter (which is also used as IV for encryption/decryption), and 16 bytes of authentication tag (to authenticate the message before decryption). The counter is transmitted in plaintext and is not authenticated, because if it is tampered with, the decryption will fail. Message routing information (SENDER ID and DESTINATION ID) are transmitted in plaintext so the message can be properly routed in multi-node network, but the data are authenticated - so any change is detected before decryption occurs (thus discarding the whole message). The message structure is shown below (note that Pprzlink 2.0 is the default version for Paparazzi).

S-Pprzlink 1.0

S-Pprzlink v1.0
byte Value Type
0 PPRZ_STX (0x99) Header
1 length N (PPRZ_STX->checksum B) Header
2 crypto byte Crypto byte
3 counter LSB 1 Counter
4 counter LSB 2 Counter
5 counter LSB 3 Counter
6 counter LSB 4 Counter
7 source ID Authenticated data
8 message ID Encrypted payload
9..(N-16) (optional) message payload (0-234 bytes) Encrypted payload
(N-15)..(N-2) tag (16 bytes) Authentication tag
N-1 checksum A Header
N checksum B Header

Pprzlink 1.0 plaintext message
Pprzlink 1.0 encrypted message

S-Pprzlink 2.0

S-Pprzlink v2.0
byte Value Type
0 PPRZ_STX (0x99) Header
1 length N (PPRZ_STX->checksum B) Header
2 crypto byte Crypto byte
3 counter LSB 1 Counter
4 counter LSB 2 Counter
5 counter LSB 3 Counter
6 counter LSB 4 Counter
7 source ID Authenticated data
8 destination ID Authenticated data
9 class component Encrypted payload
10 message ID Encrypted payload
11..(N-16) (optional) message payload (0-234 bytes) Encrypted payload
(N-15)..(N-2) tag (16 bytes) Authentication tag
N-1 checksum A Header
N checksum B Header

Pprzlink 2.0 plaintext message
Pprzlink 2.0 encrypted message

Whitelisting messages


Pprzlink proxy

When using several UAVs using UDP communication (or NPS simulations), the functionalities provided by the server agent is enough as long as there is no direct (air-to-air) communications (using v2 protocol). Otherwise, each UAV have to be accessed based on it's IP address or a specific port when simulating several aircraft on the same computer. The connections between the ground and airborne agents then have to be done through the Pprzlink_proxy tool by associating the aircraft IDs with output and input ports (and eventually an IP address if different from the default value).

Here is a list of usage examples:

./pprzlink_proxy.py --ac=101:4244:4245 --ac=102:4256:4247
./pprzlink_proxy.py --ac=101:4244:4245 --ac=102:4256:4247 --addr=
./pprzlink_proxy.py --ac=101:4244:4245 --ac=102: --gcs=
./pprzlink_proxy.py --script=proxy.txt

where 'proxy.txt' contains a list of parameters with the same format than the command line options (possibly one per line) and

./pprzlink_proxy.py -h

will show the complete list of options.