Thanks for the feedback! On Tue, Aug 21, 2018 at 1:03 AM, Jan Lübbe wrote: > On Mon, 2018-08-20 at 11:39 -0700, Evan Edstrom wrote: >> I am using RAUC for a commercial product, and one of the things we >> need to accomplish is to encrypt our update bundles. I've manually >> created an encrypted rauc bundle using a LUKS container. Once the >> container is opened it can be mounted like normal as a squashfs >> partition and used by RAUC. > > A normal RAUC bundle looks (mostly) like this: > [ squashfs ][ CMS signature over hash of squashfs ] > > I expect that your LUKS container wraps both: > [ LUKS header ][ LUKS encrpytion ( RAUC bundle ) ] > > So you get symmetric encryption of whole bundle with a password (i.e. a > shared secret), right?
Yes, I was using a keyfile with 1024 bytes of /dev/random to test with. > While this setup is pretty straight forward, I see some downsides: > - RAUC cannot read any information about the bundle before decryption > - With a single shared secret, there is no way to revoke a compromised > key (for example extracted from a single device in the field) >> * Option 1: >> Provide an optional "decryption handler"... If the config file defines >> this handler, the update process would essentially run the handler >> instead of r_mount_loop() in bundle.c. > r_mount_loop() only runs after reading and verifying the bundle > signature, so it would need a different layout than the one above. > Something like: > [ LUKS header ][ LUKS encrpytion ( squashfs ) ] CMS signature over hash > of LUKS header+encrypted data ] Exactly what I was picturing. Filling the container, closing it, then signing using the existing method so RAUC could verify the signature before attempting to decrypt in the same way it currently would. >> This gives a user the most flexibility as they're not locked into any >> particular encryption method or even bundle format. Bundle creation gets >> a little more tricky as there isn't a concept of handlers built in. Could >> have >> an optional argument which provides a mounted and empty bundle. > > A squashfs is generated by using mksquashfs. The result would then be > copied into a fresh LUKS container. So creating encrypted bundles would > required root. Correct, this is a limitation of device-mapper which is used by cryptsetup. This wasn't a show stopper for our particular case, but I see how this could be an issue for other cases. >> * Option 2: >> Implement encryption support directly into RAUC as a compile option. >> This could create an encrypted bundle and decrypt and mount during >> install time. > > I'd definitely prefer built-in encryption support. Mainly because: > - It can be integrated with the existing CMS-based signatures, so we > get support for multiple recipient devices with individual private > keys. > - It's easier to use (you don't need to write a handler). > - By using dm-crypt without LUKS, we can generate the encrypted bundle > without requiring root privileges (via OpenSSL). Would we be able to encrypt the squashfs partition using OpenSSL without mounting it with dm-crypt? Or I suppose another way, can dm-crypt mount a squashfs partition which was encrypted with OpenSSL? > - When using per device private keys, we can also store them in a TPM > or a PKCS#11 token/smartcard, so they can't be easily extracted. > > As we use CMS [1] for signing, we can potentially support everything > the OpenSSL cms tool (see 'man cms') supports (N-of-M signatures, > encryption with shared secrets and/or public/private keys). These are all good points. I am not too familiar with the abilities of CMS. I will need to do some reading before I can give as thoughtful of a response. > So my current concept would be to use a differemt payload in the CMS > message (instead of a hash over the squashfs), consisting of > information about the encryption (algorithm, parameters and payload > key) and the payload hash (or dm-verity root hash). The CMS message > would then be encrypted in addition to being signed. We don't have to use LUKS, but its header does include information about the encryption method which is inspection without decrypting first. It builds in a similar mechanism, though the header is only signed, not encrypted. Of course a user of RAUC will need to store the decryption key, but this could still leverage a TPM or secure storage on whichever architecture they used. > When opening the bundle, OpenSSL would detect that the CMS message is > encrypted, look for the matching private key and decrypt. Then we have > the information to configure dm-crypt and/or dm-verity on top of the > loop device. The rest of the installation would proceed as usual. Are you suggesting: [Arbitrary encryption method (squashfs)][CMS encrypted+signed (squashfs encryption format + payload key)] So you would first decrypt the CMS message using OpenSSL with a private key (optionally stored on a TPM or smartcard), use the newly acquired information to setup dm-crypt, and mount the mapper device. Am I understanding correctly? > So the only places that would need to change are bundle opening (setup > OpenSSL for decryption and configure device mapper targets) and bundle > creation (optionally encrypt, optionally use veritysetup and use > OpenSSL for CMS encyption). > > What do you think about this apporach? I agree building in encryption support is nice, though successful implementation of encryption and security for embedded devices requires some level of custom hardware. This is going to be very device specific and I'm worried forcing the use of a specific procedure may be too limiting. I wonder if we would still need to provide some user customizability in the form of a handler somewhere. Even without storing the payload key in a CMS message, it should be possible for a user to securely implement a TPM to generate the decryption key. Let me do a little more reading on OpenSSL encryption and CMS messages. Thanks again, Evan _______________________________________________ RAUC mailing list
