diff options
Diffstat (limited to 'doc/rvi_protocol.md')
-rw-r--r-- | doc/rvi_protocol.md | 337 |
1 files changed, 77 insertions, 260 deletions
diff --git a/doc/rvi_protocol.md b/doc/rvi_protocol.md index ce9c445..6536111 100644 --- a/doc/rvi_protocol.md +++ b/doc/rvi_protocol.md @@ -1,9 +1,4 @@ -<style type="text/css" media="print"> - div.pagebreak - { - page-break-before: always; - } -</style> +<style type="text/css" media="print"> div.pb { page-break-before: always; }</style> Copyright (C) 2015-16 Jaguar Land Rover This document is licensed under Creative Commons @@ -12,13 +7,15 @@ Attribution-ShareAlike 4.0 International. # RVI CORE PROTOCOL This document describes the core protocol between two RVI nodes. +For all examples below the certificates and credentials used are the samples +created as described in [rvi_certificates.md](rvi_certificates.md). + # STANDARDS USED -[1] Transport Layer Security - TLS (link)[https://tools.ietf.org/html/rfc5246]<br> -[2] JSON Web Token RFC7519- JWT (link)[https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32]<br> -[3] MessagePack - (link)[http://msgpack.org/index.html]<br> -[4] base64url - (link)[https://en.wikipedia.org/wiki/Base64)<br> -[5] Transport Layer Security (TLS) - (link)[https://en.wikipedia.org/wiki/Transport_Layer_Security]<br> -[6] X.509 Certificates - (link)[https://en.wikipedia.org/wiki/X.509]<br> +[1] [Transport Layer Security - TLS](https://tools.ietf.org/html/rfc5246)<br> +[2] [JSON Web Token RFC7519 - JWT](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32)<br> +[3] [MessagePack](http://msgpack.org/index.html)<br> +[4] [base64url](https://en.wikipedia.org/wiki/Base64)<br> +[5] [X.509 Certificates](https://en.wikipedia.org/wiki/X.509)<br> # FEATURES COVERED BY PROTOCOL 1. **Authorization**<br> @@ -33,7 +30,7 @@ is authorized to invoke. Invoke services on remote RVI nodes. # FEATURES NOT COVERED BY PROTOCOL -For all but the last item, TLS 1.2 [5] an be used as an underlying +For all but the last item, TLS 1.2 [1] an be used as an underlying protocol to provide the features lacking in RVI Core protocol. 1. **Authentication**<br> @@ -55,7 +52,7 @@ Public Key Infrastructure and certificate distribution. 6. **RVI Node Discovery**<br> Allowing two unconnected RVI nodes to discover each other so that they can initiate connection. -<div class="pagebreak"></div> +<div class="pb"></div> # OVERVIEW The RVI core protocol is the default protocol used between two RVI @@ -73,7 +70,7 @@ peer. ## Certificates and credentials Three types of certificates and credentials are used by the RVI Core -protocol in conjunciton with TLS. See [6] for details on X.509. +protocol in conjunciton with TLS. See [5] for details on X.509. 1. **Root certificate [X.509]**<br> Generated by a trusted provisioning server and pre-provisioned on all @@ -90,7 +87,7 @@ services that the device has right to register. Embeds the device X.509 certificate as a PEM-encoded string. Signed by root cert. -<div class="pagebreak"></div> +<div class="pb"></div> ## Integration between TLS and RVI Core RVI Client and server X.509 certificates are exchanged when the original @@ -109,6 +106,14 @@ signed by the root x.509 certificate. # PROTOCOL FLOW +The messages used for illustration below are all presented in JSON format. +Other encodings (currently only msgpack) are supported, but all RVI messages +can be encoded as JSON. Each message is identified by a `"cmd": Cmd` +attribute, where `Cmd` can be `"au"`, `"sa"`, `"rcv"`, `"frg"`, `"ping"`. + +The receiver of a message should be able to handle the presence of attributes +other than the ones described here. + ## Sequence Diagram The diagram below outlines the sequence between the client and the server. @@ -118,20 +123,38 @@ client-server terminology only denotes who initiates the connection <img src="images/rvi_protocol_flow.png" alt="RVI Core protocol Sequence Diagram" style="width:800"> -<div class="pagebreak"></div> +<div class="pb"></div> ## Authorize command The ```authorize``` command contains a list of RVI credentials, each specifying a set of services that the sender has the right to invoke on the receiving node, and a set of services that the sender has the right to register. -Please see the "RVI Credentials" chapter for detailss on RVI credentials. +```json +{"cmd" : "au", + "ver" : "1.1", + "creds": [ "eyJhbGci..." ] +} +``` + +Attributes that may be present, but not currently used: `"addr"`, `"port"`. + +Please see the [rvi_certificates.md](rvi_certificates.md) document for details on RVI credentials. ## Service Announce command The ```service_authorize``` command contains a list of services available on the sender that match services listed in RVI credentials received from the remote party. +```json +{"cmd" : "sa", + "stat" : "av" | "un", + "svcs" : [ "genivi.com/vin/d32cef88-.../hvac/seat_heat_left", ... ] +} +``` + +The `"stat"` attribute can have the value `"av"` (available) or `"un"` (unavailable) and indicates the status of all services listed in `"svcs"`. + ## Message command The ```message``` command contains a service name and a number of arguments to be presented to the corresponding service at the @@ -139,6 +162,37 @@ receiving end. This is an asynchronous command that does not expect an answer. Replies, publish/subscribe, and other higher-level functions are (for now) outside the scope of the RVI Core protocol. +```json +{"cmd" : "rcv", + "tid" : Tid, + "mod" : Mod, + "data" : Data +} +``` + +Note: The `"tid"` attribute is currently not checked by RVI. + +The content of `Data` is parsed and then encoded according to the +protocol used to forward the message. The modules `proto_json_rpc` and +`proto_msgpack` expect it to be a 'struct' (or corresponding), as follows: + +```json +{"service" : ServiceName, + "timeout" : Timeout, + "parameters: Parameters +} +``` + +`Timeout` is either a relative time in milliseconds, or an absolut time +(unix time) in seconds. + +`Parameters` is a 'struct' containing named arguments to be passed to the +service. It _can_ also contain RVI-specific arguments, named as `"rvi.Opt"`. +Currently supported RVI options are + +* `"rvi.max_msg_size"` (integer > 0) +* `"rvi.reliable"` (true | false) + ## Double connect resolution There is a risk that two parties try to initiate a connection to each other in a race condition, creating two connections between them, as @@ -179,7 +233,7 @@ Node1 Address | Node2 Address | Connecting side to be terminated The connection is terminated regardless of its current protocol session state. -<div class="pagebreak"></div> +<div class="pb"></div> ## Chunking of large messages @@ -209,7 +263,8 @@ will currently be unreliable when using JSON encoding, due to escaping of binary data. When including these options in the "parameters" list of a message invocation, -the names can be prefixed with "rvi.", e.g. "rvi.max_msg_size". +the names can be prefixed with "rvi.", e.g. "rvi.max_msg_size", or +"rvi.reliable". **TODO**: Introduce timers. Currently there are none. @@ -221,7 +276,7 @@ fragment (with a starting offset of 1), and then wait for the receiving side to request more fragments using "frg-get" messages. When the sending side receives a "frg-end" message, it will forget about the message. -<div class="pagebreak"></div> +<div class="pb"></div> ### Encoding @@ -238,7 +293,7 @@ non-whitespace byte. Configuring fragmentation encoding in RVI Core is done for the specific data link module, e.g. -``` +```json { data_link, [ { dlink_tcp_rpc, gen_server, [ @@ -251,241 +306,3 @@ data link module, e.g. ] } ``` - -# PROTOCOL DEFINITION -This chapter describes the protocol message formats and how the various fields are used. - -For all examples below the following certifcates are used: - -## Sample root certificate -The self signed root certificate used in the examples throughout this -document was generated using the following commands: - -```Shell -# Create root key pair -openssl genrsa -out insecure_root_key.pem 1024 - -# Create a self-signed root CA certificate, signed by the root key created above -openssl req -x509 -new -nodes -key insecure_root_key.pem -days 365 -out insecure_root_cert.crt -``` - -The content of the sample ```insecure_root_key.pem``` private key -file, which has no password protection, is: - -``` ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDg5A1uZ5F36vQEYbMWCV4wY4OVmicYWEjjl/8YPA01tsz4x68i -/NnlMNalqpGCIZ0AwqGI5DZAWWoR400L3SAmYD6sWj2L9ViIAPk3ceDU8olYrf/N -wj78wVoG7qqNLgMoBNM584nlY4jy8zJ0Ka9WFBS2aDtB3Aulc1Q8ZfhuewIDAQAB -AoGAfD+C7CxsQkSc7I7N0q76SuGwIUc5skmUe6nOViVXZwXH2Or55+qqt+VzsbO7 -EJphk7n0ZR0wm/zKjXd3acaRq5j3fOyXip9fDoNj+oUKAowDJ9vub0NOPpU2bgb0 -xDnDeR0BRVBOTWqrkDeDPBSxw5RlJunesDkamAmj4VXHHgECQQDzqDtaEuEZ7x7d -kJKCmfGyP01s+YPlquDgogzAeMAsz17TFt8JS4RO0rX71+lmx7qqpRqIxVXIsR58 -NI2Th7tRAkEA7Eh1C1WahLCxojQOam/l7GyE+2ignZYExqonOOvsk6TG0LcFm7W9 -x39ouTlfChM26f8VYAsPxIrvsDlI1DDCCwJBAITmA8lzdrgQhwNOsbrugLg6ct63 -kcuZUqLzgIUS168ZRJ1aYjjNqdLcd0pwT+wxkI03FKv5Bns6sGgKuhX3+KECQFm/ -Z93HRSrTZpViynr5R88WpShNZHyW5/eB1+YSDslB1FagvhuX2570MRXxybys8bXN -sxPI/9M6prI8AALBBmMCQD+2amH2Y9ukJy10WuYei943mrCsp1oosWjcoMADRCpj -ZA2UwSzj67PBc5umDIAlhVRMX0zH/gLj54rfIkH5zLk= ------END RSA PRIVATE KEY----- -``` - -The root key above is checked in as ```priv/keys/insecure_root_key.pem```. - -<div class="pagebreak"></div> - -The content of the sample ```insecure_root_cert.crt``` file is: - -``` ------BEGIN CERTIFICATE----- -MIICUjCCAbugAwIBAgIJAMI080XZPsPUMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV -BAYTAlVTMQ8wDQYDVQQIDAZPcmVnb24xETAPBgNVBAcMCFBvcnRsYW5kMQ8wDQYD -VQQKDAZHRU5JVkkwHhcNMTUxMTI3MjMxMTQ0WhcNMTYxMTI2MjMxMTQ0WjBCMQsw -CQYDVQQGEwJVUzEPMA0GA1UECAwGT3JlZ29uMREwDwYDVQQHDAhQb3J0bGFuZDEP -MA0GA1UECgwGR0VOSVZJMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDg5A1u -Z5F36vQEYbMWCV4wY4OVmicYWEjjl/8YPA01tsz4x68i/NnlMNalqpGCIZ0AwqGI -5DZAWWoR400L3SAmYD6sWj2L9ViIAPk3ceDU8olYrf/Nwj78wVoG7qqNLgMoBNM5 -84nlY4jy8zJ0Ka9WFBS2aDtB3Aulc1Q8ZfhuewIDAQABo1AwTjAdBgNVHQ4EFgQU -4Sz8rAMA+dHymJTlZSkap65qnfswHwYDVR0jBBgwFoAU4Sz8rAMA+dHymJTlZSka -p65qnfswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQDFOapf3DNEcXgp -1u/g8YtBW24QsyB+RRavA9oKcFiIaHMkbJyUsOergwOXxBYhduuwVzQQo9P5nR0W -RdUfwtE0GuaiC8WUmjR//vKwakj9Bjuu73ldYj9ji9+eXsL/gtpGWTIlHeGugpFs -mVrUm0lY/n2ilJQ1hzBZ9lFLq0wfjw== ------END CERTIFICATE----- -``` - -The root certificate above is checked in as ```priv/certificates/insecure_root_cert.crt```. - - -**DO NOT USE THE KEYS AND CERTIFICATES ABOVE IN PRODUCTION!<br> -ANY PRODUCTION KEYS SHOULD BE GENERATED BY THE ORGANIZATION AND BE 4096 BITS LONG.** - -## Sample device certificate - -The sample device x.509 certificate, signed by the root certificate above, -was generated with the following command: - -```Shell -# Create the device key. In production, increase the bit size to 4096+ -openssl genrsa -out insecure_device_key.pem 1024 - -# Create a certificate signing request -openssl req -new -key insecure_device_key.pem -out insecure_device_cert.csr - -# Sign the signing request and create the insecure_device_cert.crt file -openssl x509 -req -days 365 -in insecure_device_cert.csr \ - -CA insecure_root_cert.crt -CAkey insecure_root_key.pem \ - -set_serial 01 -out insecure_device_cert.crt -``` - - -The ```insecure_device_cert.csr``` intermediate certificate signing -request can be deleted once the three steps above have been executed. - -The content of the sample ```insecure_device_key.pem``` private key -file, which has no password protection, is: - -``` ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQCbb4jPAESKxarj3NJsgfQbhfTHZAP9kmram2TFnkzlCRxq4wQx -BDC0O85PAMgZou0armGGbOu0si4cpVRioerCQJXnMWx1MI+3GUktW5ijI3ui+tYC -sMQZtjSBVNXFZdoyZU2lPVWITOMZOe8o9vJ5DcUmFj9b2xV9jQ19oh+2+QIDAQAB -AoGAVCYV0rs6YEaTNbke0k+ocB4dXrTu1CCoaKEn9TS2PGiqUdOFOWQjWe/myS6L -JhXmd0Ng2P2uvayY+jknbh5qkNeEgTDhXJlAjiXlCADYArhgib+evRHgKz7RLTjX -tGklbmc7oECTEpjkchJC5XcJhXzHCIjroyOJvBuAVa+SeAECQQDNC+KW7fTKQpiG -YNGIt5MxCMjRparLz0fWod9J9U56wrWzU9Rnb7h9iwzTEJUEcVl9z8rnUdWtYQ8X -3lsz5cDhAkEAwg+kDWbLtXWlIvXhhla7q0+RfKb8vu/gXnkXJa6rcJdJztKRbP3b -9fehVeu9m+1+abahjC1zmQimwd2QVc8BGQJADbtfCGaVPzpoho9TWQmaRO1mrYuf -vZh7IiejEYvpHpWNn53cmrTDsTyvti7lG/APYzqYRxeW7M6UOS/+AaLAYQJAJbEW -AwhZPphoB59MO2RzNPXSYyyn4IoEwTSxuz7uy4KG8mXRmyK/a0m6i06rWDLLn8q6 -G9jkH/AfO35GP3RiWQJBAJLWBlKpHf8TxT65jAwxBhd9ZOkC2w0WidbSYjX9wkkD -38K7ZDm1LSIR69Ut6tdwotkytXvDniOMPY6ENar5IUs= ------END RSA PRIVATE KEY----- -``` - -<div class="pagebreak"></div> - -The content of the sample ```insecure_device_cert.crt``` file is: - -``` ------BEGIN CERTIFICATE----- -MIIB8zCCAVwCAQEwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCVVMxDzANBgNV -BAgMBk9yZWdvbjERMA8GA1UEBwwIUG9ydGxhbmQxDzANBgNVBAoMBkdFTklWSTAe -Fw0xNTExMjcyMzE0NTJaFw0xNjExMjYyMzE0NTJaMEIxCzAJBgNVBAYTAlVTMQ8w -DQYDVQQIDAZPcmVnb24xETAPBgNVBAcMCFBvcnRsYW5kMQ8wDQYDVQQKDAZHRU5J -VkkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJtviM8ARIrFquPc0myB9BuF -9MdkA/2SatqbZMWeTOUJHGrjBDEEMLQ7zk8AyBmi7RquYYZs67SyLhylVGKh6sJA -lecxbHUwj7cZSS1bmKMje6L61gKwxBm2NIFU1cVl2jJlTaU9VYhM4xk57yj28nkN -xSYWP1vbFX2NDX2iH7b5AgMBAAEwDQYJKoZIhvcNAQELBQADgYEAhbqVr9E/0M72 -9nc6DI+qgqsRSMfoyvA3Cmn/ECxl1ybGkuzO7sB8fGjgMQ9zzcb6q1uP3wGjPioq -MymiYYjUmCTvzdvRBZ+6SDjrZfwUuYexiKqI9AP6XKaHlAL14+rK+6HN4uIkZcIz -PwSMHih1bsTRpyY5Z3CUDcDJkYtVbYs= ------END CERTIFICATE----- -``` - -These files are checked into ```priv/certifcates``` and ```priv/keys```. - -**DO NOT USE THE KEYS AND CERTIFICATES ABOVE IN PRODUCTION!<br> -ANY PRODUCTION KEYS SHOULD BE GENERATED BY THE ORGANIZATION AND BE 4096 BITS LONG.** - - -## RVI credentials format - -A credential is a JWT-encoded JSON structure, signed by the root X.509 -certificate's private key, describing the rights that the sender -has. A received RVI credential is validated as follows. - -1. **Receive remote party's X.509 device certificate**<br> -The TLS handshake process will exchange the X.509 certificates setup in -the previous chapter. - -2. **Validate remote party's X.509 device certificate**<br> -The received device X.509 certificate has its signature validated by the -root X.509 certificate that is pre-provisioned in all RVI nodes.<br> -The receiver now knows that the remote RVI node has an identiy -generated by a trusted provsioning server using the private root key. - -3. **Receive one or more RVI credentials**<br> -Each credential is encoded as JWT, signed by the root X.509 certificate. - -4. **Validate each RVI credential signature**<br> -The root X.509 certificate is used to validate the signature of each -received RVI credential. <br> -A successful validation proves that the certificate was generated by a -trusted provisioning server using the private root key. - -5. **Validate the credential-embedded X.509 device certificate**<br> -Each received RVI credential will have its embedded device X.509 -certificate compared with the device X.509 certificate received in -step 1 above.<br> -A match proves that the certificate was generated by a trusted provisioning -server explictly for the RVI node at the remote end. - -An RVI credential has the following format in its native JSON state: - -```JSON -{ - "create_timestamp": 1439925416, - "right_to_invoke": [ - "jlr.com/vin/" - ], - "right_to_register": [ - "jlr.com/backend/sota" - ], - "id": "insecure_cert", - "iss": "jaguarlandrover.com", - "device_cert": "", - "validity": { - "start": 1420099200, - "stop": 1925020799 - } -} -``` - -<div class="pagebreak"></div> - -The members are as follows: - -Member | Description ---------------------|--------------------- -create\_timestamp | Unix timestamp of when the credential was created -right\_to\_invoke | A list of service prefixes that the sender has the right to invoke on any node that has registered matching services that start with the given string(s). -right\_to\_register | A list of services that the sender has the right to to register for other nodes to invoke. -id | A system-wide unique identifier for the credential. -iss | The issuing organization. -device_certificate | The PEM-encoded device X.509 certificate to match against the sender's TLS certificate. -validity.start | The Unix timestamps when the credential becomes active. -validity.stop | The Unix timestamps when the credential becomes inactive. - -## Generating RVI credentials - -To create a credential, tie it to a device X.509 certificate, and sign it with a root X.509 certificate private key, the following command is used: - - -```Shell -rvi_create_credential.py --cred_out="insecure_credential.json" \ - --jwt_out='insecure_credential.jwt' \ - --id="xxx" \ - --issuer="genivi.org" \ - --root_key=insecure_root_key.pem \ - --device_cert=insecure_device_cert.crt \ - --invoke='genivi.org/' \ - --register='genivi.org/' -``` - -The following command line parameters are accepted: - -Parameter | Required | Description --------------- | -------- | --------- ---cred\_out | No | Output file containing the JSON-formatted un-encoded credential. ---jwt\_out | Yes | JWT-encoded, JSON-formatted, root keyp-signed credential. ---issuer | Yes | Organization that issued the credential. ---root\_key | Yes | Private, PEM-encoded root key to sign the credential. Must be the same key used to sign the root X.509 certificate. ---device\_cert | Yes | The PEM-encoded device X.509 certificate to embed into the credential as the device_cert member. ---invoke | Yes | Space separated list (within quotes) of RVI service prefixes that the owner of the credential has the right to invoke. ---register | Yes | Space separated list (within quotes) of RVI service prefixes that the owner of the credential has the right to register for others to call (with the right credential). ---start | No | The Unix timestamps when the credential becomes active. ---stop | No | The Unix timestamps when the credential becomes inactive. - -The generated ```insecure_credential.json``` -and ```insecure_credential.jwt``` are checked into ```priv/credentials```. |