Cifra is a collection of cryptographic primitives targeted at embedded use.
In order of descending emphasis, cifra aims for:
- Clarity and simplicity.
- Countermeasures for side channel leaks inherent in some algorithms.
- Suitability for embedded use. Particularly: cifra uses an absolute minimum of the standard C library and is reasonably efficient with respect to code and data space.
- AES in the GCM, CCM and EAX authenticated encryption modes.
- NORX authenticated encryption system.
- SHA224, SHA256, SHA384 and SHA512 hash functions (including HMAC and PBKDF2).
- SHA3-224, SHA3-256, SHA3-384, SHA3-512 hash functions (FIPS 202 compatible).
- ChaCha20 and Salsa20 stream ciphers.
- Poly1305 one time MAC.
- 100% code coverage by line, zero static analysis defects, valgrind-clean.
Additionally cifra imports curve25519 from elsewhere (μNaCl, NaCl, tweetNaCl, Adam Langley's curve25519-donna) for comparison between various implementations on embedded targets.
Available at Read the Docs.
There is quite a lot of testing available:
- Host builds: run
make test
in thesrc
directory. This builds and runs assorted test programs. - Emulated embedded builds: run
make test
in thesrc/arm
directory. This expects to findqemu-system-gnuarmeclipse
on the path. These tests assume a Cortex-M3 target. - Cortex-M0 on-target tests: run
make test.stm32f0
in thesrc/arm
directory. This expects to findopenocd
on the path, with an STM32F0xx attached via stlinkv2. It uses ARM semihosting to report results. - Cortex-M3/4 on-target tests: run
make test.stm32f1
ormake test.stm32f3
as above.
Additionally all embedded targets expect to find the arm-none-eabi
toolchain
to be on the path.
All measurements performed at -Os
(optimise for space), on the following MCUs:
Core | Part number | Price (1s) | Max clock | Flash | SRAM |
---|---|---|---|---|---|
Cortex-M0 | STM32F030F4P6 | 1.17EUR | 48MHz | 16KB | 4KB |
Cortex-M3 | STM32F103C8T6 | 2.87EUR | 72MHz | 64KB | 20KB |
Cortex-M4F | STM32F303K6T6 | 4.53EUR | 72MHz | 32KB | 12KB |
More measurements are available for AEAD modes on my blog post: Benchmarking Modern Authenticated Encryption on €1 devices.
This test does a key schedule, then encrypts one block.
Core | Cycles (key schedule + block) | Cycles (key schedule) | Cycles (block) | Stack | Code size |
---|---|---|---|---|---|
Cortex-M0 | 7156 | 2147 | 5009 | 312B | 1020B |
Cortex-M3 | 4692 | 1591 | 3101 | 300B | 960B |
Cortex-M4F | 4591 | 1571 | 3020 | 300B | 960B |
Core | Cycles (key schedule + block) | Cycles (key schedule) | Cycles (block) | Stack | Code size |
---|---|---|---|---|---|
Cortex-M0 | 10611 | 3650 | 6961 | 396B | 1100B |
Cortex-M3 | 6735 | 2450 | 4285 | 380B | 1048B |
Cortex-M4F | 6588 | 2416 | 4172 | 380B | 1048B |
This test encrypts and authenticates a 16 byte message, with 16 bytes additionally authenticated data. It includes the initial key schedule.
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 57022 | 796B | 2600B |
Cortex-M3 | 44306 | 812B | 2644B |
Cortex-M4F | 43657 | 812B | 2644B |
This test encrypts and authenticates a 16 byte message, with 16 bytes additionally authenticated data. It includes the initial key schedule.
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 50564 | 932B | 2836B |
Cortex-M3 | 32855 | 932B | 2780B |
Cortex-M4F | 32159 | 932B | 2780B |
This test encrypts and authenticates a 16 byte message, with 16 bytes additionally authenticated data. It includes the initial key schedule.
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 37677 | 772B | 2280B |
Cortex-M3 | 24462 | 780B | 2256B |
Cortex-M4F | 23949 | 780B | 2256B |
This test encrypts and authenticates a 16 byte message, with 16 bytes additionally authenticated data.
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 10692 | 320B | 1636B |
Cortex-M3 | 6909 | 320B | 1820B |
Cortex-M4F | 6855 | 320B | 1820B |
This test encrypts a 64 byte message.
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 5981 | 564B | 1416B |
Cortex-M3 | 3487 | 544B | 1328B |
Cortex-M4F | 3468 | 544B | 1328B |
(For comparison with AES, add an AES256 key schedule plus 4 blocks. That's about 33K cycles.)
This test encrypts a 64 byte message.
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 6173 | 560B | 1412B |
Cortex-M3 | 3320 | 552B | 1272B |
Cortex-M4F | 3311 | 552B | 1272B |
This test hashes the empty string (one compression function invocation). 8000
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 11561 | 312B | 1760B |
Cortex-M3 | 6530 | 300B | 1708B |
Cortex-M4F | 6278 | 300B | 1708B |
This test hashes the empty string (one compression function invocation).
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 38447 | 796B | 2888B |
Cortex-M3 | 28771 | 836B | 2988B |
Cortex-M4F | 28777 | 836B | 2980B |
This test hashes the empty string (one sponge permutation).
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 93648 | 848B | 2212B |
Cortex-M3 | 74321 | 856B | 2164B |
Cortex-M4F | 72215 | 856B | 2140B |
This test hashes the empty string (one sponge permutation).
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 92565 | 880B | 2212B |
Cortex-M3 | 73509 | 888B | 2164B |
Cortex-M4F | 71419 | 888B | 2140B |
This test computes a MAC with a 32 byte key over the message "hello world".
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 48924 | 1328B | 2200B |
Cortex-M3 | 28333 | 1324B | 2132B |
Cortex-M4F | 27337 | 1324B | 2132B |
This test computes a MAC with a 32 byte key over the message "hello world". It includes the AES nonce processing.
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 15719 | 704B | 1920B |
Cortex-M3 | 11328 | 696B | 1964B |
Cortex-M4F | 10706 | 696B | 1932B |
This test is one point multiplication.
This uses the implementation from μNaCl by Düll, Haase, Hinterwälder, Hutter, Paar, Sánchez and Schwabe.
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 4070271 | 464B | 5596B |
Cortex-M3 | 3720363 | 448B | 5536B |
Cortex-M4F | 3720105 | 448B | 5536B |
See curve25519-shootout for comparitive measurements for other curve25519 implementations.
Cifra requires memcpy
, memset
, and abort
.
Keccak hash function (aka SHA3).Poly1305 one-time MAC.- Constant time curve25519 for Cortex-M4F using the FPU.
- Constant time curve25519 for Cortex-M3 (avoiding the variable-time multiplier).
- Issue #2: in all versions before commit
d62aa26e
(September 16th 2015) too much padding was added when hashing messages of certain
lengths. Specifically, messages whose length satisfied
len % 64 = 55
for SHA1/SHA224/SHA256 orlen % 128 = 119
for SHA384/SHA512. SHA3 was not affected. Better testing is now in place.
CC0.
Please attribute the author. This is a request only, and not a license term.
Joseph Birr-Pixton jpixton@gmail.com