Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.
GT.M™ is a trademark of Fidelity Information Services, Inc. Other trademarks are the property of their respective owners.
This document contains a description of GT.M and the operating instructions pertaining to the various functions that comprise the system. This document does not contain any commitment of FIS. FIS believes the information in this publication is accurate as of its publication date; such information is subject to change without notice. FIS is not responsible for any errors or defects.
|
Version |
Date |
Summary |
|---|---|---|
|
1.0 |
August 7, 2009 |
First published version |
|
GT.M Group Fidelity National Information Services, Inc. 2 West Liberty Boulevard, Suite 300 Malvern, Pennsylvania 19355 United States of America |
GT.M Support for customers: +1 (610) 578-4226 / gtmsupport@fnis.com
Switchboard: +1 (610) 296-8877 Website: http://fis-gtm.com |
Effective V5.3-004, GT.M on selected platforms can encrypt data in database and journal files. Encryption protects against unauthorized access to data by an unauthorized process that is able to access disk files, that is, it protects data at rest (DAR).
A plug-in architecture allows you to use your choice of encryption package. The characteristics of encryption are entirely determined by the package you choose – for example, GT.M implements no "back doors" or "key recovery", and if you want such functionality, you need to choose or construct an encryption package that provides the features you want.
GT.M is distributed with the source and object code for the reference implementation of a plug-in that uses popular, widely available, encryption libraries. You can use it to implement your own plug-in. If the reference implementation plug-in meets your needs, you are welcome to use it as distributed, but please read and understand the Disclaimer, below.
In the reference implementation, GT.M uses a symmetric cipher to encrypt data. The reference implementation encrypts the key for the symmetric cipher with an asymmetric cipher using public and private keys. The private keys are stored in a key ring on disk locked with a password (or passphrase – the terms are used interchangeably).
Database encryption is only useful as one component of a comprehensive security plan and is insufficient as the sole means of securing data. The use of database encryption should follow from a good security plan. This document describes implementing encrypted GT.M databases; it does not discuss security plans.
Proper security protocol never places an unencrypted password, even in obfuscated form and/or in an obscure location, on disk. With GT.M database encryption, unencrypted passwords exist in the address space of processes accessing the database, which means that unencrypted passwords can theoretically be written to swap files when process memory is paged out. To be secure, an installation must handle this by means such as: using encrypted swap devices or files, ensuring that GT.M processes are not paged out, or some other means ensuring information in swap files is available only to the running process. In other words, even with respect to encryption, GT.M encryption is only part of a complete security infrastructure.
Our expertise is in GT.M, not in encryption. Encryption needs vary. Furthermore, the use of encryption may be restricted – or required – by regulations applicable to your location and circumstances. Therefore, our approach is to create a plug-in architecture where you can choose your preferred encryption software. In the course of development, we tested it primarily with GNU Privacy Guard, the widely available implementation of Pretty Good Privacy (see "PGP: Pretty Good Privacy" by Simson Garfinkel). Ensure that you have confidence in (and confidence in the support for) whichever encryption software you choose, because failure of the encryption software is likely to leave your data unrecoverable. GT.M itself performs no encryption, and encryption is performed exclusively by software that you install and configure. FIS neither endorses nor supports any specific encryption algorithm or library.
Furthermore, just as GT.M allows for the use of your choice of encryption libraries, encryption libraries in turn require keys that must be managed. In its simplest form, key management requires both that only those who need a key have that key, and also that keys are not lost. Key management is two steps removed from GT.M's implementation of database encryption, but is important to the successful use of encrypted databases. It must be part of your operations policies and procedures. FIS strongly recommends that you understand in detail how to implement the infrastructure for whichever specific encryption you choose.
Elements of your security infrastructure need to manage issues discussed in the following sections.
GT.M database encryption is designed to protect data at rest. Applications execute business logic to manipulate and produce unencrypted data. Unencrypted data must exist within application processes, and can be accessed by any process with access rights to the virtual address space of a process containing unencrypted data. Also, data in transit between systems and between processes is not protected by GT.M database encryption.
A database file has an extended life. In typical operation, only a minuscule fraction of the data within a database changes each day. As changing an encryption key requires re-encrypting all the data, this means encryption keys for files have long lives. Since long-lived keys are security risks – for example, they cannot be changed when an employee leaves – key management must therefore be part of the overall security plan. At a minimum, long lived keys require two stage key management – a database key with a long life, not normally accessed by a human, stored in a form encrypted by another key that can be changed more easily.
Furthermore, a key must be retained at least as long as any backup encrypted with that key; otherwise the backup becomes useless. You must have appropriate procedures to retain and manage old keys. Since successful data recovery requires both keys and algorithms, the retention processes must also preserve the encryption algorithm.
Database and journal files are large (GB to hundreds of GB). This large volume makes database encryption more amenable to attack than a small encrypted message because having many samples of encrypted material makes it easier to break a key.
FIS neither endorses nor supports any specific encryption algorithm.
The selection of an encryption algorithm is determined by many factors, including but not limited to, organizational preferences, legal requirements, industry standards, computational performance, robustness, the availability of encryption hardware, etc. No algorithm meets all needs.
Therefore, GT.M provides a "plug-in" architecture for encryption algorithms, which allows you to integrate your preferred encryption software with GT.M. In the GT.M development environment, we created variations on a reference implementation using popular encryption packages for our validation. We tested each reference implementation variation on at least one computing platform, and one reference implementation variation on each computing platform. This document lists which encryption package we tested on which platform.
You take all responsibility for the selection and use of a specific encryption package. Please be aware that:
All encryption libraries that run within the address space of a GT.M process must conform to the rules of any functions for GT.M, as documented, including but not limited to being single threaded, not altering GT.M's signal handlers, restricting the use of timers to the API provided by GT.M, etc. 2
Malfunction of encryption software or hardware can render your data irrecoverable. As part of your comprehensive organizational risk management strategy, please consider the use of logical multi-site application configurations, possibly with different encryption packages and different encryption keys.
The cipher used for database encryption must not change the length of the encrypted sequence of bytes. In other words, if the cleartext string is n bytes, the encrypted string must also be n bytes.
The reference implementation of GT.M database encryption has no "back door" or other means to recover lost keys. We are also not aware of back doors in any of the packages used by the reference implementation.
Lost keys make your data indistinguishable from random ones and zeros. While FIS recommends implementing a documented key management process including techniques such as key escrow, ultimately, you take all responsibility for managing your keys.
At some point in the process invocation chain, the reference implementation requires a human being to provide a password that can be placed (in obfuscated form) in the process environment where child processes can inherit it. If you want to be able to access encrypted databases without any human interaction, you must modify the reference implementation, or create your own implementation.
For example, if you have a GT.M based application server process that is started by xinetd in response to an incoming connection request from a client, you may want to consider an approach where the client sends in a key that is used to extract an encrypted password for the master key ring from the local disk, obfuscates it, and places it in the environment of the server process started by xinetd. If the application protocol cannot be modified to allow the client to provide an additional password, xinetd can be started with the $gtm_passwd obfuscated password in its environment, and the xinetd passenv parameter used to pass $gtm_passwd from the xinetd process to the spawned server process.
GT.M database encryption is only supported for the Buffered Global (BG) access method. It is not supported for the Mapped Memory (MM) access method. See Alternatives to Database Encryption, below, for other options.
On some platforms, you may be able to use disk drives with built-in encryption, or encrypted file systems to protect data at rest. These may or may not be as secure as GT.M database encryption: for example, once an encrypted file system is mounted, files thereon can be accessed by any process that has appropriate permissions; with GT.M database encryption each process accessing a database file must individually have access to the keys for that database file.
The built-in interface to encryption is implemented only for data in database, journal, backup and certain formats of extract files. To encrypt IO (say for sequential disk files), you can use IO to PIPE devices. Alternatively, you can call encryption routines from GT.M using the external call interface.
GT.M encrypts neither the replication stream nor GT.CM (GNP/OMI) network traffic. When needed, there are excellent third party products for implementing secure TCP/IP connections: software solutions as well as hardware solutions such as encrypting routers.
As with any GT.M process that accesses databases, the Update Process, helper processes and GT.CM server all require provisioning with keys to enable their access to encrypted databases.
When a GT.CM server has a key for an encrypted database, any client connecting to the server can access encrypted records in that database.
This section describes the operation of GT.M database encryption with the reference implementation. A subsequent section describes the functions of the reference implementation which can be reworked or rewritten to use different encryption packages.
|
Terms |
Description |
|---|---|
|
Cipher |
An encryption algorithm or the implementation of an encryption algorithm, for example, the symmetric cipher AES 256 CFB. |
|
Hash |
A signature algorithmically derived from an object which is guaranteed, or certain to a very impressive probability, to uniquely identify the object within a set of similar objects. |
|
Key length |
The number of bits comprising a key. Longer key lengths may result in stronger encryption (more difficult to break) but require more computation. |
|
Key management |
The generation, distribution, and access of keys. The reference implementation of database encryption uses:
|
|
Master key file |
This file contains pairs of entries indicating which symmetric key is used to encrypt/decrypt database records. Database records can be found in database, journal, extract and backup files. |
|
Obfuscation |
A technique used to make data difficult to discern on casual observation. A common example is "pig Latin". Since the password used for the private key in the reference implementation must exist in the process' environment, GT.M obfuscates it to reduce the chance that visual access to process information (say during debugging) inadvertently exposes the password. |
|
Password (or Passphrase) |
A secret word or phrase used in the reference implementation to protect a private key on disk (the password should never be on disk in the clear). |
|
Public key / Private key (or Asymmetric keys) |
A pair of keys used so what one key encrypts the other can decrypt. The private key is sometimes referred to as the "secret" key (because it is not shared as opposed to the public key which is; the private key should never be on disk in the clear). In the reference implementation, asymmetric keys are used to encrypt the symmetric database key. This allows a master to encrypt a symmetric database key with a user’s public key (so only the user can decrypt it with their private key). Encryption using a public key / private key pair is referred to as "public key encryption". The reference implementation uses GNU Privacy Guard with associated libraries libgpgme and libgpg-error for asymmetric key encryption. |
|
Symmetric key |
The same key used to both encrypt and decrypt. Symmetric ciphers are faster than asymmetric ciphers. Encryption using a symmetric key is referred to as "symmetric key encryption". Depending on the platform, the reference implementation uses either GNU Privacy Guard's libgcrypt, or libcrypto from OpenSSL, for symmetric key encryption. |
GT.M implements database encryption with a plug-in architecture that allows for your choice of cipher. Any code statically or dynamically linked in to a GT.M process must meet the requirements of code used for external calls. The GT.M distribution includes a reference implementation that interfaces to several common packages and libraries. You are free to use the reference implementations as is, but remember that the choice of cipher and package is yours, and FIS neither recommends nor supports any specific package.
Note: In any given instance, you must use the same encryption libraries for all databases accessed by the processes of an application instance, but each database file can have its own key. Of course, all processes accessing a database or journal file must use the same encryption algorithm and key.
A GT.M database file contains several parts (details are in the GT.M Administration and Operations Guide):
A file header containing information pertaining to the database file itself.
Global and local bit maps, which together specify which blocks in the file are in use and which blocks are free.
Data blocks containing the actual data, as well as index blocks containing structural information providing paths to the actual data (there is a directory tree, and one or more global variable trees). Each data or index block consists of a block header, and one or more data records.
In an encrypted database, GT.M encrypts only the index and data records in a database. The file header, bit maps, and block headers are not encrypted, i.e., information relating to database structure is not encrypted. This means some system administration operations such as turning journaling on and off, do not require the encryption key for a database file. Others, such as MUPIP EXTRACT, do.
Journal files contain data records, such as before image records, update records, and after image records, as well as structural information such as transaction markers, process records, etc. Again, only records that contain data – before image records, update records and after image records – are encrypted. Records that contain structural information remain in cleartext.
Records subject to encryption are collectively referred to herein as data records.
For performance, a symmetric cipher is used to encrypt and decrypt data records. Asymmetric ciphers are used by the reference implementation to secure the symmetric cipher keys stored on disk. A password is used to secure the private key which is stored on a key ring on disk. The following illustration is an overview of GT.M database encryption in the reference implementation using GNU Privacy Guard (GPG) to provide the ciphers.
In the reference implementation, a password protected key ring on disk contains the private key of the asymmetric cipher. A password is required to access the key ring on disk and obtain the private key. Password acquisition happens in one of three ways:
When the environment variable $gtm_passwd is not set, before a GT.M mumps process needs to open an encrypted database file, the application calls a program such as GETPASS.m to prompt for and obtain a password for the key ring on disk.
When the environment variable $gtm_passwd is set to the null string, at process startup, GT.M implicitly calls the program GETPASS.m to prompt for and obtain a password. The environment variable, $gtm_passwd is then set to an obfuscated version of the password required to unlock the key ring on disk.
The environment variable $gtm_passwd contains an obfuscated version of the password required to unlock the key ring on disk to obtain the private key. The environment variable can be passed in to GT.M, or it can be prompted for and set, as described below.
Some graphical user interfaces, e.g., GNOME or KDE, may detect when you are being prompted for the GPG keyring password and use a graphical interface instead of the terminal interface. You may be able to disable this behavior if you unset the $DISPLAY environment variable, or use an ssh connection to localhost that disables X forwarding. Consult your graphical user interface documentation.
In order to enable the Job command, the password for the key ring on disk exists in the environment of the process in environment variable $gtm_passwd where it can be passed from a parent process to a child. In order to prevent inadvertent disclosure of the password, for example, in a dump of the environment submitted to FIS for product support purposes, the password in the environment is obfuscated using information available to processes on the system on which the process is running, but not available on other systems.
$gtm_passwd is the only way for a child process to receive a password from a parent. In the event that the parent process does not pass $gtm_passwd to the child, or passes an incorrect password, there is little a child without access to an input device can do except log an error and terminate.
An obfuscated password in the environment is the only way that other GT.M processes (MUPIP and DSE) can be provided with a password. If they encounter an encrypted database or journal file, and do not have an obfuscated password to the key ring on disk in the environment, they terminate with the error message "GTM-E-CRYPTINIT, Error initializing encryption library. Environment variable gtm_passwd set to empty string. Password prompting not allowed for utilities" . There are (at least) two ways to provide MUPIP and DSE processes with obfuscated passwords in $gtm_passwd:
maskpass is a stand-alone program that prompts the user for the password to the key ring on disk, and returns an obfuscated password to which $gtm_passwd can be set. The environment variable $gtm_passwd should be not set, set to a null value, or set to a value produced by maskpass. Setting $gtm_passwd to an incorrect non-null value without using maskpass could result in undefined behavior of the encryption library. You can use maskpass in shell scripts. For example:
$ $gtm_dist/plugin/gtmcrypt/maskpass
Enter Password: 3D303E34213F
$ echo -n "Enter Password: ";export gtm_passwd=`$gtm_dist/plugin/gtmcrypt/maskpass|cut -f 3 -d " "`
Enter Password:
$ echo $gtm_passwd
3D303E34213F
$
Create a one line GT.M program as follows:
zcmd ZSYstem $ZCMdline Quit
and use it invoke the MUPIP or DSE command. For example:
$ gtm_passwd="" mumps -run zcmd mupip backup -region \"*\"
The empty string value of $gtm_passwd causes the MUMPS process to prompt for and set an obfuscated password in its environment which it then passes to the MUPIP program. Shell quote processing requires the use of escapes to pass the quotes from the ZSYstem command to the shell.
The following schematic illustrates acquisition of the password for the key ring on disk. Note that an error (for example from the entry of an incorrect password) may not be triggered immediately – for example, DSE does not need an encryption key until you attempt to access data (since the file header is not encrypted, access to it does not need a key).
The reference implementation uses a master key file for each user to obtain the symmetric keys for each database or journal file. The environment variable $gtm_dbkeys specifies the master key file. If $gtm_dbkeys points to a file, it is the master key file. If it points to a directory, the file .gtm_dbkeys in that directory is the master key file (that is: $gtm_dbkeys/.gtm_dbkeys). If the environment variable is not defined, the functions look for a key file ~/.gtm_dbkeys (i.e., in the home directory of the process' userid). The master key file contains sections as follows:
dat database_filename
key key_filename
where database_filename is the name of a database file, for example, /var/xyzapp/gbls/accounts.dat and key_filename is the name of a key file containing a symmetric key encrypted with a public key, for example: /home/sylvia/dbkeys/accounts.key. Note: even though UNIX permits spaces and linefeed characters in filenames, GT.M does not permit them in database file names; hence, this format does not place any additional restrictions on database file names.
Key files are text files which can even be faxed or e-mailed: since they are secured with asymmetric encryption, you can transmit them over an insecure channel. As discussed below, the same database_filename can occur multiple times in a master key file.
For each key_filename, the GT.M process (mumps, MUPIP or dse) builds a memory key ring from the key ring on disk and the master key file. The memory key ring contains a list of elements where each element consists of a filename, a symmetric cipher key, and a cryptographic hash of that symmetric cipher key. Using the private key obtained from the key ring on disk, GT.M obtains the symmetric keys from key files pointed to by the master key file.
Database and journal file headers include a cryptographic hash of the encryption key and algorithm used for that file. When opening a file, GT.M uses the key in the memory key ring whose hash matches that in the header – the database_filename in the key ring is ignored. Older keys need not be deleted until they are no longer required (for example, an older key may be required to access a restored backup copy of a database). Permitting the same database_filename to occur multiple times in a master key file also enables one master key file to be used for multiple instances of an application. This ensures that the correct key for a file is always used, even if the file has been renamed, copied from another location, etc. – the correct key must of course be available in the memory key ring; if no such key exists, GT.M triggers a CRYPTKEYFETCHFAILED error.
Only for MUPIP CREATE does GT.M rely on the database_filename in the key ring. MUPIP CREATE computes the cryptographic hash for the correct key to place in the database file header. If the same database_filename occurs more than once in the master key file (and hence in the memory key ring), MUPIP CREATE uses the key_filename associated with the last occurrence of that database_filename in the master key file.
This is illustrated by the picture below.
As discussed earlier, a process uses that key in its memory key ring whose hash matches the hash in the database or journal file header: the file name is not checked. MUPIP CREATE computes the hash value for the key at database creation time, and writes it to the database file header. When GT.M creates a new journal file for an encrypted database file, it copies the hash from the database file header into the journal file header. Similarly, MUPIP EXTRACT -FORMAT=BINARY, places the database file hash in the extract, which is encrypted; indeed, since an extract can come from multiple database files, extract places the hash from the file header of each encrypted database in the extract. When processing each section in the extract, MUPIP LOAD uses that key in its memory key ring that matches the hash for that section.
On disk, database and journal files are always encrypted – GT.M never writes unencrypted data to an encrypted database or journal file. GT.M uses decryption when reading data records from disk, and encryption when it writes data records to disk.
With encrypted databases, the number of global buffers allocated is automatically doubled, for example, if the database file header specifies 2000 global buffers, when the file is opened, GT.M automatically allocates 4000 global buffers. Global buffers are used in pairs: one global buffer has a copy of the encrypted database block as it exists on disk and the other has a copy of the unencrypted version. There is no change to the size of the control structures (including lock space and journal buffers) in shared memory. So, when using encrypted databases, you need to adjust your calculations of memory and shared memory usage accordingly: for each open database file, the shared memory usage will increase by the number of global buffers times the block size. For example, if the block size of a database file is 4KB, with 2048 global buffers, and the shared memory segment for that database file occupies 9MB when unencrypted, it occupies 17MB when the file is encrypted. Depending on your operating system you may need to change system configuration and tuning parameters. Other than global buffers, there is no change to memory usage with encryption.
Encrypted databases consume additional CPU resources for encryption and decryption. Without detailed knowledge of the chosen algorithms, the application patterns and hardware configuration, it is not possible to predict whether this will be appreciable, and whether application throughput will be affected. As far as possible, FIS has attempted to engineer GT.M database encryption so that the additional CPU resources are consumed outside software critical sections. The intention is to minimize the impact of encryption on application throughput, at least on computer systems that are not starved of CPU resources. You should determine the actual impact of encryption on your application when it runs on your system, preferably using a test environment that exactly reflects your production environment.
The commands here are all line oriented to illustrate that they can be automated by being called from GT.M or from a shell script. For interactive use, there are many graphical user interfaces (GUIs) usable with GPG. Although these examples were generated on Linux, usage on other UNIX systems should be virtually identical.
This is an example of key management using GPG and the reference implementation.
In this example, Helen is the master and Phil is an ordinary user who needs to access an encrypted database and obtains the encryption key for the database file from Helen.
Helen creates a public-private key pair for authentication and encryption using the command: gpg –gen-key. GPG asks her for a password with which to protect her private key on disk, for example, something like "olde king-coal Wiped his 2feet". (If Helen already has a GPG key ring on disk, she has to enter the password for that key ring. It is also likely that Helen already has a public-private key pair, in which case she can skip this step.)
Helen exports her public key in an ASCII form using a command such as: gpg --armor --output helen.publickey.txt --export helen.keymaster@fnis.com. The output file helen.publickey.txt looks something like this and can be e-mailed or otherwise sent to Phil:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.9 (GNU/Linux)
mQGiBEQb+d8RBACtaK4HUrWOIc6lP5mkGmQN3qyZaYTHL/5qoG287TkMGdi6eypY
r7s0GcTAxaGfvd0tyy7cxdezodwYoe80vNGsUErxQpYyNIBtg6HEC9qaWdm7bQfo
0psoSaRCcyoMxhSE2N74L6003lzDyn9p2BHZJqlyIc+jXtV/AxqnLv4TMwCgklhy
... (in the interest of brevity, many lines are not shown here) ...
dN3v+iT6Mg9m4HVOtTagigKGA8bZivWj74VU5MFLv10HOtqS4w5bAUcZPmo4jSqg
/nocVn/1TH4CcexUIkBpaeDFcbquqtasZt8Pyb4e/L5R/f0fVxKwl5vj/ACfUGlH
Gto/QQBKTZevAvDMUKC+UbsAnjstZKhcoBpSeditl57NQUC9AveN
=Kzb8
-----END PGP PUBLIC KEY BLOCK-----
Helen can both create a key pair and export the public key using gen_keypair.ksh, a sample Korn shell script provided in the reference implementation:
$ $gtm_dist/plugin/gtmcrypt/gen_keypair.ksh helen.keymaster@fnis.com
Enter Password: (password entry here does not echo)
Key generation might take a few minutes...
GNUPGHOME=/home/helen/.gnupg
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 5 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 5u
$
Phil similarly creates a key pair, and sends the public key to Helen, who adds it to her key-ring. Phil's private key on disk is encrypted on disk by GPG using a password, say "i coulda danced a11~knighT". Phil and Helen can compare the fingerprint of Phil's public key over the telephone.
Phil imports Helen's public key into his GPG key-ring with a command such as gpg --import helen.publickey.txt. Phil and Helen can compare the fingerprint of Helen's public key over the telephone, with a command such as gpg --fingerprint helen.keymaster@fnis.com whose output might look like this:
pub 1024D/82B38F62 2009-05-13
Key fingerprint = 80E0 5796 C2D9 9DBE F1CC 17FB 0FA2 45F4 82B3 8F62
uid Helen Keymaster <helen.keymaster@fnis.com>
sub 2048R/BB5AF816 2009-05-13
With later versions of gpg, import_and_sign_key.ksh, a sample Korn shell script provided in the reference implementation, can be used to both import the public key and sign it:
$gtm_dist/plugin/gtmcrypt/import_and_sign_key.ksh helen.publickey.txt helen.keymaster@fnis.com
Are you sure you want to import helen.publickey.txt (helen.keymaster@fnis.com) ? (y/n):y
gpg: key 5A3E1E34: public key "helen.keymaster <helen.keymaster@fnis.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
#########################################################
pub 1024D/5A3E1E34 2009-02-25
Key fingerprint = 4672 65A5 9C68 5F56 BF9E A81C 96EF B05C 5A3E 1E34
uid helen.keymaster <helen.keymaster@fnis.com>
sub 1024R/61706FE4 2009-02-25
#########################################################
Please confirm the validity of the the fingerprint before signing (y/n):y
Enter Password:
Successfully signed helen.publickey.txt (helen.keymaster@fnis.com).
Helen creates a password for the database file, ideally by using a random password generator. She keeps the actual password, like the legendary Coca Cola recipe, in some secure place. In this example, for readability, it is "mary Had_1_leg of Lamb_4_diner".
In practice, Helen would likely use a command such as gpg –gen-random, or the gen_sym_key.ksh Korn shell script provided in the reference implementation to generate a random key. It is probably easiest to temporarily store the key in a shell variable. gen_sym_key.ksh takes one command line parameter, an integer from 0 through 2, to specify the strength of the randomness in the key (0 is fast and appropriate for development and testing; 2 is more appropriate for production use).
$ accounts_key=`$gtm_dist/plugin/gtmcrypt/gen_sym_key.ksh 2`
$ echo $accounts_key
C1FF8BD4CD19C5C5961714A37DC80C847F824D38EA9FC87457C4E00E32C0053A
$
It is possible to exhaust the entropy in the system when generating a strong key, and you may have to perform other activities to generate entropy before key generation can complete, e.g.:
$ history_key=`$gtm_dist/plugin/gtmcrypt/gen_sym_key.ksh 2`
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 263 more bytes)
$ echo $history_key
2BBD7CBBC82461C66E9A417EF6A1F8F91E73EC933ECBB33DF9359B7ECC73099B
$
Helen now creates a text file containing the database password encrypted with Phil's public key using the command such as gpg --armor --encrypt --output dbpassword.tophiluser.txt --recipient phil.user@fnis.com. If she wishes, she can sign this with her private key so Phil can use her public key to confirm it came from her. She sends this text file, simulated below, to Phil (say, via e-mail):
3-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.9 (GNU/Linux)
hQEOA3VfP89PcoV1EAP9HiQGToIsRSCRJCN9yRhhXOSL8y2iSDMjDEvqpUKlCoPD
... (in the interest of brevity, many lines are not shown here) ...
l9iBHprwROcU1KY3LYS7ObtngSuie/sFLc4Sg8t4Qoi2C9HnUWnsWJb+A2Ju/Zwn
Erme/ArEJQ==
=MpQi
-----END PGP MESSAGE-----
Alternatively, the encrypt_db_key.ksh Korn shell script in the reference implementation creates an output file from a key placed in the environment by the gen_sym_key.ksh script shown above (note: on z/OS, owing to shell incompatibilities, the manual method described above should be used):
$ $gtm_dist/plugin/gtmcrypt/encrypt_db_key.ksh $accounts_key /tmp/accounts.key phil.user@fnis.com
$
Helen can send the binary key as an e-mail attachment to Phil. Notice that it is quite safe to put the accounts.key file on /tmp where it can be read by anyone, or to send it via an unsecured e-mail channel because it is encrypted with Phil's public key, and only Phil can decrypt the contents.
Using a text editor, Phil creates a file with a name like /home/phil/.gtm_dbkeys, with the encrypted key provided by Helen (assuming the database file is /var/profile/accounts.dat and Phil has saved the encrypted key provided by Helen in the file /home/phil/accounts.dat_keys). He sets the environment variable $gtm_dbkeys to point to the /home/phil/.gtm_dbkeys, which is shown below. Phil can now access the encrypted database at /var/profile/accounts.dat. For each additional database file, Helen creates an encryption key, encrypts it with Phil's public key and sends it to him. Phil creates a new section in /home/phil/.gtm_dbkeys for each such additional file.
dat /var/profile/accounts.dat
key /home/phil/accounts.dat_keys
/home/phil/accounts.dat_keys is the file Helen sent him:
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.9 (GNU/Linux)
hQEOA3VfP89PcoV1EAP9HiQGToIsRSCRJCN9yRhhXOSL8y2iSDMjDEvqpUKlCoPD
... (in the interest of brevity, many lines are not shown here) ...
l9iBHprwROcU1KY3LYS7ObtngSuie/sFLc4Sg8t4Qoi2C9HnUWnsWJb+A2Ju/Zwn
Erme/ArEJQ==
=MpQi
-----END PGP MESSAGE-----
Alternatively, Phil can save the key e-mailed by Helen as an attachment, and use the add_db_key.ksh Korn shell script in the reference implementation to add the section
$ $gtm_dist/plugin/gtmcrypt/add_db_key.ksh accounts.dat ~/accounts.key ~/db.keys
$ cat ~/db.keys
dat /var/profile/accounts.dat
key /home/phil/accounts.key
If Phil is the user creating the database file, when defining the database segment for the GT.M GDE utility, he flags the database as being encrypted via the GDE change –region –encryption qualifier. Phil sets the environment variable $gtm_passwd to the appropriate value of his obfuscated password using the maskpass program. He uses MUPIP CREATE to create the database file, at which point the database file header (and journal file header, if he uses journaling) contain the cryptographic hash of the symmetric encryption key.
Whenever Phil wishes to run GT.M application programs, he sets the environment variable $gtm_passwd to the appropriate value or to the null string (and is prompted for the password if the latter). The password is available to all descendant processes.
This is illustrated below:
Two more sample Korn shell scripts are provided. decrypt_db_key.ksh retrieves the clear text database key which can be encrypted with another person's public key to given them access to an encrypted database file. gen_sym_hash.ksh displays the hash for a particular key which can be matched against the hash in an encrypted database file to verify that this key is the correct one for the database file. Usage of the scripts is illustrated below:
$gtm_dist/plugin/gtmcrypt/decrypt_db_key.ksh my.key
Enter Password: gpg: encrypted with 2048-bit RSA key, ID 57F039CE, created 2009-06-16
"helen <helen.keymasterfnis.com>"
93520BA8276EA78081DBC059EA7DBC7A937414066B4ACB883F3F5F17C9473465
$gtm_dist/plugin/gtmcrypt/gen_sym_hash.ksh my.key
Enter Password:
22B5BA481E1579CAA5A68EF43F729ABED324205760A59C329ABD7888FB745E9B044C622E0ABFEBE8E731F5DDEF61909B190E8EEFC0BEF7D55E6959CB7008B485
GT.M database encryption comes with a reference implementation that should work "out of the box" with selected encryption packages. You can use this for your initial development and testing with GT.M database encryption. There are many encryption packages. As discussed earlier, FIS neither endorses nor supports any specific cipher or package. For your production use, you take responsibility for choosing, implementing and procuring support for your preferred package. Please remember that a malfunction in your chosen encryption package may result in unrecoverable data and FIS will be unable to help you.
The Plugin Architecture and Interface section below details the reference implementation, which is provided with full source code that you can freely modify for your own use.
For each platform on which GT.M supports encryption, the following table lists the encryption packages and versions against which FIS tested GT.M. Note that FIS tested GT.M for operation against these packages; FIS did not test the robustness of the encryption packages themselves.
|
OS (HW) |
libgpgme |
libgpg-error |
libgcrypt / libcrypto |
GPG |
|---|---|---|---|---|
|
Ubuntu 8.04 LTS (x86_64) |
1.1.5-2 |
1.4-2 |
libgcrypt 1.2.4-2 |
1.4.6-2 |
|
RHEL 5.3 (x86_64) |
1.1.4 |
1.4-2 |
libgcrypt 1.2.4-1 |
1.4.5-14 |
|
RHEL 4 .7 (x86) |
1.0.3 |
1.0.1 |
libgcrypt 1.2.0-3 |
1.2.6-9 |
|
RHEL 5 .3 (IA64) |
1.1.4 |
1.4-2 |
libgcrypt 1.2.3-1 |
1.4.5 |
|
z/OS (zSeries) |
1.1.8 |
1.7 |
libgcrypt 1.4.4 |
1.4.9 |
|
AIX 5.3 (pSeries) |
1.1.8 + fix |
1.7 |
libcrypto from openssl 0.9.8k |
1.4.9 |
|
Solaris 9 and 10 (SPARC) |
1.1.4 + fix |
1.6 |
libgcrypt 1.4.1 |
1.4.9 |
|
HP-UX 11.31 (IA64) |
1.1.8 + fix |
1.7 |
libgcrypt 1.4.1 |
1.4.9 |
Where the table lists a package version number followed by "+ fix" it means that in the process of testing, we identified issues with the package that we fixed. We are providing the source code for our fixes to the upstream package maintainers. If you have a support agreement with FIS, we will share that source code with you, upon request.
The reference implementation uses:
For public key encryption including the generation of public/private key pairs: RSA as implemented by GPG.
For the cryptographic hash: SHA-512.
For a programmatic interface to GPG: libgpgme.
To provide error messages for GPG: libgpg-error.
For symmetric encryption: AES 256 CFB implemented by libgcrypt on all platforms except AIX; Blowfish CFB implemented by libcrypto on AIX.
The reference implementation for AIX differs from other platforms because of certain limitations in libgcrypt as of the date of the initial release of GT.M database encryption as a consequence of the port of libgcrypt to the 64-bit environment being less mature than its port to the 32-bit environment (GT.M on AIX is a 64-bit application). Also, Blowfish is used because the implementation of AES on libcrypto from openssl requires data to be in chunks that are multiples of 16 bytes. It is possible that these limitations may no longer be an issue at such time when you consider AES on libgcrypt for your use. Nevertheless it serves to demonstrate that the plug-in architecture works with two different libraries. Note: this means that database files encrypted by the reference implementation are incompatible between AIX and other UNIX platforms.
The sample shell scripts in the reference implementation use the Korn shell (ksh) except on z/OS, where they use the standard shell (/bin/sh).
The normal GT.M installation script (invoked by sh ./configure executed as root or with sudo sh ./configure in the directory in which you have unpacked the GT.M distribution) will automatically install GT.M with the reference implementation plug-in.
You must also implement appropriate key management, including ensuring that users have appropriate values for $gtm_dbkeys.
The $gtm_dist/plugin directory is configured such that you can copy it to a location of your choice to customize your own encryption plug-in. After testing, simply replace the directory as distributed with your customized directory.
Utility programs written in M (such as %GO) run within mumps processes and behave like any other code written in M. Encryption keys are required if the mumps process accesses encrypted databases. A process running a utility program written in M that does not access encrypted databases (such as %RSEL) does not need encryption keys just to run the utility program.
Utility programs not written in M (e.g., MUPIP) that need access to encryption keys do not prompt for the password to the key ring on disk. They require the obfuscated password to be in the environment. You can use the maskpass program to set the password in the environment or a mumps wrapper process as discussed earlier to set the obfuscated password in the environment. In some cases, if a required key is not supplied, or if an incorrect key is specified, the utility program defers reporting the error at process start up in case subsequent actions don't require access to encrypted data, and instead reports it when first attempting an encryption or decryption operation.
Since they do not access application data at rest, the GDE and LKE uitlities do not need access to encryption keys to operate with encrypted databases.
MUPIP and DSE use the same plug-in architecture as mumps processes – gtmcrypt_init() to acquire keys, gtmcrypt_encode() to encode, etc.
Since the global directory file is never encrypted, GDE does not need access to encryption keys.
The need to support encryption brings an upgrade to the global directory format, whether or not you use encryption. Simply opening an existing global directory with GDE and closing the program with an EXIT command upgrades the global directory.
FIS strongly recommends you make a copy of any global directory before upgrading it. There is no way to downgrade a global directory – you need to recreate it.
If you inadvertently upgrade a global directory to the new format and wish to recreate the old global directory, execute the SHOW ALL command with the new GT.M release and capture the output. Use the information in the SHOW ALL command to create a new global directory file with the prior GT.M release, or better yet, create a script that you can feed to GDE to create a new global directory.
-[NO]ENcryption is a new SEGMENT qualifier. When creating the database file for a segment that is flagged as being encrypted, MUPIP CREATE acquires an encryption key for that file, and puts a cryptographic hash of the key in the database file header.
Except for the following commands where it does not need encryption keys to operate on encrypted databases, MUPIP needs access to encryption keys to operate on encrypted databases: BACKUP -BYTESTREAM, EXIT, EXTEND, FTOK, HELP, INTRPT, REPLICATE, RUNDOWN, STOP. MUPIP looks for the password for the key ring on disk in the environment variable $gtm_passwd, terminating with an error if it is unable to get a matching key for any database, journal, backup or extract file that contains encrypted data.
Note:
MUPIP JOURNAL operations that only operate on the journal file without requiring access to the database - EXTRACT and SHOW - require only the key for the journal file, not the current database file key.
MUPIP SET operations that require stand-alone access to the database do not need encryption keys; any command that can operate with concurrent access to the database requires encryption keys.
All other MUPIP operations require access to database encryption keys.
MUPIP EXTRACT -FORMAT=ZWRITE or -FORMAT=GLO and MUPIP JOURNAL -EXTRACT are intended to produce readable database content, and produce cleartext output even when database and journal files are encrypted.
Since a MUPIP EXTRACT -FORMAT=BINARY extract file can contain encrypted data from multiple database files, the extract file contains the hashes for all database files from which extracted data was obtained.
An encrypted database cannot be downgraded to GT.M version 4 (V4) format.
MUPIP CREATE is the only command that uses the database_filename in the master key file to obtain the key from the corresponding key_filename. As discussed elsewhere, all other commands use the key from the key ring in memory that matches the cryptographic hash for the encrypted data. If there are multiple files with the same file name, MUPIP CREATE uses the key specified in the last database_filename entry with that name in the master key file.
The MUPIP JOURNAL -SHOW command now displays the cryptographic hash of the symmetric key stored in the journal file header (the output is one long line):
$ mupip journal -show -backward mumps.mjl 2>&1 | grep hash
Journal file hash F226703EC502E9757848EEC733E1C3CABE5AC146C60F922D0E7D7CB5E2A37ABA005CE98D908B219249A0464F5BB622B72F5FDA0FDF04C8ECE52A4261975B89A2
$
Since an extract may contain the cryptographic hashes of multiple database files from which the data has been extracted, MUPIP LOAD may require multiple keys even to load one database file. Additionally, the database file into which the data is being loaded may have a different key from any data in the extract.
Unless you are acting under the specific instructions of FIS GT.M support, please provide DSE with access to encryption keys by setting the value of $gtm_passwd in the environment.
DSE operations that operate on the file header (such as CHANGE -FILEHEADER) do not need access to database encryption keys, whereas DSE operations that access data blocks (such as DUMP -BLOCK) usually require access to encryption keys. However, all DSE operations potentially require access to encryption keys because if DSE is the last process to exit a database, it will need to flush dirty global buffers, for which it will need the encryption keys. DSE does not encrypt block dumps. There is a current misfeature, that access to the database key is needed to look at block 0 (a bitmap). In practical usage this is not a severe restriction since typically when a bitmap is examined data records are also examined (which require the key anyway).
Please remember that DSE is a low level utility for use by knowledgeable users, and does not check for reasonableness of commands and values.
The DSE DUMP -FILEHEADER -ALL command shows the database file header, including the encryption hash (the hash is a very long line):
$ dse dump -fileheader -all 2>&1 | grep hash
Database file encryption hash F226703EC502E9757848EEC733E1C3CABE5AC146C60F922D0E7D7CB5E2A37ABA005CE98D908B219249A0464F5BB622B72F5FDA0FDF04C8ECE52A4261975B89A2
$
Under normal operating conditions, you should not need to change the cryptographic hash of the symmetric key. However, since there are theoretical attacks against hashes, and because a new cryptographic hash standard (SHA-3) is under development as of this date, DSE provides the ability to change the hash of the password stored in the database file header if and when you change the hash library.
The new DSE CHANGE -FILEHEADER -ENCRYPTION_HASH function hashes the symmetric key in the key file and replaces the hash in the database file header with this new value. The procedure to change the hash is:
With the old hash function linked to your plug-in, ensure that the database is structurally sound with a MUPIP INTEG. Although changing the hash in the file header makes no change to any data block, you will have more confidence in your work, and easier troubleshooting in the event of subsequent problems, if you verify database wholesomeness before proceeding.
Switch the plug-in to use the new hash function.
Execute the DSE CHANGE -FILEHEADER -ENCRYPTION_HASH operation.
Since recovery is not possible with a prior generation journal file with a different hash, if the database is journaled, create a new journal file without a back-pointer using the MUPIP SET -JOURNAL -NOPREVJNL command. FIS suggests backing up the database at this time.
Verify the correctness of the new hash function by reading a global node or with a DSE DUMP -BLOCK command.
As there is no way to change the hash in a journal file header, make sure that you retain access to the hash packages used for any journal file as long as you want the data in old journal files to be accessible. These old journal files with different hashes cannot be used for database recovery. The data in them can, however, be accessed with a MUPIP JOURNAL -EXTRACT command by a MUPIP process linked to the old hash function.
The only way to change the encryption key of a database file is to extract the data and load it into a new database file created with a different key. Use a logical multi site (LMS) application configuration to change keys while keeping the application available. For example, if A is initially the initiating (primary) instance and B the replicating (secondary) instance:
Bring down instance B and change the database keys with EXTRACT and LOAD. Remember to save the journal sequence numbers in the original database files, and to set the journal sequence number in all the newly created database files to the largest number in any original database file.
Bring up instance B and let it catch up with A.
At a convenient time, switchover. Now application logic executes on B and A is the replicating instance.
Bring down instance A and change the database keys with either EXTRACT / LOAD or using a backup from B. Then bring it back up and let it catch up.
To restore the original operating configuration, switchover at a convenient time. Now A again executes application logic which is replicated to B.
FIS suggests using different encryption keys for different instances, so that if the keys for one instance are compromised, the application can be kept available from another instance whose keys are not compromised, while changing the encryption keys on the instance with compromised keys.
Just as there is no way to change the encryption key of a database file, it is not possible to turn on encryption for an unencrypted database file, or to turn it off for an encrypted database file. Once a database file is created, its encryption attributes are immutable. To create an encrypted database, use GDE to specify encryption in the global directory file. Then use MUPIP CREATE to create an encrypted database and MUPIP LOAD to load data into it.
As noted in the section Tested Reference Implementations, GT.M includes a reference implementation that uses widely available encryption packages. It is your choice: you can decide to use the packages that FIS tested GT.M against, or you can choose to interface GT.M to another package of your choice. As noted earlier, FIS neither recommends nor supports any specific package (not even those that we tested against) and you should ensure that you have confidence in and support for whichever package that you intend to use in production. The reference implementation is provided compiled as ready to run object code as well as source code that you can customize to meet your needs.
Building the reference implementation from source code requires standard development tools for your platform, including C compiler, make, ld, standard header files, header files for encryption libraries, etc.
This section discusses the architecture of and interface between GT.M and the plugin. You must ensure that any plugin you provide presents the same interface to GT.M as the reference implementation.
The reference implementation mostly resides in $gtm_dist/plugin/gtmcrypt. GETPASS.o, the object file for the GETPASS.m utlity program resides in $gtm_dist, and if the installation includes Unicode support, the installation script compiles and places a GETPASS.o in the utf8 subdirectory as well.
The reference implementation includes:
A $gtm_dist/plugin/gtmcrypt sub-directory with all source files and scripts. The scripts include those needed to build/install libgtmcrypt.so and "helper" scripts, for example, add_db_key.ksh (see below).
The plugin interface that GT.M expects is defined in gtmcrypt_interface.h. Never modify this file - it defines the interface that the plugin must provide.
$gtm_dist/plugin/libgtmcrypt.so4 is the shared library containing the executables which is dynamically linked by GT.M and which in turn calls the encryption packages. If the $gtm_dist/utf8 directory exists, then it should contain a symbolic link to ../plugin.
GETPASS.m – source code for a (trivial) routine to prompt the user for a password. The installation script compiles this to create $gtm_dist/GETPASS.o, and , if a utf8 sub-directory is being created, $gtm_dist/utf8/GETPASS.o.
Source code is provided in the file $gtm_dist/plugin/gtmcrypt/source.tar which includes build.sh and install.sh scripts to respectively compile and install libgtmcrypt.so from the source code.
GT.M now provides additional C structure types (in the gtmxc_types.h file):
gtmcrypt_key_t – a datatype that is a handle to a key. The GT.M database engine itself does not manipulate keys. The plug-in keeps the keys, and provides handles to keys that the GT.M database engine uses to refer to keys.
xc_fileid_ptr_t – a pointer to a structure maintained by GT.M to uniquely identify a file. Note that a file may have multiple names – not only as a consequence of absolute and relative path names, but also because of symbolic links and also because a file system can be mounted at more than one place in the file name hierarchy. GT.M needs to be able to uniquely identify files.
Although not required to be used by a customized plugin implementation, GT.M provides (and the reference implementation uses) the following functions for uniquely identifying files:
xc_status_t gtm_filename_to_id(xc_string_t *filename, xc_fileid_ptr_t *fileid) – function that takes a file name and provides the file id structure for that file.
xc_status_t gtm_is_file_identical(xc_fileid_ptr_t fileid1, xc_fileid_ptr_t fileid2) – function that determines whether two file ids map to the same file.
gtm_xcfileid_free(xc_fileid_ptr_t fileid) – function to release a file id structure.
Mumps, MUPIP and DSE processes dynamically link to the plugin interface functions that reside in the shared library. The functions serve as software "shims" to interface with an encryption library such as libmcrypt or libgpgme / libgcrypt.
The plugin interface functions are: gtmcrypt_init(), gtmcrypt_getkey_by_name(), gtmcrypt_getkey_by_hash(), gtmcrypt_hash_gen(), gtmcrypt_encode(), gtmcrypt_decode(), gtmcrypt_close(), and gtmcrypt_strerror(). A GT.M database consists of multiple database files, each of which has its own encryption key, although you can use the same key for multiple files. Thus, the gtmcrypt* functions are capable of managing multiple keys for multiple database files. Prototypes for these functions are in gtmcrypt_interface.h.
The core plugin interface functions, all of which return a value of type xc_status_t are:
gtmcrypt_init() performs initialization. If the environment variable $gtm_passwd exists and has an empty string value, GT.M calls gtmcrypt_init() before the first M program is loaded; otherwise it calls gtmcrypt_init() when it attempts the first operation on an encrypted database file.
Generally, gtmcrypt_getkey_by_hash or, for MUPIP CREATE, gtmcrypt_getkey_by_name perform key acquisition, and place the keys where gtmcrypt_decode() and gtmcrypt_encode() can find them when they are called.
Whenever GT.M needs to decode a block of bytes, it calls gtmcrypt_decode() to decode the encrypted data. At the level at which GT.M database encryption operates, it does not matter what the data is – numeric data, string data whether in M or UTF-8 mode and whether or not modified by a collation algorithm. Encryption and decryption simply operate on a series of bytes.
Whenever GT.M needs to encode a block of bytes, it calls gtmcrypt_encode() to encode the data.
If encryption has been used (if gtmcrypt_init() was previously called and returned success), GT.M calls gtmcrypt_close() at process exit and before generating a core file. gtmcrypt_close() must erase keys in memory to ensure that no cleartext keys are visible in the core file.
More detailed descriptions follow.
gtmcrypt_key_t *gtmcrypt_getkey_by_name(xc_string_t *filename) - MUPIP CREATE uses this function to get the key for a database file. This function searches for the given filename in the memory key ring and returns a handle to its symmetric cipher key. If there is more than one entry for the given filename , the reference implementation returns the entry matching the last occurrence of that filename in the master key file.
xc_status_t gtmcrypt_hash_gen(gtmcrypt_key_t *key, xc_string_t *hash) - MUPIP CREATE uses this function to generate a hash from the key then copies that hash into the database file header. The first parameter is a handle to the key and the second parameter points to 256 byte buffer. In the event the hash algorithm used provides hashes smaller than 256 bytes, gtmcrypt_hash_gen() must fill any unused space in the 256 byte buffer with zeros.
gtmcrypt_key_t *gtmcrypt_getkey_by_hash(xc_string_t *hash) - GT.M uses this function at database file open time to obtain the correct key using its hash from the database file header. This function searches for the given hash in the memory key ring and returns a handle to the matching symmetric cipher key. MUPIP LOAD, MUPIP RESTORE, MUPIP EXTRACT, MUPIP JOURNAL and MUPIP BACKUP -BYTESTREAM all use this to find keys corresponding to the current or prior databases from which the files they use for input were derived.
xc_status_t gtmcrypt_encode(gtmcrypt_key_t *key, xc_string_t *inbuf, xc_string_t *outbuf) and xc_status_t gtmcrypt_decode(gtmcrypt_key_t *key, xc_string_t *inbuf, xc_string_t *outbuf)- GT.M uses these functions to encode and decode data. The first parameter is a handle to the symmetric cipher key, the second a pointer to the block of data to encode or decode, and the third a pointer to the resulting block of encoded or decoded data. Using the appropriate key (same key for a symmetric cipher), gtmcrypt_decode() must be able to decode any data buffer encoded by gtmcrypt_encode(), otherwise the encrypted data is rendered unrecoverable.5 As discussed earlier, GT.M requires the encrypted and cleartext versions of a string to have the same length.
char *gtmcrypt_strerror() - GT.M uses this function to retrieve addtional error context from the plug-in after the plug-in returns an error status. This function returns a pointer to additional text related to the last error that occurred. GT.M displays this text as part of an error report. In a case where an error has no additional context or description, this function returns a null string.
The complete source code for reference implementations of these functions is provided, licensed under the same terms as GT.M. You are at liberty to modify them to suit your specific GT.M database encryption needs. Check your GT.M license if you wish to consider redistributing your changes to others.
Run Time Error: GT.M failed to load the gtmcrypt plug-in or one of its related libraries.
Action: Refer to the accompanying detail (xxxx) and verify that the gtmcrypt plug-in and related libraries are properly installed and that $LD_LIBRARY_PATH / $LIBPATH are properly set.
Run Time Error: gtmcrypt plug-in reports there is problem with the hash function.
Action: Examine the message (xxxx) from the plug-in and take the needed action.
Run Time Error: The gtmcrypt plug-in reports it is unable to initialize one or more of its related libraries.
Action: Examine the detailed message (xxxx) from the plug-in and take appropriate action.
Run Time Error: gtmcrypt plug-in reports the hash of the key in the header of database file dddd does not match the hash stored in the header of journal file jjjj. This is most likely caused by inappropriate operator action such as replacing the current journal file with an older journal file.
Action: Correct the error that caused the incorrect journal file to be pointed to by the database file. If the correct journal file has been inadvertently deleted, create new journal files with the -noprevjnl switch. Take a backup as soon as possible thereafter. Depending on your situation, you may need to refresh secondary instances.
Run Time Error: gtmcrypt plug-in reports it was unable to obtain an encryption key for file ffff.
Action: Examine the message (xxxx) from the plug-in and take the needed action to allow the proces to locate the correct key for the file. For example, with the reference implementation, verify that
Run Time Error: gtmcrypt plug-in reports it was unable to obtain an encryption key based upon matching the hash of an encryption key.
Action: See the actions for CRYPTKEYFETCHFAILED.
MUPIP or GDE error: This error is triggered by an attempt to mark an MM database as encrypted with GDE or to switch an encrypted database from BG to MM with MUPIP SET. The MM access method is not supported for encrypted databases.
Action: Use the BG access method for encrypted files.
Run-time error: This error occurs if an external call was used to set the $gtm_passwd environment variable to the null string after starting GT.M and before the first time an encrypted database file is accessed is within a TP transaction.
MUPIP error: An attempt to downgrade file ffff which is an encrypted database to the V4 (GT.M version 4) format failed because the V4 format does not support encrypted database files.
Action: Use the database in the current format. If a V4 format is required, extract the data in the (unencrypted) ZWRite format with MUPIP EXTRACT and load it into a newly created V4 database.
Run Time Error: gtmcrypt plug-in reports there is problem with encryption or decryption.
Action: Examine the message (xxxx) from the plug-in and take appropriate action.
DSE error: DSE detected that there were still processes using the old encryption key
Action: Restart these processes so that all the processes are using the new hash/key.
Plugin error: The plugin cannot find the master key file.
Action: Set the $gtm_dbkeys environment variable to point to the correct master key file.
Plugin error: The plugin cannot find the MUMPS executable.
Action: Set the $gtm_dist environment variable to the directory containing MUMPS executable. Verify proper permissions for directory path and file.
Plugin error: The plugin cannot open the master key file.
Action: Verify the master key file exists and there are appropriate authorizations on the directory path and master key file.
Plugin error: The plugin reports that the master key file is not the proper type file.
Action: Point the gtm_dbkeys environment variable to an appropriately formatted master key file.
Plugin error: The plugin reports that the master key file does not contain a valid entry pointing to the database file.
Action: Create an entry in the master key file for the specified database file, verify that the database file exists and appropriate authorizations exist on the directory and database file name.
Plugin error: The plugin is unable to find the specified database file.
Action: Verify the database file exists, that a corresponding entry in the master key file points to the database file and that appropriate authorizations exist on the directory path and the database file.
Plugin error: The plugin detected an internal error.
Action: Indicates there is a communications error between GT.M and the gtmcrypt plug-in. Replace process with undamaged one. Report the entire incident context to your GT.M support channel.
Plugin error: The plugin was not able to find the key file on the specified path.
Action: Verify master key file entry for this key file points to the correct path. Verify that the key file itself exists. Verify proper authorizations on directory path and file.
Plugin error: A gtmcrypt function was called before gtmcrypt_init().
Action: Call gtmcrypt_init() before calling any other encryption functions.
Plugin error: An environment variable needed by the plugin was not set.
Action: Set the environment variable <environment_variable> to its correct value.
Plugin error: The $gtm_dbkeys environment variable was set to the empty string.
Recovery Action: Set $gtm_dbkeys to point to the master key file.
Plugin error: The plugin was unable to locate the master key file.
Action: Place the master key file in the users home directory or point the gtm_dbkeys environment variable to the master key file.
Plugin error: The plugin detected that it needed the obfuscated password but the $gtm_passwd environment variable was set to the empty string.
Action: Use maskpass to set $gtm_passwd to the obfuscated password prior to invoking MUPIP/DSE, or wrap the invocation with a MUMPS process which will prompt for the password and set the obfuscated password.
Plugin error: libgpgme reported an error to the plugin.
Action: Consult GpgME documentation for the specific error message.
Plugin error: The plugin was unable to find a matching "dat" entry for a "key" entry in the master key file.
Action: Verify that each "key" entry has a corresponding "dat" entry.
Plugin error: The plugin detected that the master key file was not properly formatted.
Action: Verify entries in the master key file start with "dat" or "key".
Plugin error: The plugin was not able to find a "key" entry for a "dat" entry.
Action: Verify the database file exists, that the corresponding entry in the master key file points to the database file, that appropriate authorizations exist on the directory path and the database file, and that each "dat" entry has a corresponding "key" entry.
Plugin error: The plugin detected that the correct private key password was not supplied.
Action: Provide the correct password.
Plugin error: The plugin could not locate an appropriate libgcrypt library version.
Action: Verify the <expected_version> is installed and in the library search path.
Plugin error: The plugin was not able to find a needed database file key.
Action: Add an entry for this encryption key. If needed, use DSE DUMP –FILE –ALL on all of the database files to find the database file that matches the <hash>. With extracts and backups, multiple database files may have contributed encrypted records.
Plugin error: The plugin was unable to find any entries in the master key file.
Action: Add entries to the master key file.
Plugin error: The plugin was unable to find a valid encrypted key in the specified file.
Action: Create a valid key file.
FIS neither encourages nor supports the use of any specific encryption library. In order to be helpful, here is how we created the libraries for testing GT.M in the development environment.
Packages were installed from standard repositories using the package manager.
All packages except libgpgme were installed from Red Hat Network. libgpgme was built from source after specifying ./configure CC=gcc CFLAGS=-m64
All packages except libgpgme were installed from Red Hat Network. libgpgme was built from source after specifying ./configure CC=gcc
All packages except libgpgme were installed from Red Hat Network. libgpgme was built from source after specifying ./configure CC=gcc
./configure CC=cc CFLAGS=-q64 ($OBJECT_MODE=64)
./Configure aix64-cc # Note: it is an upper case C
.make
(as root) make install
GPGME requires a source level fix to use the proper malloc() that requires an include for stdlib.h in the include section of version.c. Then:
./configure CC="xlc -q64" --disable-asm ($OBJECT_MODE=64)/ or CC=cc CFLAGS=-q64
GPG on AIX requires the setuid bit to be set. This can be done via chmod u+s /path/to/gpg. Please see http://www.gnupg.org/documentation/faqs.en.html#q6.1
./configure CC="xlc -q64" --disable-asm ($OBJECT_MODE=64) or CC=cc CFLAGS=-q64
Set $LD_LIBRARY_PATH to include /usr/lib/sparcv9 AND /usr/ucblib/sparcv9 for both Solaris 9 and 10. Solaris seems to default to the 32-bit version of ucblib at runtime, unless the 64-bit path is ahead of the 32-bit in $LD_LIBRARY_PATH. However, using -R/usr/lib/sparcv9 -R/usr/ucblib/sparcv9/ as a CFLAG at build time hard-codes the path into the library, removing the need for $LD_LIBRARY_PATH.
./configure CC=/opt/SUNWspro/bin/cc CFLAGS="-m64 -R/usr/lib/sparcv9 -R/usr/ucblib/sparcv9/"
./configure CC=/opt/SUNWspro/bin/cc CFLAGS="-m64 -R/usr/lib/sparcv9 -R/usr/ucblib/sparcv9/" --disable-asm --with-gpg-error-prefix=/usr/local
GPGME requires a source level fix to use the proper malloc() that requires an include for stdlib.h in the include section of version.c.
./configure CC="xlc -q64" --disable-asm ($OBJECT_MODE=64)/ or CC=cc CFLAGS=-q64
./configure CC=/opt/SUNWspro/bin/cc CFLAGS="-m64 -R/usr/lib/sparcv9 -R/usr/ucblib/sparcv9/" --disable-asm --with-gpg-error-prefix=/usr/local
./configure CC=/opt/SUNWspro/bin/cc CFLAGS="-m64 -R/usr/lib/sparcv9 -R/usr/ucblib/sparcv9/" --disable-asm