关键词: TLS protocol, secure microcontrollers, secure companion ICs, embedded security, Transport Layer Security protocol, secure communications
It's more important than ever to protect the sensitive data that is collected and shared between our many smart, connected devices and the cloud. Industrial sensors, home appliances, wearable medical devices, and the like all utilize data that, if in the wrong hands, could lead to severe consequences.
The Transport Layer Security (TLS) protocol, formerly known as Secure Socket Layer (SSL), is the most used protocol for protecting data in transit. While it was initially created for bi-directional secure communications over the internet, between computers and web sites, the TLS protocol is now critical for securing the communication of IoT devices over the internet, preventing eavesdropping or tampering of data in transit. The protocol is considered to be robust since it has been vastly studied, attacked, and fixed and is widely adopted. To ensure that the TLS protocol can be trusted on the device side, secret keys, private keys, and certificates that must never be disclosed or modified must be stored in the devices and used in the course of the execution of the protocol. However, since IoT devices are deployed into the wild, these security assets can be exposed to attackers who might attempt invasive as well as non-invasive attacks. In an invasive attack, a cyber criminal opens the device's enclosure to manipulate its memory content, replace firmware, or probe PCB traces. The non-invasive variety, usually performed through communication ports, targets logical bugs in the device's firmware. Without a secure IC companion, protecting a TLS implementation becomes impossible.
This application note discusses a low-cost, low-complexity solution to secure a TLS implementation in a connected embedded system while also reducing the burden on the devices' application processor.
TLS occurs between a client and a server. In this application note, the "client" is an embedded system (e.g., an IoT device) and the "server" is a remote machine in the cloud, reachable using the internet.i
As such, let's imagine a "client" device with sensors and actuators that is connected to a web service provided by the "server." Based on this scenario, the user can use a smartphone to view sensor data and send commands to the device through the server. The client device uses TLS to report data or fetch commands to/from the server.
There are two main phases for the TLS protocol:
The handshake phase is a negotiation of the secure communication's configuration. The phase includes server and client authentication, as well as computation of a shared secret. The four steps to this phase are as follows:
Once the shared communication secret keys have been exchanged using the above process, a secure communication channel is established; the two communicating parties can start exchanging application-level data (e.g., HTTP request/responses). The TLS protocol layer automatically encrypts and signs packets sent out, and decrypts and verifies received packets on the receiver’s end. The layer does so using secret key-based algorithms such as AES-CBC for the encryption, AES-CMAC for signature, or more recent flavors such as AES-CCM for simultaneous encryption and signature. If incoming messages are corrupt, then the TLS protocol layer returns errors.
After the communication has ended, the shared communication keys, also called session keys, are discarded.
From a software perspective, the TLS protocol can be easily integrated into any application using off-the-shelf software libraries (such as mbedTLS, https://tls.mbed.org). Software integration of such a library seems easy to do. After all, when communicating over the internet using the TCP/IP protocol, applications often use the POSIX socket API's "connect," "read," and "write" functions. To use TLS, the application only needs to redirect those calls to, for example, "mbedtls_ssl_connect," "mbedtls_ssl_read," and "mbedtls_ssl_write" when using the mbedTLS library. The application source code does not need to contain all the odds of implementing the main phases of TLS: "mbedtls_ssl_connect" automatically performs the authentication and key negotiation, and "mbedtls_ssl_read" and "mbedtls_ssl_write" automatically add the TLS protection (encryption and signature) to both the incoming and outgoing application data transfers (e.g. HTTP request/responses).
Figure 1. This diagram provides a rough picture of TLS implementation. More details can be found here: https://tls.mbed.org/kb/how-to/mbedtls-tutorial.
As straightforward as it might seem, integrating a TLS library into applications and their configurations, including configuration on the server, comes with some shortcomings. Even if using a bug-free TLS stack (see https://project-everest.github.io), the integration and use of the TLS library in the software can be flawed (see https://www.mitls.org/pages/attacks).
The following sections of this application note examine the common weaknesses in the TLS integration on the client side, i.e., our embedded device.
One of the first issues seen very often in TLS library usage by applications relates to certificate verification.
It's the application's role to enforce verification of the server certificates, so TLS libraries often don't do this automatically. They have to explicitly request the verification from the TLS library. But without this fundamental verification step, the communication can be exposed to a "man-in-the-middle" attack.
Figure 2. Man-in-the-middle attack.ii
Suppose the network traffic gets diverted to a computer that isn't the intended server. By not verifying the peer certificate, the client establishes a wrongly trustworthy TLS channel with the attacker. When this happens, the TLS protocol becomes useless and, worse, delivers a false impression of security.
TLS failures can stem from the server's configuration. For example, the server can be configured to accept weak cipher suites. Weak cipher suites typically utilize deprecated or broken cryptographic algorithms (such as RC4) that are too weak to resist state-of-the-art attacks. Usually the TLS negotiation phase taps into the strongest protocol configuration, from a security standpoint, supported by both the client and the server. However, if the server supports obsolete cryptographic algorithms, an attacker can downgrade the security of the exchanges between the server and clients, and gain access to the exchanged data. Likewise, some algorithms use forward secrecy, which protects past sessions against future compromises of secret keys or passwords. The cipher suites that use ephemeral Diffie-Hellman (DHE) or the elliptic-curve variant (ECDHE) has perfect forward secrecy-these are the cipher suites servers should implement. There are options that do not have perfect forward secrecy. More details on cipher suites can be found here: https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices.
Effective verification of a server's certificate is integral to resisting man-in-the-middle attacks. A root certificate stored in the embedded system verifies the server's certificate. Typically loaded during embedded device manufacturing, the root certificate belongs to a certification authority, which issued the device and the server certificates and can guarantee their integrity. If this root certificate gets replaced by a rogue one in the device's long-term memory, then the certificate can fall victim to a security breach. When this occurs, an attacker's server can successfully authenticate as a valid server because the rogue server's certificate would be correctly verified by the rogue root certificate that was mischievously loaded into the client device. This scenario also requires some form of a man-in-the-middle attack; however, it isn’t difficult to do.
Session keys are a short-term secret weapon in the security arsenal: their validity lasts as long as the TLS secure communication channel. One set of session keys cannot be used to guess another set of session keys. However, if these keys are leaked, this would still compromise a whole TLS session, whether it is a recorded past session or a currently running session.
The TLS negotiation phase can include a step where the client authenticates to the server. If the client exposes its private key for authenticating to the server, then the client can be impersonated by an attacker who would reuse that key.
If the device's long-term memory was dumped, the exposure of this key can be "immediate." The exposure can also be indirect because the cryptographic algorithms in use, while functionally correct, aren't resistant to side-channel attacks. In a side-channel attack, attackers can guess private or secret keys by measuring timing and/or power consumption and/or electromagnetic emissions of the device when it runs a cryptographic algorithm involving such keys.
There are a set of minimum rules to follow to maintain a truly secure TLS scheme and also to mitigate the pitfalls discussed in this application note:
The TLS handshake phase on the client side involves these long-term assets:
Using a secure IC, such as the MAXQ1061, protects the TLS implementation by preventing the above vulnerabilities by design, without placing any additional burden on the application processor.
A slightly modified TLS stack derived from mbedTLS, provided by Maxim, allows the application processor to leverage the above features of the MAXQ1061, providing an increased level of security without requiring a major redesign. The modified mbedTLS stack leverages the MAXQ1061 for session key exchange, server certificate verification, and client authentication. The secure communication itself can be carried out by the MAXQ1061 itself or by the main application processor.
The above discussion does not preclude any weaknesses on the server side. Needless to say, it's imperative to follow security measures to protect the server private key and chain of certificate.
Securing an embedded system calls for robust software coding and locked system doors (physically and logically). It also pays to not underestimate the attackers.
Storing long-term secrets such as private keys for authentication, or vital data such as certificates, is much safer and easier within a secure IC. The alternative is storing these assets in a common application processor, but these processors typically provide, by design, many debug features that give access to their whole memory content. Another benefit of using a secure IC along with an application processor is that the physical isolation between the two ICs guarantees that a software vulnerability in the application processor won't endanger the assets stored in the secure IC.
i A Primer on Public Key-Based Digital Signature
Consider a scenario where a "sender" wants to transmit a message M to a "receiver," where M is a sequence of bytes. The receiver wants to ensure that the message comes unmodified from the genuine sender.
In the next sequence, consider message exchange between the "sender" and the "receiver." The names of the different items on the receiver's end are postfixed with "_r" (for "received") because they can not be the same as on the sender's end, due to error transmissions or attempts to tamper with the values by an attacker. All the items on the sender's end are postfixed with "_t" (for "transmitted").
Signature and Signature Verification
On the sender's end, a message M_t is prepared for transmission:
On the receiver's end, the triplet (M_r, S_r, SPubk_r) is received (message, signature, public key). In principle, it should be equal to (M_t, S_t, SPubk_t), but due to transmission errors, or voluntary modifications, this might not be the case.
Now the sender wants to verify the signature of the received message M_r.
As SprivK_t_ and SPubk_t are mathematically bound (but knowing SPubk_t does not allow one to find out SPrivK_t), if a signature is found to be correct using SPubk_t, then one knows that the signature was computed using SprivK_t and no other key.
However, the above signature verification is not entirely sufficient. To truly guarantee message authenticity, the public key used to verify the signature (SPubk_r) must be traced back to the sender. Indeed, if an attacker catches the triplet of the genuine sender (M_t, S_t, SPUbk_t) during transit and silently replaces it with another correct but evil triplet (M'_t, S'_t, SPubk'_t) signed using SPrivK' (owned by the attacker itself), then the receiver finds the triplet (M_r, S_r, SPubk_r) = (M'_t, S'_t, SPubk'_t) as authentic and not corrupt because SPubk'_t matches S'_t . However, the message was not sent nor signed by the correct sender!
Certificate Verification, PKI
It's imperative for the receiver to verify that SPubk_r belongs to the expected sender (i.e., SPubk_r = SPubk_t). When there is a single sender, this is quite trivial: it suffices to store SPubk_t on the receiver's end and use the stored version rather than the received version of the public key to verify incoming signed messages. However, in a networked environment, many senders might want to send messages to many receivers. This is led to the advent of public key infrastructures (PKI). In a PKI, public keys are transmitted by senders to receivers within certificates. Certificates are issued by certification authorities. Certificates are data sets that contain the full identity of the sender (usually the domain name of the server, e.g "www.domainname.org", the name, address, country, and phone number of the owning organization), the identity of the certification authority who issued the certificate, and the public key of the sender. The whole certificate is digitally signed by the certification authority (following the same process as in our example above, but with the message M_t replaced by the certificate and the signing private key SPrivk_t being the one owned by the certification authority) and the resulting signature is appended to the certificate.
Now, when a receiver receives (M_r, S_r, Cert_SPUbk_r), he/she first needs to verify that the certificate Cert_SPUbk_r is valid, before using SPUbk_r for verifying the message’s signature. To this end, the receiver uses the certificate of the issuer of Cert_SPUbk_r and proceeds as for verifying an incoming message (the message being Cert_SPUbk_r). A successful verification means that:
When this occurs, it becomes impossible to forge a valid certificate with arbitrary identities and public keys inside, so an attacker cannot impersonate a sender. The certification authority's private key remains secret. But how do we validate the certification authority’s certificate? There can be a few intermediate certificates involved (a chain of certificates), but to put an end to this chicken-and-egg issue, a root certification authority certificate must ultimately be trusted. It means that the verifier must have the root certification authority certificate stored in a safe place beforehand.
iiIn a "man-in-the-middle" attack, an attacker redirects network communications between a client and a server. Then it establishes regular TLS channels with, on the one hand, the client, and, on the other hand, the server. After receiving traffic from the client, it eavesdrops on it or tamper with it before transmitting to the server and vice versa. As a result, the communication channel is no longer secure.
Traffic diversion occurs through switch or router poisoning (routers/switches transfer Ethernet packets to their legitimate recipient according to the Ethernet card MAC address and the IP address), or with DNS hikjacking (DNS is the protocol that resolves server names, e.g. www.mywebsite.com into its IP address).