Why do we need a $gtmcrypt_config file?

GT.M ships with a reference implementation of an encryption plugin which uses OpenSSL and GnuPG to perform various operations for Database Encryption, File Encryption, TLS replication and/or TLS-enabled sockets. The environment variable $gtmcrypt_config points to the configuration file that GT.M uses to set certain OpenSSL options. This configuration file must be in the structure of a libconfig configuration file. For more information on the structure of a libconfig configuration file, refer to http://hyperrealm.github.io/libconfig/libconfig_manual.html#Configuration-Files.

GT.M Database Encryption, File Encryption, TLS replication, and TLS sockets are not prerequisites for each other. You can use these GT.M features together or selectively in your environment depending on the $gtmcrypt_config file for a given process.

The configuration file, pointed to by $gtmcrypt_config, is divided into five major sections:

The $gtmcrypt_config file does not need to include all sections. For example, if a GT.M application only uses TLS replication and/or TLS sockets, it does not need to include sections for Database, Files or Plugin.

Configuration File Version 2

The configuration file version does not need to be the first item in the entire configuration. However, placing it at the top of the file makes for simplicity and understanding Prior to version, 2 configuration files were not explicitly versioned. When no version is present, the plugin treats the file version as 1. Configuration files using the "plugins" section must be version 2 or higher.

A version 2 configuration file is backwards compatible provided keys protected by GnuPG are configured and present on disk. If this section is missing, the plugin treats the configuration as version 1.

Plugins Configuration

Version 2 of the reference plugin supports the "openssl-pkcs8" plugin configuration using OpenSSL. This section, if enabled, defines an RSA private and public key/certificate that encrypt database encryption keys and file encryption keys. The format of these sections follows the format described for Database Encryption and File Encryption below. Those configurations are nested inside the plugin's definition to signify those keys are encrypted with the RSA private key.

The plugin section uses "openssl" in the name because it uses functionality from OpenSSL for encryption.

FIS recommends following your corporate procedures for generating and/or acquiring the RSA key.

File Encryption

The files section defines keys that MUMPS applications use to perform file encryption. It can exist as a global configuration used by GnuPG or as a subsection of the "openssl-pkcs8" plugin configuration.

MUMPS applications reference these keys by their name. These names must be unique among encryption keys inside the configuration file. This section serves to define GnuPG operation in a way compatible with version 1.

TLS

The tls section contains information such as the location of the root certificate authority, leaf-level certificates with the corresponding private key files, and other TLS configuration options. Under the tls section, you can use the same tlsid or separate tlsids (with a different set of certificates and options) for TLS replication and TLS sockets depending on what establishes appropriate security for your application.

Database Key Management

Section ordering

GT.M parses the "plugins" section after the GnuPG configuration. One must disable any "plugins" subsections to use the GnuPG configuration.

Adding New Database Keys

In the example below, new database keys are appended to the database-to-key entries. GT.M searches those entries for a match of the database file name as well as the hash in the database file header. If there is no match for either, GT.M produces an configuraton error.

When creating database files for the first time, MUPIP CREATE uses the last key in the list. When working with new databases using existing configuration files take care to order the keys in the desired order for the circumstances.

Command To Convert From GnuPG to OpenSSL

Each GnuPG protected key can be decrypted and piped to OpenSSL to encrypt with the RSA public key. In the example below, one must input the password for the GnuPG keyring.

  gpg --homedir=$GNUPGHOME --pinentry-mode=ask --decrypt /path/to/database/key/dbONE.key | \
    openssl pkeyutl -certin -inkey /path/to/key/one.crt -out /path/to/database/key/pkcs8dbONE.key  \
        -pkeyopt rsa_padding_mode:pkcs1 -encrypt

Each RSA protected database key file generated like this will need an entry in the "database" subsection of the "openssl-pkcs8" plugin configuration.

Annotated Example Configuration

[Note] Note

Each user or role will need a role specific configuration file and keys.

/* Default is 1 which disables "plugins" section parsing */
version: 2;
/* Database Encryption Section
 * GT.M processes lookup database symmetric key file paths using both database file paths and the symmetric key
 * hash value in the database file header. To support re-keying, a database file may have multiple keys
 * associated with it.
 * This top-level Database section implicitly provides the (default) GnuPG configuration.
 */
