# Diffie-Hellman over several non-secured HTTP requests - will it work?

This problem is about setting up cryptographic keys on an IoT device. I don't want my devices to be set up with any cryptographic keys pre-baked, but actual communication have to be based on TLS. Now I need a way to inject an SSL certificate and its corresponding private key from the device the user is using. Can this be done by using several HTTP requests to perform a Diffie-Hellman key exchange?

The protocol:

1. The user presses a button on the device, key setup and the unencryted HTTP channel allowed.
2. Client to Server: GET /setup/dh.wib.
3. Server to Client: DH initial parameters, and a new random session cookie.
4. Client to Server: POST /setup/dh.wib with client's computed DH intermediates and session cookie.
5. Server to Client: Server's computed DH intermediates.

Up to this point, a cryptographic key that is suitable for AES encryption should be established. Then:

1. Client to Server: POST /setup/auth.wib with the the device's serial number (as printed on the back of the device) encrypted using the established key, a SHA512-HMAC of the serial number using the key in plain, and the session cookie.
2. Server to Client: HTTP status code 204 if serial number matched with the record stored inside the device, otherwise HTTP status code 401 and the session cookie removed and invalidated.
3. Client to Server: POST /setup/key.wib with the generated certificate, and its corresponding key bundled encrypted using the established key, a SHA512-HMAC of the aforementioned bundle using the key in plain and the valid, authenticated session cookie.
4. Server to Client: If the certificate and key pair worked then HTTP 204, otherwise HTTP 400. Session cookie is invalidated no matter what here. Key setup and unencrypted HTTP access disabled here.
• Counter-proposal: Harden the server's certificate (DANE?) and use standard server-authenticated TLS to sign a certificate associated with a freshly generated private key. Please, please, please: Never actually send a private key over the wire. Let it be generated on your device. Don't roll your own crypto. – SEJPM Dec 9 '15 at 21:07
• @SEJPM This is going against my proposal of not having keys baked in. The device have no onboard quality RNG that can generate good long-term keys with adequate entropy, so no private key generation allowed (but session keys for TLS, being short terms keys, are generally okay as each session lasts a few hundreds of milliseconds) – Maxthon Chan Dec 9 '15 at 21:17
• If you can generate no quality long term keys on-board you won't ever get a secure session. If the DH exchange gets broken (because you used a low entropy DH share) an attacker will be able to get the (transmitted) private key. I guess you'd need to squeeze every bit of entropy out of your RNG so you can at least get a decent private key (100 bits = <14 bytes entropy likely is enough) – SEJPM Dec 9 '15 at 21:23
• @SEJPM 128 or so bits of entropy is way way less than 2500 that is required to generate an RSA key pair. – Maxthon Chan Dec 10 '15 at 5:12
• You don't need 2k+ bits of entropy for an RSA key. Depending on the keylength, you need 128-256 bits of entropy. You can however use these 256 bits to key a stream cipher and use this as your RNG to generate the needed thousands of bits. – SEJPM Dec 10 '15 at 12:16

First, I'd like to say: Don't roll your own crypto.

Your first protocol is basically "your own crypto". The easiest / standard solution to this problem is to use TLS. You can use TLS (with server-authentication only) as a replacement for your first part. I'd recommend though, using DNSSEC / DANE as well (if possible) so you don't have to have a (complex) root-certificate store.

What you do next is up to you. I'll first analyze your proposal and then provide another.

1. If an attacker (within your threat model) can get hands on the serial number he can pretend being that device and thereby may break security guarantees, because the server doesn't know who he's talking to.
2. In your third step you say that "Client to Server" sends the key. I think you meant it the other way around? Note that if you send the private key over the wire, the key is only as secure as the connection (so if you use a "bad" DH private key the key could still be compromised even though it's high entropy).

Otherwise this looks fine and pretty standard.

1. You generate your own private key on the device along with a CSR.
2. You send the CSR to your server along with some "secret" that identifies the device in question and that can not easily be retrieved for attackers in your threat model.
3. The server will create the certificate from the CSR and send it back to the client.
4. The client can now use said certificate for client-authentication.

As for the "how" of the generation of the private key:

You stated that you have a somewhat reliable entropy source on the device.
If you can guess any private key generated on the device there's no chance that you can get a private key securely to the device as the transport key could be broken (because it's weak).
Assuming you can scratch enough entropy together (i.e. 128 bits of entropy distributed over an unspecified amount of bytes) you can run your "random" bytes through a key based key derivation function (e.g. HKDF), to get a key and an IV for the stream cipher of your choice (e.g. AES-CTR or ChaCha20 or Salsa20).
You can now use this stream cipher to generate a pseudo random stream of bytes that you can use as a replacement for your system RNG to get a good private RSA key. Note that 128-bit entropy is good enough for a 3072-bit RSA key as it anyways only provides a 128-bit security margin.

• Does this mean setting up a TLS-capable server inside the smartphone app that is used to configure the gadget? Also no the gadget do not have a good entropy source on-chip (adding an off-chip HWRNG is always an option, but if so what is a good one that can be implemented using either exactly one digital GPIO pin or one I2C device and as little external parts as possible) By the way, a reliable HWRNG renders the entire point of key injecting moot as I can generate a self-signed certificate (and later sign it using a server) easily. – Maxthon Chan Dec 11 '15 at 13:42
• "Does this mean setting up a TLS-capable server inside the smartphone app that is used to configure the gadget?" - yes. This is the more secure (and easier) solution than rolling your own DH exchange. As for the RNG the answer doesn't assume anything else than the comments did, which means that you can somehow scratch 128-bits of entropy together. If you can't the whole question is pointless is there can't be any way to create a secure session w/o a secure RNG or pre-shared keys. – SEJPM Dec 11 '15 at 22:27