I’m seeking comments/feedback/suggestions for the protection of sensitive information on the vehicle module for OVMS v3.

Firstly, here is the background document from Espressif regarding native ESP-32 flash encryption facilities, along with a short summary:

http://esp-idf.readthedocs.io/en/latest/security/flash-encryption.html


Once the flash is encrypted, it is secure from tampering. But, you can always just upload another program to it (via OTA, or serial flash) and run that. Then, that program has full access to the decrypted flash. To get around that vulnerability, Secure Boot should always be used in combination with flash encryption:

http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html


Bottom line is that if an attacker has physical access to the device, then only a combination of flash encryption and secure boot can protect the contents of the flash. At that point, a microscope and chip etching is needed.

However, that is completely incompatible with open source development. Only the manufacturer (us, Open Vehicles, in this case) can sign programs to be loaded onto the device. It is also a PITA for developers (due to the limit of 3 flashes for factory/developer serially flashed images).

Our requirement is to protect sensitive information on the device. Things like wifi passwords, etc. The ESP32 provides us the flash encryption + secure boot option, as well as various storage areas we can take advantage of (RAM, NVM key-value store in flash, SPIFFS file system, eFuses). Assuming we aren’t going to use flash encryption + secure boot, and assuming we can compromise to limited protection from those with physical access to the device, what can we do?

I have created a stub config API:

void RegisterParam(std::string name, std::string title, bool writable=true, bool readable=true);
void DeregisterParam(std::string name);
void SetParamValue(std::string param, std::string instance, std::string value);
std::string GetParamValue(std::string param, std::string instance);

The config store is based on Param+Instance=Value. So, for example, we can have a parameter for wifi parameters, an instance of the wifi SSID, and the value being the password, etc. Each param can also be tagged as writable and/or readable by the end-user (the system itself must of course have full read/write access).

The question is how to implement that store in as secure a way as possible? OVMS v2 provided no protection - a serial console directly connected had access to everything.

One compromise suggestion I have is:


If we did that, someone with physical access to the device could either (a) upload their own code to read and print the configs, or (b) extract the flash contents, find the NVM key, and decrypt stuff themselves. Pretty much no protection for an educated smart hacker with time. We’re open source so this is trivial.

Protection against remote access to these protected configs would be better. So long as our command processor is not exploitable, or there is some other unknown remote exploit affecting us, we’re pretty secure.

Note that a suggested variant of this would be to store the key externally to the device and to have to enter it manually whenever the device is powered on (but before network access). Storing the key in ram would make it slightly more secure to external access, but would be more troublesome for the end-user to have to get a laptop out to plug it in and enter the key.

One other comment is that even if WE don’t enable flash encryption and secure boot, there is nothing stopping an educated end-user doing that. He would need to arrange to sign his own updates (and not use ours).

Thoughts? Suggestions?

Regards, Mark.