Good practices for AES key derivation and storage on STM32 - cryptography

I'm developing a device on STM32L4x6. It is connected through BLE to a smartphone and it exchanges encrypted data with it.
Encryption is AES-GCM and I'm using the reference implementation provided by STMicro.
I have implemented a shared secret exchange mechanism using Diffie-Hellman protocol on Curve25519. Right now I am using this shared secret directly as AES key.
However I am confused on 2 points:
I think I have to derive a session key from the shared key however I don't really understand how.
about key storage on STM32, what is the common/best practice ? Is it enough to store the key in Flash and to set the Flash in Read Protected Level 1 ?
Thank you

As for deriving a session key - you may want to look into the topic of Key Derivation Function (KDF). Googling it returns a lot of useful informations related to establishing session keys. You may also ask your question on https://crypto.stackexchange.com/.
As for storing keys in STM32 - it depends what your requirements are. Do the keys need to persist between sessions or can you generate a new one each time a connection is established? Generating a new key each time a new connection is made will be safer due to two reasons:
It's different for each connection so even if someone manages to get the key for a session from the past, it may only be used to decrypt that session.
If you generate a new key for each new session, you don't have the need to store it anywhere such as Flash memory, as you may keep it in RAM only. Powering down the device will wipe the key. Enabling read protection prevents access to RAM as well as to internal Flash.
Regarding 2nd point however - STM32 is NOT considered a "Secure Microcontroller". It lacks hardware elements that prevent hardware attacks - power voltage glitch detection, side-channel prevention, secure mesh etc. With enough resources and determination an attacker will be able to obtain the cryptographic keys that you use, for example by grinding down the chip package and optically reading your data. That touches on the aspect of how secure does the device really have to be - development time cost, hardware security cost. With STM32 all you can do is to make it harder (keep the keys in RAM and only when you need it, then overwrite them with noise) and limit the scope of the attacker (change session keys as often as possible, e.g. each session).

Related

Would there be a compelling reason for implementing integrity check in a file transfer protocol, if the channel uses TLS?

I am developing a client server pair of applications to transfer files by streaming bytes over TCP/IP and the channel would use TLS always.
(Note: Due to certain OS related limitations SFTP or other such secure file transfer protocols cannot be used)
The application level protocol involves minimum but sufficient features to get the file to the other side.
I need to decide if the application level protocol needs to implement an integrity check (Ex: MD5).
Since TLS guarantees integrity, would this be redundant?
The use of TLS can provide you with some confidence that the data has not been changed (intentionally or otherwise) in transit, but not necessarily that the file that you intended to send is identical to the one that you receive.
There are plenty of other opportunities for the file to be corrupted/truncated/modified (such as when it's being read from the disk/database by the sender, or when it's written to disk by the receiver). Implementing your own integrity checking would help protect against those cases.
In terms of how you do the checking, if you're worried about malicious tampering then you should be checking a cryptographic signature (using something like GPG), rather than just a hash of the file. If you're going to use a hash then it's generally recommended to use a more modern algorithm such as a SHA-256 rather than the (legacy) MD5 algorithm - although most of the issues with MD5 won't affect you if you're only concerned about accidental corruption.

Amazon S3 Data integrity MD5 vs SSL/TLS

I'm currently working with the Amazon S3 API, and have a general wondering about the server-side integrity checks that can be done if you provide the MD5 hash during posting of an object.
I'm not sure I understand if the integrity check is required if you send the data (I'm assuming the object data you're posting also) via SSL/TLS, which provide their own support for data integrity in transit.
Should you send the digest regardless if you're posting over SSL/TLS? Isn't it superfluous to do so? Or is there something I'm missing?
Thanks.
Integrity checking provided by TLS provides no guarantees about what happens going into the TLS wrapper at the sender side, or coming out of it and being written to disk at the receiver.
So, no, it is not entirely superfluous because TLS is not completely end-to-end -- the unencrypted data is still processed, however little, on both ends of the connection... and any hardware or software that touches the unencrypted bits can malfunction and mangle them.
S3 gives you an integrity checking mechanism -- two, if you use both Content-MD5 and x-amz-content-sha256 -- and it seems unthinkable to try to justify bypassing them.

