Awesome
Cifra
Cifra is a collection of cryptographic primitives targeted at embedded use.
Aims
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.
Features
- AES in the GCM, CCM, EAX and OCB3 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.
Documentation
Available at Read the Docs.
Testing
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.
Measurements
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.
AES
This test does a key schedule, then encrypts one block.
128-bit key
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 |
256-bit key
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 |
AES128-GCM
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 |
AES128-EAX
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 |
AES128-CCM
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 |
NORX32
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 |
ChaCha20
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.)
Salsa20
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 |
SHA256
This test hashes the empty string (one compression function invocation).
Core | Cycles | Stack | Code size |
---|---|---|---|
Cortex-M0 | 11561 | 312B | 1760B |
Cortex-M3 | 6530 | 300B | 1708B |
Cortex-M4F | 6278 | 300B | 1708B |
SHA512
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 |
SHA3-256
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 |
SHA3-512
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 |
HMAC-SHA256
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 |
Poly1305-AES
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 |
Curve25519
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.
C library requirements
Cifra requires memcpy
, memset
, and abort
.
Future
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).
Notable past bugs/advisories
- 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. - Issue #3: in all versions before commit 82d77cd8 (April 16th 2016) EAX would produce wrong tags for empty AADs or messages. The underlying CMAC is now more resistant to this case.
- Issue #6: in all versions before commit b6cdf9f3 the chacha20poly1305 construction would produce incorrect tags for some message or AAD lengths. These case weren't covered by the standard test vectors, so extra tests have been added computed with libsodium.
- Issue #11: in all versions before commit df1e4130 our salsa20 used incorrect internal ordering when constructing the nonce. The correct ordering is apparently not specified by the specification or covered by test vectors. Additional tests have been generated from libsodium.
License
CC0.
Please attribute the author. This is a request only, and not a license term.
Author
Joseph Birr-Pixton jpixton@gmail.com