Hi everyone,
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.
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.
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.
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.h https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.c
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.
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.c#L11...
1. Device sends its public key 2. 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:
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.h#L32
#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.
Cheers,
C
On Fri, Sep 11, 2020 at 09:52:45AM -0400, Christopher Friedt wrote:
Hi everyone,
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.
Wait, Greybus is transport-neutral, why are you trying to bake crypto and authentication (two totally different things) into it?
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.
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.
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.h https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.c
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.
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.c#L11...
- 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:
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.h#L32
#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
Why does this have to be part of GB at all? Can't the authentication happen outside of the core and then when "all is good", the connection is handed off to the GB core for the normal enumeration process?
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.
What is the use-case here? "Traditionally" GB was done with wires, and the data transport is not encrypted, nor does it need to be (like PCI and USB and bucket-loads of other wired protocols). If you wish to put GB over the network, the network connection itself can handle any needed authentication to set up the connection, and then use any type of encryption for the transport if it wants to, GB doesn't care.
But, to get back to the original issue, why do you want authentication? Do you authenticate your USB keyboard? Your PCI network card? Your NVME disk? What is the usecase here?
Same for crypto, why do you care about encrypting the datastream here? What is the usecase?
thanks,
greg k-h
Hi Greg,
On Fri, Oct 2, 2020 at 7:32 AM Greg KH gregkh@linuxfoundation.org wrote:
On Fri, Sep 11, 2020 at 09:52:45AM -0400, Christopher Friedt wrote:
Hi everyone,
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.
Wait, Greybus is transport-neutral, why are you trying to bake crypto and authentication (two totally different things) into it?
I agree that Greybus is transport-neutral, and am well aware that crypto and authentication are two totally different things.
However, I am not suggesting that we bake auth and crypto into Greybus, or to be more specific, I also don't think that they belong in Greybus Core.
Why does this have to be part of GB at all? Can't the authentication happen outside of the core and then when "all is good", the connection is handed off to the GB core for the normal enumeration process?
Thanks - that's a good suggestion, and really I'm looking for suggestions. I think that everyone interested should definitely weigh in.
We could definitely use a separate layer that handles authentication for Greybus. The only reason I used Greybus messages to encapsulate that was because it was easy enough to do for a proof of concept.
Are there any recommendations for a generic authentication protocol that can be used here?
I found this [2] which shows OpenSSH using OAuth as a 2nd factor after public key authentication but I don't think that's what we're looking for (or is it?).
Ideally, there would be an authentication layer that supports: * simple, point-to-point public key authentication, without referring to a third party * something like Oauth, for the convenience of authenticating with your mobile device * possibly FIDO? I know that it must have fairly small footprints for memory-constrained devices
Oauth supports public-key authentication via PKCS #11 [3], but it's not clear to me if that requires a third party.
Ideally I would use a generic authentication library that already exists for Zephyr, but I can't find anything that specifically does this. I know that they support mbedtls, but I'm can't tell if mbedtls supports any of the above requirements.
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.
As mentioned above, if not tunneling Greybus, and authentication & encryption were added as extensions outside of Greybus Core, plaintext would be the default case (i.e. "I am not suggesting that we bake auth and crypto into Greybus").
In the case that some other authentication library were not used, negotiating any kind of authentication and encryption would be completely optional: * "All Protocols shall be versioned, to allow future extensions (or fixes) to be added and recognized." - Chapter 7 of the spec * the Common Greybus Protocol Version Operation would be used first before making an attempt to use authentication or encryption (that would be a "shall" behaviour). * even if the Common Greybus Protocol Version Operation wasn't done first, and an unsupported Greybus message is received, GB_OP_INVALID is returned as a result [1]
I can't seem to find the line of code in Linux, where an unsupported GB operation type is received, but I would imagine it's a similar result of GB_OP_INVALID.
What is the use-case here? "Traditionally" GB was done with wires, and the data transport is not encrypted, nor does it need to be (like PCI and USB and bucket-loads of other wired protocols). If you wish to put GB over the network, the network connection itself can handle any needed authentication to set up the connection, and then use any type of encryption for the transport if it wants to, GB doesn't care.
But, to get back to the original issue, why do you want authentication? Do you authenticate your USB keyboard? Your PCI network card? Your NVME disk? What is the usecase here?
It's not currently standard practice to authenticate and encrypt traffic that goes over wires connecting devices but that's not to say it shouldn't be done in order to secure a system.
With a sensitive enough software-defined radio it's entirely possible to decode a password typed on a USB keyboard from the next room over. In fact, exactly that was done at my previous place of employment. I think it's even possible to decode what appears on current monitors that use LVDS signalling using a similar method, to some level of SNR.
Same for crypto, why do you care about encrypting the datastream here? What is the usecase?
The use-case is really just secure communications.
If I wanted to allow malicious people to perform a replay attack and open my front door or my garage door, or have the ability to set my thermostat or turn my lights off and on, then I would be happy to use plaintext for everything, but I'd rather not let malicious people do that.
I think I understand where you're coming from though in terms of not wanting to disturb Greybus Core in any way.
C
[1] https://github.com/projectara/nuttx/blob/5bf12438cfff61121a900faa01b43506adc... [2] https://www.insecure.ws/linux/openssh_oath.html [3] https://openauthentication.org/wp-content/uploads/2015/09/ReferenceArchitect...
On 9/11/20 8:52 AM, Christopher Friedt wrote:
Hi everyone,
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.
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.h https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.c
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.
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.c#L11...
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.
-Alex
- 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:
https://github.com/friedtco/gbridge/blob/feature/tcpip-ble-ipsp/pkauth.h#L32
#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.
Cheers,
C
On 07-11-20, 11:33, Alex Elder wrote:
On 9/11/20 8:52 AM, Christopher Friedt wrote:
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.
We were trying to implement something which can authenticate a module inserted into the phone using some keys present with the module, but we weren't able to finish the work before the project closed. So it has some infrastructure in place, but no real plan on how to use it now.
I can't comment on this.
Hi Alex & all.
Happy New Year, and thanks for all of the advice :-)
I ended up taking it and am using TLS for authentication and encryption. Standards are nice.
Both one-way authentication (similar to HTTPS) and mutual authentication (similar to SSH public key) are supported now between Zephyr[1] and Gbridge[2].
On Sat, Nov 7, 2020 at 12:33 PM Alex Elder elder@linaro.org wrote:
On 9/11/20 8:52 AM, Christopher Friedt wrote: 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
I would also concur at this point. My original changes were mostly doing the same thing that TLS does but just in a non-standard way. Originally, it was just a proof of concept for the client due to underspecification, but TLS just makes way more sense.
I've used Zephyr's TLS extensions for the socket API and OpenSSL on the Linux side. So it's pretty clean and also very testable.
There are no changes required to the Greybus spec so that works as-is, and encryption is kept as a transport-layer option. For gbridge, it's a separate logical transport and can be used independently of plain-text TCP/IP too. The service is advertised using "_greybuss._tcp" rather than "_greybus._tcp".
Quite a number of features were added to Zephyr to support this, including
* DNS-SD (and slight modification of the existing mDNS impl) * aligned heap allocators * dynamic pthread stack support * some minor bugfixes to TCP * some driver support for the physical layer (IEEE 802.15.4, BLE) * a forthcoming template for external modules
The fact that gbridge uses a separate socket per CPort (although kind of nice conceptually) does have a non-negligable impact on memory-constrained devices though.
That impact is exacerbated when TLS is thrown into the mix. I've added another pair of tickets to concentrate all traffic into a single socket connection like what is currently done for the UART transport. That reduces not only the memory required per socket, but also the duplication of TLS resources on a per-socket basis (especially when mutual auth is used). A future change for gbridge and Linux might be to move socket I/O to the kernel after TLS auth + AES is set up. That was out of scope for my existing contract, but it would be "interesting" to implement.
At this point, my Greybus for Zephyr module is alpha ready. It works over UART, but also any other transport that supports TCP/IP such as Ethernet, WiFi, BLE, 802.15.4 (both 2.4 GHz and Sub GHz), CAN (although that's untested). Still lots of work to be done (like support for different Greybus protocols), but it's quite usable for GPIO, I2C, and SPI now ;-)
Thanks again for all of the feedback and for everyone's contributions to Greybus over the years!
Chris
[1] https://github.com/cfriedt/greybus-for-zephyr/pull/34/files [2] https://github.com/cfriedt/gbridge/pull/7/files
On Tue, Jan 05, 2021 at 12:37:38PM -0500, Christopher Friedt wrote:
Hi Alex & all.
Happy New Year, and thanks for all of the advice :-)
I ended up taking it and am using TLS for authentication and encryption. Standards are nice.
Both one-way authentication (similar to HTTPS) and mutual authentication (similar to SSH public key) are supported now between Zephyr[1] and Gbridge[2].
On Sat, Nov 7, 2020 at 12:33 PM Alex Elder elder@linaro.org wrote:
On 9/11/20 8:52 AM, Christopher Friedt wrote: 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
I would also concur at this point. My original changes were mostly doing the same thing that TLS does but just in a non-standard way. Originally, it was just a proof of concept for the client due to underspecification, but TLS just makes way more sense.
I've used Zephyr's TLS extensions for the socket API and OpenSSL on the Linux side. So it's pretty clean and also very testable.
There are no changes required to the Greybus spec so that works as-is, and encryption is kept as a transport-layer option. For gbridge, it's a separate logical transport and can be used independently of plain-text TCP/IP too. The service is advertised using "_greybuss._tcp" rather than "_greybus._tcp".
Nice, that sounds very reasonable.
Quite a number of features were added to Zephyr to support this, including
- DNS-SD (and slight modification of the existing mDNS impl)
- aligned heap allocators
- dynamic pthread stack support
- some minor bugfixes to TCP
- some driver support for the physical layer (IEEE 802.15.4, BLE)
- a forthcoming template for external modules
Hey, even better, Zephyr is benefiting from this, great work.
The fact that gbridge uses a separate socket per CPort (although kind of nice conceptually) does have a non-negligable impact on memory-constrained devices though.
In what way? Is this because a socket has a lot of memory state needed, or is this some other greybus overhead?
That impact is exacerbated when TLS is thrown into the mix. I've added another pair of tickets to concentrate all traffic into a single socket connection like what is currently done for the UART transport. That reduces not only the memory required per socket, but also the duplication of TLS resources on a per-socket basis (especially when mutual auth is used). A future change for gbridge and Linux might be to move socket I/O to the kernel after TLS auth + AES is set up. That was out of scope for my existing contract, but it would be "interesting" to implement.
At this point, my Greybus for Zephyr module is alpha ready. It works over UART, but also any other transport that supports TCP/IP such as Ethernet, WiFi, BLE, 802.15.4 (both 2.4 GHz and Sub GHz), CAN (although that's untested). Still lots of work to be done (like support for different Greybus protocols), but it's quite usable for GPIO, I2C, and SPI now ;-)
Any Linux kernel-side changes needed for any of this?
I am interested in getting the remaining greybus code out of staging this year, as there's no good reason for it to be hanging around with no real development happening. If there's anything left to be done on the Linux portion, that would be good to know, otherwise I think we'll just start moving indivdual drivers out of staging slowly...
thanks,
greg k-h
On Tue, Jan 5, 2021 at 1:21 PM Greg KH greg@kroah.com wrote:
On Tue, Jan 05, 2021 at 12:37:38PM -0500, Christopher Friedt wrote:
Hi Alex & all. The fact that gbridge uses a separate socket per CPort (although kind of nice conceptually) does have a non-negligable impact on memory-constrained devices though.
In what way? Is this because a socket has a lot of memory state needed, or is this some other greybus overhead?
Nothing to do with Greybus.
I'm pulling numbers out of thin air here, but in Zephyr, each TCP service consumes * >= 2 POSIX fd's (and entries in the fd table) * >= 2 TCP contexts * >= some minimal number of network buffers (each consuming some size)
Most of those are statically allocated (configured via Kconfig), but they do add up. I don't have a specific number of bytes for each of these.
The real gotcha is in the TLS contexts. So for each TLS service, there are * additional fd's (2 iirc, but don't quote me on it) * 2 buffers of >= 512 bytes (one for each of TX, RX) **per socket** * 1 buffer for the client cert (if mutual auth is used) **per socket** * 1 buffer for the ca cert (if mutual auth is used) **per socket**
RSA key minimum safe-ish size is 2k, so those numbers do add up on a tiny device with e.g. 64k of SRAM, especially when considering that most Greybus handlers are threaded (I think the default thread size is 1k).
At this point, my Greybus for Zephyr module is alpha ready. It works over UART, but also any other transport that supports TCP/IP such as Ethernet, WiFi, BLE, 802.15.4 (both 2.4 GHz and Sub GHz), CAN (although that's untested). Still lots of work to be done (like support for different Greybus protocols), but it's quite usable for GPIO, I2C, and SPI now ;-)
Any Linux kernel-side changes needed for any of this?
So far, none. The only caveat to that is, that to automagically probe the Linux driver for a number of SPI or I2C devices, some platform data is required. Vaishnav Ma is working on that atm (for microbus) and he's pretty far along now. The same ideas could be reused for different form factors such as Feather, etc, so there is some overlap.
I am interested in getting the remaining greybus code out of staging this year, as there's no good reason for it to be hanging around with no real development happening. If there's anything left to be done on the Linux portion, that would be good to know, otherwise I think we'll just start moving indivdual drivers out of staging slowly...
I can appreciate that. Nothing that I've seen in upstream has seemed to cause any issues that I've encountered at this point.
I believe that gb_netlink and gbridge require some work to be done in terms of graceful shutdown, error, and connection handling, as there are occasionally panics, but (from my experience) those are most likely due to issues in gb_netlink or gbridge and not the upstream kernel code.
For example,
https://github.com/anobli/gbridge/blob/master/controllers/tcpip.c#L207
Also, the simple fact that the gbridge process does not require root privileges is (a bit) concerning. The gb_netlink module should probably be modified to check the permissions of the process sending it data, maybe some userspace greybus user / group should be created, etc.
C