Two-way encryption/authentication between servers and clients

To be honest I don't know if this is the appropriate title since I am completely new to this area, but I will try my best to explain below.
The scenario can be modeled as a group of functionally identical servers and a group of functionally identical clients. Assume each client knows the endpoints of all the servers (possibly from a broker or some kind of name service), and randomly chooses one to talk to.
Problem 1: The client and the server first need to authenticate themselves to each other (i.e. the client must show the server that it's a valid client, vice versa).
Problem 2: After that, the client and server talk to each other over some kind of encryption.
For Problem 1, I don't know what's the best solution. For Problem 2, I'm thinking about letting each clients create a private key and give the corresponding public key to the server it talks to right after authentication, so that no one else can decrypt its messages; and let all servers share a private key and distribute the corresponding public key to all clients, so that the external world (including the clients) can't decrypt what the clients send to the servers.
These are probably very naive approaches though, so I'd really appreciate any help & thoughts on the problems. Thank you.
I asked a similar question about half a year ago here, I've been redirected to Information Security.
After reading through my answer and rethinking your question, if you still have questions that are so broad, I suggest to ask there. StackOverflow, from what I know, is more about programming (thus security in programming) than security concepts. Either way, you will probably have to migrate there at some point when doing your project.
To begin with, you need to seriously consider what needs protecting in your system. Like here (check Gilles' comment and others), one of the first and most important things to do is to think over what security measures you have to take. You just mentioned authentication and encryption, but there are many more things that are important, like data integrity. Check wiki page for security measures. After knowing more about these, you can choose what (if any) encryption algorithms, hashing functions and others you need.
For example, forgetting about data integrity is forgetting about hashing, which is the most popular security measure I encounter on SO. By applying encryption, you 'merely' can expect no one else to be able to read the message. But you cannot be sure if it reaches the destination unchanged (if anything), either because of interceptors or signal losses. I assume you need to be sure.
A typical architecture I am aware of, assumes asymmetric encryption for private key exchange and then communicating using private keys. This is because public-key infrastructure (PKI) assumes that the key of one of the sides is publicly known, making communication easier, but certainly slower (e.g. due to key length: RSA [asymmetric] starts with 512bits, but typical key length now is 2048, which I can compare to weakest, but still secure AES [symmetric], which key lengths start with 128bits). The problem is, as you stated, the server and user are not authenticated to each other, so the server does not really know if the person sending the data really is who they claim they are. Also, the data could have been changed during traffic.
To prevent that, you need a so called 'key exchange algorithm', such as one of the Diffie Hellman schemes (so, DH might be the 'raw' answer to both of your problems).
Taking all above into consideration, you might want to use one (or more) of the popular protocols and/or services to define your architecture. Popular ones are SSH, SSL/TLS and IPSec. Read about them, define what services you need, check if they are present in one of the services above and you are willing to use the service. If not, you can always design your own using raw crypto algorithms and digests (hashes).

Securing a UDP connection

For a personal MMO game project I am implementing a homebrew reliable UDP-based protocol in java. Given my current setup I beleive it would be relatively simple for a snooper to hijack a session, so in order to prevent this I am taking the opportunity to learn a little cryptology. Its very interesting.
I can successfully create a shared secret key between the client and server using a Diffie-Hellman key exchange (a very clever concept), but now I need to use this to guarantee the authenticity of the packets. My preliminary testing so far has shown that the couple of different ciphers Ive tried bloat the amount of data a bit, but I would like to keep things as small and fast as possible.
Given that I am only trying to authenticate the packet and not nessecarily conceal the entire payload, I have the idea that I could put an 8 byte session ID generated from the secret key into the packet header, encrypt the whole packet, and hash it back down to 8 bytes. I take the unencrypted packet and put the 8 byte hash into the place of the session ID and then send it off.
Would this be secure? It feels a little inelegant to encrypt the whole packet only to send it unencrypted - is there a better/faster way to achieve my goal? Please note I would like to do this myself since its good experience so Im not so interested in 3rd party libraries or other protocol options.
If both peers have access to a shared secret (which they should, since you're talking about Diffie-Hellman), you could simply store a hash of the datagram in its header. The receiver checks to see if it matches.
As an added security measure, you could also add a "challenge" field to your datagram and use it somewhere in the hashing process to prevent replays.
So this hash should cover:
The shared secret
A challenge
The contents of the datagram
EDIT
The "challenge" is a strictly incrementing number. You add it to your datagram simply to change the hash every time you send a new message. If someone intercepts a message, it cannot resend it: the receiver makes sure it doesn't accept it.

How much security is required for message storage and transmission?

I need to implement a very secured Web Service using WCF. I have read a lot of documents about security in WCF concerning authorization, authentication, message encryption. The web service will use https, Windows Authentication for access to the WS, SQL Server Membership/Role Provider for user authentication and authorization on WS operations and finally message encryption.
I read in one of documents that it is good to consider security on each layer indenpendently, i.e. Transport Layer security must be thought without considering Message Layer. Therefore, using SSL through https in combination with message encryption (using public/private key encryption and signature) would be a good practice, since https concerns Transport Layer and message encryption concerns Message Layer.
But a friend told me that [https + message encryption] is too much; https is sufficient.
What do you think?
Thanks.
If you have SSL then you still need to encrypt your messages if you don't really trust the server which stores them (it could have its files stolen), so this is all good practice.
There comes a point where you have a weakest link problem.
What is your weakest link?
Example: I spend $100,000,000 defending an airport from terrorists, so they go after a train station instead. Money and effort both wasted.
Ask yourself what the threat model is and design your security for that. TLS is a bare minimum for any Internet-based communications, but it doesn't matter if somebody can install a keystroke logger.
As you certainly understand, the role of Transport-Level Security is to secure the transmission of the message, whereas Message-Level Security is about securing the message itself.
It all depends on the attack vectors (or more generally the purpose) you're considering.
In both cases, the security models involved can have to purposes: protection against eavesdropping (relying on encryption) and integrity protection (ultimately relying on signatures, since based on public-key cryptography in most cases).
TLS with server-certificate only will provide you with the security of the transport, and the client will know that the communication really comes from the server it expects (if configured properly, of course). In addition, if you use client-certificate, this will also guarantee the server that the communication comes from a client that has the private key for this client certificate.
However, when the data is no longer in transit, you rely on the security of the machine where it's used and stored. You might no longer be able to assert with certainty where the data came from, for example.
Message-level security doesn't rely on how the communication was made. Message-level signature allows you to know where the messages came from at a later date, independently of how they've been transferred. This can be useful for audit purposes. Message-level encryption would also reduce the risks of someone getting hold of the data if it's stored somewhere where some data could be taken (e.g. some intranet storage systems).
Basically, if the private key used to decrypt the messages has the same protection as the private key used for SSL authentication, and if the messages are not stored for longer time than the connection, in that case it is certainly overkill.
OTOH, if you've got different servers, or if the key is stored e.g. using hardware security of sorts, or is only made available by user input, then it is good advice to secure the messages themselves as well. Application level security also makes sense for auditing purposes and against configuration mistakes, although personally I think signing the data (integrity protection) is more important in this respect.
Of course, the question can also become: if you're already using a web-service that uses SOAP/WSDL, why not use XML encrypt/sign? It's not that hard to configure. Note that it does certainly take more processor time and memory. Oh, one warning: don't even try it if the other side does not know what they are doing - you'll spend ages explaining it and even then you run into trouble if you want to change a single parameter later on.
Final hint: use standards and standardized software or you'll certainly run into crap. Spend some time getting getting to know how things work, and make sure you don't accept ill formatted messages when you call verify (e.g. XML signing the wrong node or accepting MD5 and such things).