database: {
    keys: (
    {    /* Database file ONE */
        dat: "/path/to/database/file/dbONE.dat";    /* Encrypted database file */
        key: "/path/to/database/key/dbONE.key";     /* Encrypted symmetric key */
    },
    {    /* Database file TWO */
        dat: "/path/to/database/file/dbTWO.dat";
        key: "/path/to/database/key/dbTWO.key";
    },
    {    /* Database file ONE using a new key. Note the DB name remains the same */
        dat: "/path/to/database/file/dbONE.dat";
        key: "/path/to/database/key/dbONEnew.key";
    }
    /* Append new database symmetric keys to the end of this list */
    /* "dat:" entries are searched from the last to the first entry for matching keys in the file header */
    ...
    );
}
/* File Encryption Section
 * MUMPS applications reference file encryption keys by the name.
 * Each name is unique in the configuration. One name cannot refer to more than one key.
 * This top-level Files section implicitly belongs to the (default) GnuPG plugin configuration.
 */
files:    {
    name1: "/path/to/symmetric/key1";
    name2: "/path/to/symmetric/key2";
};
/* GT.M Encryption Reference Plugin support
 * To use RSA keys for database key encryption, set the configuration version to 2
 * and create a plugin entry that includes database keys and (if needed) MUMPS file encryption keys.
 */
