On 9/11/20 8:52 AM, Christopher Friedt wrote:
Christopher, I was on vacation during the Plumbers conference, and finally spent the time yesterday to watch your presentation at the "You, Me, and IoT Two" microconference there. Your coverage of Project Ara was almost entirely correct, and I appreciated learning a few things about Zephyr. I also watched the presentation by Vaishnav. Anyway, after that I returned to this message and read through it again more closely.
I will start by mentioning some things I don't know enough about. First, I don't know much about how secure sockets are implemented. I generally understand public key authentication but I lack detail on how a negotiated session key is actually used by the socket layer (or by the API that uses the socket layer) to encrypt traffic.
Second, I haven't looked closely at Alexandre's GBridge code, but I think I understand what it is trying to do--simulating parts of the Project Ara model (SVC and processor bridges).
I also concur with Greg's questions about why you feel these things need to be incorporated *into* Greybus, rather than set up *around* Greybus somehow. On Project Ara, the underlying transport was a UniPro network. Our basic assumption was that the UniPro network was embedded and provided physical security. I'm forgetting some details now but module firmware was encrypted using keying material tied to the module. And the module identified itself to the AP in a way that somehow used public/private keys. (I should probably see if I have any old notes on this...)
In any case I do have a few comments to share on what you have written, including one thoughts about why you might need to do something inside Greybus to support encrypted communication.
I thought it might be a good time to start / re-start / join the conversation about authentication and encryption in Greybus, and in particular, for using a transport (and lower layers) other than UniPro. This is the logical next step after getting the TCP/IP transport working with gbridge over BLE, 802.15.4, WiFi, ethernet, UART, etc.
This sounds great. Most details of the Greybus protocol are independent of the underlying transport by design, and this proves we were successful. It seems to me that some things (especially some SVC interactions) were probably designed based on idiosyncrasies of the UniPro network/switch we were working with though.
There is the Component Authentication Protocol that exists already, but I'm not terribly familiar with it. Is anyone able to clarify if there is some overlap between CAP and some of the work that follows? If it's possible to re-use some of the CAP, that would be nice.
I can't comment on this.
Just over a year ago I set up authentication and encryption over Greybus for BeagleBoard.org. I was able to demonstrate it working over a TCP/IP transport. Here is some code that is on the back-burner for now.
I have looked at the header and glanced at the code but haven't looked at it very closely. It's not completely clear to me *where* this code runs--is it in user space? Is it associated with connections? It seems like it's a completely new Greybus protocol, which would not be usable by the other existing protocols. Not having read the code or seen how it ties in to other code (including GBridge) I don't think I unserstand the overall model, and where this fits into it.
Here are a few thoughts though.
Overall, if traffic over a Greybus connection were to be encrypted, all existing protocols should benefit from how that is implemented. That is, connection traffic should be encrypted or not, and the driver that uses the (for example) GPIO connection should not need to be aware of that.
The encryption should be provided by the underlying transport. In the case of TCP that probably means Greybus sits on top of the TLS/SSL (application) layer. This implies that a session key is negotiated, and I presume there already exist ways to do that, but this is where one of the holes in my knowledge shows.
It seems to me that there could be a chicken-and-egg problem with negotiating the session key, and conceivably that could mean Greybus needs to be involved somehow. But again, if we already know we're using TCP sockets, there must have already been a way for that connection to be set up for Gretbus to use, so it just isn't clear why this would be needed.
As I mentioned, modules (interfaces, really, or to be really specific, GP bridges) were expected to hold secure key information. If we need such a key we should use what already exists and not add something more. To be honest I don't recall formalizing how that would be accessed though, so this might not be a very helpful comment...
I have a PR open to anobli/gbridge on GitHub that pulls in the non-authentication / encryption changes. So the change that deals with auth and encryption is fairly small. On the Host side, it uses OpenSSL.
We are using regular SSH keys for asymmetric authentication and the initial secure channel, then generating and sharing an AES-128 session key for symmetric encryption of the subsequent communications. The wireless SoC we're using for testing is the CC1352R from TI, and it has both AES and PK hardware accelerators. Most SoC's these days have an AES accelerator, at least.
The handshake is described here, but I'll copy it into the email as well.
I'm going to ignore the points I made above, and provide you with some feedback on your proposed Greybus protocol.
This might not align with other existing PKA mechanisms, but I have a simpler method that I would propose in place of what you have described. I.e. if I were designing this Greybus message exchange myself, I might have suggested what follows.
First, in Greybus, the AP is the king of the world. So the first thing that should change in your protocol is that the AP, not the module (host, not the device) should initiate the exchange. I.e., for your protocol, step 1 would be "AP sends device its public key."
Second, your protocol involves a lot of messages. I think this might make handling each message stateless, but I don't believe that's a critical property in Greybus protocols. The (mutual) authentication process is a process, after all, and it is only successful after the series of messages, in sequence, is complete.
So with that, here is what I would suggest as an alternative. It consists of two operations (two request/response pairs), both initiated by the AP. The AP and all modules have unique public and private keys. For Project Ara we assumed the AP had the ability to consult an online repository of legitimate module public keys. In each message below, unless a value has a known fixed length, a length-of-value field would also be present.
1. AP sends an IDENTIFY operation request message to the module. It contains: AP public key in plain text (and length...) Module receives the IDENTIFY request and extracts the AP public key. It records this for future use. - The module could check its "authorized keys" to determine whether the AP legitimate, but this is not really practical. 2. Module sends an IDENTIFY response message to the AP. It contains: Module public key encrypted with AP public key AP public key encrypted with module private key AP receives the response message and extracts the two values it contains. - AP decrypts the first value with its AP private key to produce the module public key. It records this. - AP can consult its "authorized keys" list and aborts the session setup if it is not legitimate. - AP decrypts the second value with the module public key. If it matches the AP public key, the module is the authentic owner of the module public key. AP creates a symmetric session key to use. 3. AP sends a SESSION_KEY request message to the module. It contains: Module public key encrypted with the AP private key Session key encrypted with the module public key Module receives the SESSION_KEY request and extracts the two values it contains. - Module decrypts the first value with the AP public key. If it matches the module public key the AP is the authentic owner of that AP public key. - Module decrypts the second value with its module private key. This is recorded as the session key. 4. Module sends a SESSION_KEY response message to the AP. It contains only a result code (success or fail). - Module associates session key with socket AP receives the SESSION_KEY response - If result code is success, AP associates session key with socket.
I supply the above mainly to give you feedback about what I would consider good practice in designing a Greybus protocol. Keep it simple and concise, and take advantage of the ability to carry information in both the request and response messages. I don't guarantee that this would survive rigorous security analysis.
Above all though, I am not convinced we need to do this negotiation *within* Greybus.
I really appreciate the renewed interest in Greybus. We who worked on it felt it had value beyond Project Ara, as reflected in Greg's push to get it merged into the Linux device staging tree.
- Device sends its public key
- Host compares device public key with those in a collection of
trusted public keys. if not found connection closed. 3. Host sends its public key 4. Device compares host public key with those in a collection of trusted public keys. if not found connection closed. 5. Device creates a randomly generated message, "PlainText A". 6. Device encrypts "PlainText A" using Host public key, creating "CipherText A". 7. Device transmits "CipherText A" to Host. 8. Host decrypts "CipherText A" with Host private key, resulting in "PlainText B". 9. Host encrypts "PlainText B" using Device public key, creating "CipherText B". 10. Host transmits "CipherText B" to Device. 11. Device decrypts "CipherText B" with Device private key, resulting in "PlainText C". 12. Device compares "PlainText A" and "PlainText C", and responds with success or noauth. 13. Host creates a randomly generated message, "PlainText D". 14. Host encrypts "PlainText D" using Device public key, creating "CipherText D". 15. Host transmits "CipherText D" to Device. 16. Device decrypts "CipherText D" with Device private key, resulting in "PlainText E". 17. Device encrypts "PlainText E" using Host public key, creating "CipherText E". 18. Device transmits "CipherText E" to Host. 19. Host decrypts "CipherText E" with Host private key, resulting in "PlainText F". 20. Host compares "PlainText D" and "PlainText F", and responds with success or noauth. 21. Host generates symmetric session key as "PlainText G", pairs session key with socket. 22. Host encrypts "PlainText G" with Device public key, resulting in "CipherText G". 23. Host transmits "CipherText G" to device. 24. Device decrypts "CipherText G" using Device private key, resulting in "PlainText H". 25. Device pairs the session key ("PlainText H") with socket.
Currently, this handshake happens when a new connection is created on any port / CPort (be it Control, GPIO, I2C, SPI, etc).
While I understand that this security mechanism is not nearly as sophisticated as that of Thread, for example, it's fairly easy to implement locally for developers.
However, we would ultimately like to support more than one method of authentication and encryption in Greybus. For the very basic method we implemented above, 5 additional message primitives were required:
#define GB_PKAUTH_TYPE_VERSION 0x7a #define GB_PKAUTH_TYPE_PUBKEY 0x7b #define GB_PKAUTH_TYPE_CHALLENGE 0x7c #define GB_PKAUTH_TYPE_CHALLENGE_RESP 0x7d #define GB_PKAUTH_TYPE_SESSION_KEY 0x7e
For full negotiation of the auth mechanism and encryption algorithm (e.g. OAuth2 authentication + 3DES encryption) we'll probably need a few more message primitives, and likely a new minor version (at least) for each CPort protocol.
It should be possible (although discouraged) to opt for everything in plaintext, but that would also be the default case for the CPort protocols as they exist today.
I would love to hear some ideas about this from whoever is interested.