Hacker News new | ask | show | jobs
by suf 3004 days ago
Hey, can you share some crypto advice for limited embedded systems (let's say minimum being 32bit cortex-M0). Say for firmware updates, user data uploading, etc.
3 comments

Use Monocypher, TweetNaCl, or Libsodium.

Monocypher is portable (C99/C++), pretty fast, and has low memory footprint (generated binary between 30kB and 60kB). Problem: it isn't trusted yet. (I'd like to run a bug bounty, but I'm not sure how I should go about it.)

TweetNaCl is portable (C89), has low memory footprint, and is made by trustworthy professional cryptographers. Problem: it is slow.

Libsodium is blazing fast on modern processors, has portable implementations, and is trusted. Problem: it is pretty big, and I hate the auto tools.

Edit: of course, those recommendations only hold if you have a trustworthy RNG.

What could be used with a small/medium sized microcontroller, something like 64 kB total flash budget and 4-20 kB RAM?

IOW, Cortex M0 territory.

Small IoT is about this size, so I think many will be interested in some answers... any answers.

Say, for securely transmitting sensor data to an x86 server (or similar) without hardcoding symmetric keys on the devices.

Take Monocypher or TweetNaCL, and rip off any primitive you don't need. This may be enough. Even when you take the whole thing, Monocypher only needs 30kb of x86-64 machine code when compiled with -Os. If you only keep authenticated encryption and x25519, which are enough for many uses, I think you should be able to halve that down to 15kb or less.

If speed doesn't matter, TweetNaCl is even smaller.

If those aren't enough still, you may want to dive in, learn a ton about crypto (starting with https://www.crypto101.io/), and investigate the sponge construction, whose versatility may allow you to shrink the code even more. Perhaps. I'm in over my head at this point.

avr has aes extensions, surely arm cortex-m has similar. are those any good, are they used by the libs you mention?
Neither of those libraries uses any extensions. TweetNaCl is a famously minimal implementation of NaCl in portable C by the NaCl authors. Monocypher is a library 'loup-vaillant wrote as a sort of side project. TweetNaCl does see some use, but libsodium is the most popular NaCl implementation, and libsodium's author provides his own low-footprint misuse-resistant crypto API separately.

Neither TweetNaCl nor 'loup-vaillant's library really addresses the low-footprint concern.

If they have hardware AES support, forget everything I said. Monocypher and TweetNacl are portable C, they don't use extensions of any kind.
When you're that small it really requires more context. What are you trying to do?

I've deployed TLS in 50 KiB flash and 6 Kb RAM. But I could rely on hardware support for some public key operations and could pick a single ciphersuite, and controlled the server end as well.

The boring answer is that you'll need to identify the set of primitives you need and then find a library that matches. I can't think of any single primitive that would break that budget, so it'll depend on how many you need!

You need to provide more info.

  1. How much of your flash budget is eaten up by the application?

  2. What performance do you need for different use cases and operations?
Generally, RAM is often the least of your problems. And if you are into Cortex M0 or even M0+ territory, your MCU will quite probably sport an AES-128 core. Even if it is slow you should try and use that.
libhydrogen might be an option.
Got an opinion on BearSSL?
I can't be sure, but I think he thinks you should use his thing.
I'm not yet to the point where I can recommend my thing without even mentioning the other two competitors. I did get bloody thorough, though, and I do think it is good enough for me to bet my job. (Meaning, I'd be willing to lose my job if my employer uses Monocypher on my watch, and data gets leaked because of that choice.)

(As for the original question, I don't know BearSSL enough to have an opinion. It does seem however to get even further than Monocypher on the constant time thing. Monocypher needs the platform to provide constant time 64-bit multiplication. Most do, but not all.)

> (Meaning, I'd be willing to lose my job if my employer uses Monocypher on my watch, and data gets leaked because of that choice.)

Would you be willing to be personally liable for that data leak?

(Put aside the philosophical question of whether or not it's reasonably for developers to be personally liable for their software failures - I'm interested in how far your confidence in your cryptography goes).

Disclaimer: I'm not 'tptacek but I'm one of the Latacora principals and co-edited this document.

Embedded crypto gets weird fast. General recommendations are a little tricky, but: is that device talking to the internet directly or some kind of IoT hub or whatever?

Let's say talking directly to the internet.
If it's on the raspi side of powerful, just use OpenSSL, or maybe Go's TLS stack, again, assuming you can get away with it.

On smaller systems, things get weird. If you can't afford go/openssl, there aren't a lot of things I'm very confident in. BearSSL near the top of the list. That's still double-digits kilobytes of RAM though, so maybe I just ate all your budget. You might be in one of the cases where a NOISE protocol instance is in fact the right answer; depends a little on what else the box is doing and how frequently.

Sorry, I get that it's not a satisfying answer :-) It's complicated!

What's wrong with PolarSSL/Mbed TLS? It is designed for low-end ARM processors and is directly backed by ARM.
Their history of implementation issues leads me to believe that the general upside of TLS doesn’t necessarily weigh up to the upside (and cost!) of a light bespoke implementation. That’s contingent on having someone around who won’t mess this up; failing that, an embedded TLS stack is still a good idea.

I would have told you something differently before NOISE and NaCl, particularly Curve25519. We could have done AESCTRHMACSHA256 a long time ago and be basically a good as XSalsa20-Poly1305, but Curve25519 was a huge leap compared to the DH2048 you were likely to do before.

I don't think you can deem mbedTLS too risky on one hand, and then on the other recommend Noise, with it's slew of unfinished and largely unverified libraries. Outside of the WireGuard RHUL effort for a specific 'pattern' AFAIK the Noise core hasn't really seen any formal analysis either. Commoditizing the DH operation means you can build an enormous amount of AKEs, and even people like Trevor Perrin can make mistakes there.

Noise is potentially very interesting, particularly for the embedded space, but it'll be a while before it's safe to use.

SSL/TLS isn't very well suited for cheap embedded devices. It seems like you have to chew up almost 64K of RAM to make a compliant stack.

mbed TLS also doesn't seem to be particularly well vetted and has had a number of compromises due to implementation issues.

Thanks, yeah embedded systems are always an exception that makes for strange design.
Yeah. Unfortunately this cuts both ways: I've also heard "you don't understand, we are on an embedded platform" when they mean "we're on a raspi".
Advice for that kind of problem typically requires a lot more context, e.g.: * You need to do symmetric crypto between two MCUs, where only one has an RNG; * You need to do symmetric crypto with no RNG; * You can't rely on your MCU safely storing state / unreliable transports.

Cryptography and libraries/standards are gradually building towards a world in which higher-and-higher level abstractions let inexperienced web/high-level application developers build safe systems. The same isn't really true for the lower-end of the embedded space, and consequently you can't really produce an equivalent set of (reasonable) guidelines like the ones linked.