plugins: {
    /* When using "openssl-pkcs8", only one RSA key encrypts keys. This could be a corporate issued key+certificate
     * that shares a common root CA. With this setup, users can share database encryption keys. Without the common
     * CA, users would fail to verify other users when attempting to share the encrypted database symmetric key.
     */
    openssl-pkcs8:    {
        enabled:    1;        /* Disabled by default */
        format:        "PEM";        /* Currently only PEM format is supported */
        key:        "/path/to/key/one.key";
        cert:        "/path/to/key/one.crt";
        /* The following parameters may be used in a future release. Please refer to the guidance in the TLS section */
        CAfile: "/path/to/tls/certs/CA/CA.crt";
        CApath: "/path/to/tls/certs/CA/";
        /* This section follows the guidelines of the top level "Files" section. This plugin specific Files section
         * belongs to this configuration. These keys are encrypted using this plugin's key
         * Key paths must be distinct from keys used by other plugins
         */
         files:    {
             pkcs8name1: "/path/to/symmetric/pkcs8key1";
             pkcs8name2: "/path/to/symmetric/pkcs8key2";
         };
        /* This section follows the guidelines of the top level "Database" section. This plugin specific Database
         * section belongs to this configuration. These keys are encrypted using this plugin's key
         * Key paths must be distinct from keys used by other plugins
         */
         database: {
            keys: (
            {    /* Database file ONE */
                 dat: "/path/to/database/file/dbONE.dat";
                 key: "/path/to/database/key/pkcs8dbONE.key";
            },
            {    /* Database file TWO */
                 dat: "/path/to/database/file/dbTWO.dat";
                 key: "/path/to/database/key/pkcs8dbTWO.key";
            },
            {    /* Database file ONE using a new key. Note the DB name remains the same */
                 dat: "/path/to/database/file/dbONE.dat";
                 key: "/path/to/database/key/pkcs8dbONEnew.key";
            }
             /* Append new database symmetric keys to the end of this list */
             /* "dat:" entries are searched from the last to the first entry for matching keys in the file header */
             ...
            );
         };
    };
};
/* TLS section */
tls: {
    /* Certificate Authority (CA) verify depth provides an upper limit on the number of CAs to look up for verifying a given
     * certificate. The depth count is described as ''level 0:peer certificate'', ''level 1: CA certificate'',
     * ''level 2: higher level CA certificate'', and so on. The default verification depth is 9.
     */
    verify-depth: 7;
 
    /* CAfile: points to a file, in PEM format, describing the trusted CAs. The file can contain several CA certificates identified by:
     * -----BEGIN CERTIFICATE-----
     * ... (CA certificate in base64 encoding) ...
     * -----END CERTIFICATE-----
     * sequences.
     */
    CAfile: "/path/to/tls/certs/CA/CA.crt";
 
    /* CApath: points to a directory containing CA certificates in PEM format. The files each contain one CA certificate.
      * The plugin looks up files, which must be available, by the CA subject name hash value.
      * If more than one certificate with the same name hash value exists, the extension must be different (e.g. 9d66eef0.0, 9d66eef0.1 etc). 
     * The directory is typically created by the OpenSSL tool 'c_rehash'.
     */
    CApath: "/path/to/tls/certs/CA/";
    /* crl: points to a file containing list of revoked certificates. Create this file with the openssl utility. */
    crl: "/path/to/tls/revocation.crl";
 
    /* Timeout (in seconds) for a given session.
     * If a connection disconnects and resumes within this time interval,
     * TLS reuses the session to speed up the TLS handshake. 
     * A value of 0 forces sessions to not be reused. 
     * The default value is 1 hour.
     */
    session-timeout: 600;
    /* ssl-options: specifies OpenSSL options to be set or cleared. By default the TLS plugin uses the following ssl-options,
     * which disables SSLv2, SSLv3, TLSv1 and TLSv1.1
     *    ssl-options: "SSL_OP_NO_SSLv2:SSL_OP_NO_SSLv3:SSL_OP_NO_TLSv1:SSL_OP_NO_TLSv1_1";  // Default
     * Enable SSLv3/TLSv1 by doing the following. Note the use of '!' preceding the options inverts their application
     *    ssl-options: "SSL_OP_NO_SSLv2:!SSL_OP_NO_SSLv3:!SSL_OP_NO_TLSv1:SSL_OP_NO_TLSv1_1";
     *
     * WARNING: Even if the configuration is changed to support SSLv3/TLSv1, OpenSSL may have been compiled to not support
     * SSLv3/TLSv1 or additional changes are needed to OpenSSL's configuration to allow SSLv3/TLSv1
     */
  
    /* cipher-list: List of acceptable TLS ciphers
     * NOTE: The naming scheme changed as of TLSv1.3
     * pre-TLSv1.3 ciphers default if not specified for TLSv1.2 and before
     *    cipher-list: "ALL:!ADH:!LOW:!EXP:!MD5:!DH:@STRENGTH";
     * TLSv1.3 ciphers
     *    cipher-list: "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384";
     */
  
    /* verify-mode: Verification mode
     * - SSL_VERIFY_NONE does no verification of certificates
     * - SSL_VERIFY_PEER (default) performs verification of all certificates
     * - SSL_VERIFY_POST_HANDSHAKE TLSv1.3 specific verifies certificates after handshake
     *    verify-mode: "SSL_VERIFY_PEER"
     
  
    /* Enable post-handshake fallback for clients that do not support PHA when using TLSv1.3
     *    post-handshake-fallback: 1;
     */
  
    /* List of alphanumeric TLS configuration identifiers (the "tlsid" used by GT.M processes) which must begin with a letter.
     * Each configuration consists of name/value pairs for specific options like certificate, key and format. "tlsid" specific
     * configuration options override global "tls" scope options.
     * These tlsids can be used for GT.M Database Replication and for TLS SOCKET devices used by application logic.
     */
    PRODUCTION: {        /* "PRODUCTION" is the "tlsid" name */
        /*  Format of the certificate and private key pair. Currently, the GT.M TLS plug-in only supports PEM format. */
        format: "PEM";
        /*  Path to the certificate. */
        cert: "/path/to/tls/certs/Malvern.crt";
        /* Path to the private key. If the private key is protected by a passphrase, an obfuscated version of the password
         * should be specified in the environment variable which takes the form gtmtls_passwd_<identifier>. For instance,
         * for the below key, the environment variable should be 'gtmtls_passwd_PRODUCTION'.
         * Currently, the GT.M TLS plug-in only supports RSA private keys.
         */
        key: "/path/to/tls/certs/Malvern.key";
    };
    DEVELOPMENT: {        /* "DEVELOPMENT" is the "tlsid" name */
        format: "PEM";
        cert: "/path/to/tls/certs/BrynMawr.crt";
        key: "/path/to/tls/certs/BrynMawr.key";
    };
};

As this $gtmcrypt_config file contains database, file, plugin and tls sections, you need to set the gtm_passwd and gtmtls_passwd_<tlsid> environment variables conforming to the maskpass utility's output. For more information on these environment variables, refer to "Environment Variables".