diff options
Diffstat (limited to 'doc/rvi_certificates.md')
-rw-r--r-- | doc/rvi_certificates.md | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/doc/rvi_certificates.md b/doc/rvi_certificates.md new file mode 100644 index 0000000..1d46259 --- /dev/null +++ b/doc/rvi_certificates.md @@ -0,0 +1,254 @@ +<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 +Attribution-ShareAlike 4.0 International. + +# CREATING RVI CERTIFICATES + +This document describes how to generate the necessary certificates, +keys and credentials needed for RVI Core. The example certificates +are used in (rvi_protocol.md)[rvi_protocol.md]. + +# STANDARDS USED +[1] JSON Web Token RFC7519- JWT (link)[https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32]<br> +[2] base64url - (link)[https://en.wikipedia.org/wiki/Base64)<br> +[3] Transport Layer Security (TLS) - (link)[https://en.wikipedia.org/wiki/Transport_Layer_Security]<br> +[4] X.509 Certificates - (link)[https://en.wikipedia.org/wiki/X.509]<br> + +For all examples below the following certificates 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="pb"></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. + +<div class="pb"></div> + +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----- +``` + +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/certificates``` 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.** + +<div class="pb"></div> + +## 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="pb"></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```. |