I am reviewing the security of an embedded system, specifically how it uses the TLS or DTLS protocol to communicate securely. The system implements as few features of the protocol as it can get away with. It doesn't deviate from the protocol as such, but it may not always be strictly compliant with all applicable RFC. My objective is to determine whether the choice of security parameters are safe.

I will have to do this again for other similar systems, hence my question is somewhat general rather than being about a specific system.

The security objectives of using (D)TLS are the usual one: an attacker could intercept network traffic (active man-in-the-middle). We want to ensure that the client is talking to the server it thinks it's talking to and that a third party cannot obtain or modify transmitted data (confidentiality and integrity of traffic on the connection). Client authentication is sometimes desired as well.

These are embedded (IoT) systems with very few resources, and usually interacting in controlled ecosystems. At least, we control the legitimate peers, so compatibility with diverse antique clients and servers is not an issue — the concerns are very different from using TLS on the web. A typical endpoint client only speaks one or two ciphersuites (“classic” signature-based server authentication, pre-shared key, or one of each). Depending on the scenario, the PKI may or may not be a closed system: some devices live in a world where we can trust CAs to only deliver certificates of a certain form, while others may trust a “public web” CA.

These are devices with stringent constraints on available computing power, RAM size and code size. So they're generally running stripped down TLS libraries with as few features as possible. I'm talking microcontroller with 128–512kB of RAM, not higher-end devices running Linux.

Are there (D)TLS or X.509 extensions that are important? I'm not concerned with the choice of ciphersuites (nobody uses DES, RC4 or MD5 in my world, or ciphersuites without server authentication) or with key sizes. What I'm worried about is, for example, an implementation that skips checks on certificates (e.g. key usage restriction) which would allow a certificate to be misused. Or a missing check during the handshake that allow some kind of downgrade attack (an endpoint device usually only speaks a single protocol version, but the servers it talks to may support multiple versions). Or a missing extension that allows an active MitM to convince the two parties to settle on mismatched security parameters, or to renegotiate insecurely.

What should I be looking for when reviewing the TLS configuration on a small embedded device?

  • BearTLS might be considered the smallest possible valid implementation as a point of comparison. (and I hear that it is well documented)
    – schroeder
    Aug 9, 2017 at 22:23
  • You mean this bearssl.org ? Wow, written by our own @ThomasPornin. I had no idea that existed. Since I recently completed a security review of it, I feel obliged to mention WolfSSL which is FIPS-140, but BearSSL is probably a better comparison of what's strictly necessary. Aug 9, 2017 at 23:25
  • Default build for BearSSL is ~680k, and doesn't appear to be as customizable as mbedTLS (I could be missing a build option somewhere...). The default build for mbedTLS is ~760k. I've configured it for an embedded device to support only a few ciphersuites. Even with the x509 libraries I got it down to 330k.
    – RoraΖ
    Aug 10, 2017 at 16:02
  • Interesting. For comparison, I've seen wolfSSL build to 50k and I think the sales team claims it can be pared down to 35k (no idea how much functionality was removed though). Aug 10, 2017 at 16:25

1 Answer 1


It's unclear whether you're only looking at the TLS client, or whether you're reviewing both client and server implementation. I'll assume both.

I recently completed a security review of WolfSSL (which comes with a recommendation by the way), and various proprietary TLS stuff, so this is fresh on my mind. Here is a thoroughly incomplete list of things I look for:

X.509 Stuff

  • Make sure the client is checking that the CN of the DN matches the domain of the URL it requested.
  • Use your judgement that cert validation makes sense in the closed-system context. You may need to make some lists of what the possible use-cases are, given the constrained environment, and make sure they're met. Also do some head-scratching that the absence of checks for the use-cases you're leaving out can't be abused.
  • Can certificates get revoked in this environment? If so, what mechanism? CRL? OCSP? There could be additional extensions you need to support here.
    • How does the client behave if it can't retrieve revocation data? Is that reasonable given the use-case?
  • Are there intermediate CAs, or are all certs issued directly by the pinned root?
    • Is root cert pinning / trust management being done in an intelligent way?
    • If intermediates, do those expect you to fetch data from the AIA extension? (if there are "public web CAs" involved, then this is almost certainly a Yes).
    • If intermediates, then you probably need to enforce basicConstraints for path length and cA to make sure jokers aren't issuing certs off an end-entity cert.

TLS Stuff

  • State machine: all the SMACK-TLS related vulns (SKIP, FREAK) are caused by the attacker abusing TLS engine's state machine, so make sure it's enforcing from each state, what the valid possible next states are. More scrutiny on the server, but relevant to both.
  • Cipher Suites: check client configuration, and check that server combines the client's preference order with its own in some intelligent way. (btw TLS 1.3 has some changes here, so if you need to support that, beware.)
  • The usual array of buffer size handling, pointer nullity, and memory-management checks. Bad things usually show up near the socket recv calls.

I could go on, but I may need to ask for compensation :P


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .