openlvc / portico

Portico is an open source, cross-platform, fully supported HLA RTI implementation. Designed with modularity and flexibility in mind, Portico is a production-grade RTI for the Simulation and Training Community, so come say hi!
http://www.porticoproject.org
151 stars 81 forks source link

Implement encryption configuration and infrastructure #241

Closed timpokorny closed 6 years ago

timpokorny commented 6 years ago

Summary

Add support for RID configuration options to enable and force the use of encryption.

These options will include values specifically for the RTI and LRCs.

RTI Configuration The RTI must have a number of configuration options to:

This task is focused on the infrastructure needed in the RTI and LRC to support encryption. We will put in place the components to parse, verify and configure the RTI and LRC to support the processing of encrypted messages without actually doing it.

All messages will pass through dummy encrypters which will log activity rather than encrypting anything. The subsequent tasks will implement the actual encryption and decryption (and any key exchange semantics necessary to support this).

Below is an example configuration:

# Is encryption support enabled or not?
rti.security.encryption = enabled | disabled | on | off | true | false

# Is encryption required to connect?
rti.security.allowUnencrypted = true | false

# Specify the support cipher list for session keys and key pairs
rti.security.pki.ciphers = ...
rti.security.sym.ciphers = ...

# Public and Private key files for either Federate or RTI
# If either is empty, the use of encryption will be disabled
rti.security.pki.public  = <empty> or ...KEY TEXT or ...KEY FILE...
rti.security.pki.private = <empty> or ...KEY TEXT or ...KEY FILE... 

# Class that handles authorization of federates on connection
rti.security.auth.handler = <class name>
rti.security.auth.permfile = ...PATH TO PERMISSIONS FILE...

LRC Configuration The LRC configuration has some slight differences, such as the exact specification of the ciphers to use rather than the list of those supported. An example configuration is below:

# Is encryption support enabled or not?
lrc.security.encryption = enabled | disabled | on | off | true | false

# Ciphers we will use for the shard and key pairs
lrc.security.pki.cipher = ...
lrc.security.sym.cipher = ...

# Public and Private key files for either Federate or RTI
# If either is empty, the use of encryption will be disabled
lrc.security.pki.public  = <empty> or ...KEY TEXT or ...KEY FILE...
lrc.security.pki.private = <empty> or ...KEY TEXT or ...KEY FILE... 

# Public and Private key files for either Federate or RTI
# If either is empty, the use of encryption will be disabled
portico.security.pki.public = ...KEY TEXT or FILE...
portico.security.pki.private = ...KEY TEXT or FILE... 

Acceptance Criteria

Once complete, Portico shall:

RTI

LRC

timpokorny commented 6 years ago

This work now complete and on the central RTI branch.

This work is now complete. The configuration has changed somewhat. Now on each connection you can specify whether public key encryption should be used, or plain old shared key. These configuration options are valid for all connections and can be added to the configuration for any of them. Example configuration from default RID below showing the options present (and disabled) on the Multicast and TCP connections in the RTI:

# (R.5) Multicast Connection Configuration
#
#  Transport: Signals that this is a multicast connection
#    Address: A valid multicast or broadcast group, or the symbolic name BROADCAST
#       Port: Any valid port number
#        NIC: The address or host name of the NIC we should use to send/receive traffic, or
#             one of the symbolic names from above (LOOPBACK, LINK_LOCAL, SITE_LOCAL, GLOBAL).
#
rti.network.multicast.transport = multicast
rti.network.multicast.address   = 239.1.2.3
rti.network.multicast.port      = 20913
rti.network.multicast.nic       = SITE_LOCAL

#rti.network.multicast.bundling = false
#rti.network.multicast.bundling.maxSize = 64K
#rti.network.multicast.bundling.maxTime = 30
#rti.network.multicast.flow.credits = 2M
#rti.network.multicast.flow.threshold = 0.4
#rti.network.multicast.frag.size = 60K

    # (R.5a) Public Key Authentication and Encryption
    #
    #        Federates connect to the RTI using PKI. The federate must have the
    #        RTI's public key on file locally. When connecting to the RTI and
    #        performing non-federation calls (Create, Destroy, Join, Resign, ...),
    #        the messages are encrypted with the RTIs public key. On connect, they
    #        also exchange keys, with return messages from the RTI encrypted using
    #        the federates public key. Once a federation is joined, the federate
    #        is given access to a federation-wide shared key and that is used instead.
    #        (Less CPU load and needed so federates can read each other's broadcasts).
    #
    #        NOTE: Only one of Public Key or Shared Key options can be enabled at once.
    #
    #          Enabled: Is encryption on or off?
    #         Enforced: Enforce that all connections use a public key. When set to false,
    #                   federates can connect even if they do not provide creds. Only used by RTI.
    #       PrivateKey: Points to the file containing the federate's private key (PEM format)
    #        RtiPublic: Points to the file containing the RTI public key (PEM format) Only used by LRC.
    #    SessionCipher: Cipher configuration for federation messages
    #    SessionKeylen: Bit-length of shared key for federation messages
    #      
    rti.network.multicast.publickey.enabled       = false
    rti.network.multicast.publickey.enforced      = false
    rti.network.multicast.publickey.privatekey    = ./id_rsa
    rti.network.multicast.publickey.rtipublic     = ./rti_public.pem
    rti.network.multicast.publickey.sessionCipher = AES/CFB/NoPadding
    rti.network.multicast.publickey.sessionKeylen = 128

    # (R.5b) Symmetric Encryption Settings
    #
    #        Let the connection make use of a shared-key for encryption
    #
    #        NOTE: Only one of Public Key or Shared Key options can be enabled at once.
    #
    #     Enabled: Is encryption on or off?
    #      Keylen: Bit-length of federation shared key. 128-bit is the default, higher values
    #              require the use of the Java unlimited strength policies (google it)
    #      Cipher: Cipher configuration string used in create Cipher. Only supports AES currently.
    #         Key: The pre-shared key. Must be the same on all ends
    #      
    rti.network.multicast.sharedkey.enabled  = false
    rti.network.multicast.sharedkey.keylen   = 128
    rti.network.multicast.sharedkey.cipher   = AES/CFB/NoPadding
    rti.network.multicast.sharedkey.key      = password

# (R.6) Unicast Network Connection
#
#  Transport: Signals that this is a TCP Server connection that will listen for clients
#       Port: The port number to listen on.
#        NIC: A valid host name or IP address used by the NIC we should use to receive connections,
#             or one of the symbolic names from above (LOOPBACK, LINK_LOCAL, SITE_LOCAL, GLOBAL).
#
rti.network.tcp.transport = tcp-server
rti.network.tcp.port      = 52295
rti.network.tcp.nic       = SITE_LOCAL

    # (R.6a) Public Key Authentication and Encryption
    #
    #        Federates connect to the RTI using PKI. The federate must have the
    #        RTI's public key on file locally. When connecting to the RTI and
    #        performing non-federation calls (Create, Destroy, Join, Resign, ...),
    #        the messages are encrypted with the RTIs public key. On connect, they
    #        also exchange keys, with return messages from the RTI encrypted using
    #        the federates public key. Once a federation is joined, the federate
    #        is given access to a federation-wide shared key and that is used instead.
    #        (Less CPU load and needed so federates can read each other's broadcasts).
    #
    #        NOTE: Only one of Public Key or Symmetric options can be enabled at once.
    #
    #          Enabled: Is encryption on or off?
    #         Enforced: Enforce that all connections use a public key. When set to false,
    #                   federates can connect even if they do not provide creds. Only used by RTI.
    #       PrivateKey: Points to the file containing the federate's private key (PEM format)
    #        RtiPublic: Points to the file containing the RTI public key (PEM format) Only used by LRC.
    #    SessionCipher: Cipher configuration for federation messages
    #    SessionKeylen: Bit-length of shared key for federation messages
    #      
    rti.network.tcp.publickey.enabled       = false
    rti.network.tcp.publickey.enforced      = false
    rti.network.tcp.publickey.privatekey    = ./id_rsa
    rti.network.tcp.publickey.rtipublic     = ./rti_public.pem
    rti.network.tcp.publickey.sessionCipher = AES/CFB/NoPadding
    rti.network.tcp.publickey.sessionKeylen = 128

    # (R.6b) Symmetric Encryption Settings
    #
    #        Let the connection make use of a shared-key for encryption
    #
    #        NOTE: Only one of Public Key or Symmetric options can be enabled at once.
    #
    #     Enabled: Is encryption on or off?
    #      Keylen: Bit-length of federation shared key. 128-bit is the default, higher values
    #              require the use of the Java unlimited strength policies (google it)
    #      Cipher: Cipher configuration string used in create Cipher. Only supports AES currently.
    #         Key: The pre-shared key. Must be the same on all ends
    #      
    rti.network.tcp.sharedkey.enabled  = false
    rti.network.tcp.sharedkey.keylen   = 128
    rti.network.tcp.sharedkey.cipher   = AES/CFB/NoPadding
    rti.network.tcp.sharedkey.key      = password