#### PGP

#### Synopsis

    HELP:   Decryption and/or verification of OpenPGP messages
    TYPE:   OBJECT
    SYNTAX: PGP(BUFSIZ=num,NOSIGV,PASSWD='bin',SKPKEY,SKPFMT,FRCENC,FRCINT,FRCSIG,LITERR,USERID='str',TIMSTP=num,LEVELS=num,FKM5(),REENCYPT())

#### Description

The OpenPGP converter can be used to encrypt or decrypt data streams conforming to RFC4880. The available functionality depends mainly on the functions implemented by the used FLAM key management extension version 5 (FKM5).

Encryption always results in binary blocks of data. The decryption result can be text or binary data. Record boundaries are lost. Please use delimiters, length fields or fixed length data if records must be exchanged.

The encrypted data can be ASCII-armored for transport/storage via/on text-based media.

       cnv.pgp(...) cnv.bas(... armor(...))

If compression parameters are not specified and the data is marked as being without redundancy, then no compression is done. In all other cases, the default level 6 (AUTO) with GZIP is used. You can switch to level 1 or 9 with the FAST and BEST keywords, respectively. Currently, the compression procedures GZIP (DEFAULT, raw without header, called ZIP in RFC4880), ZLIB and BZIP2 are supported. With the compression mode COPY, no compression is done, but to save CPU time, we recommend to use the defaults.

On z/OS, the GZIP compression is done with ZEDC if available.

Some PGP crypto operations use a random number generator (e.g. for session key generation) which needs to be initialized with high quality entropy. If there is no good source of entropy available from the operating system (e.g. /dev/urandom, /dev/random or /dev/srandom on Unix-like systems including z/OS (which requires ICSF)), some operations may fail. Without a source of entropy, cryptographically safe randomness cannot be generated and would likely lead to weak encryption. Therefore, it is better to abort the operation. If you wish to continue anyway and potentially weak encryption is acceptable, you can define the environment variable FL_ALLOW_LOW_ENTROPY. It allows the random number generator to be seeded with a low entropy source based on the variability of CPU clock cycles. Plase note that there is no 100% guarantee for this to work.

The component supports different methods, formats and algorithms for encryption and signing. By default, a newer format of PGP data packets is used that protects the encrypted data against modification (SEIP, c.f. RFC4880 "Symmetrically Encrypted Integrity Protected Data Packet"). The old format (SENC) without integrity protection can also be used if necessary (not recommended). Additionally, you can define the key label templates as well as user and signer IDs for FKM5 usage.

PGP files containing (un)compressed and unencrypted data are supported. If you want to ensure that only encrypted data is accepted when reading, you can enable the FRCENC switch. FRCINT enforces integrity protection. Additionally, you can also enforce signing.

Symmetrical encryption using a password is also supported, but is not recommended to use. For a professional solution, the FLAM key management extension version 5 can be used. Several implementations are available in LIBFKM5. For example, on z/OS the use of ICSF PKDS is the default.

When reading, the key is chosen based on the key ID provided in the PGP message. Some tools like GunPG support hidden recipients, where no key ID is stored. In such a case, the user ID must be provided to read the encrypted PGP file. If there are multiple keys for the same user ID and the required key is not the currently active key (i.e. the youngest of valid keys at the current point in time), a timestamp must also be provided which is used instead of the current time. It must be within the validity period of the key. Setting a timestamp has the same effect as setting the system time to the timestamp. So, if you specify a timestamp one year in the future, the key is selected that matches the user ID and is the youngest of valid keys at the date one year from now. If there is more than one matching key (multiple keys with same user ID and creation date), the key with the shortest validity period is chosen.

To generate, import, export and delete PGP keys, the corresponding KEY command can be used. Below you can see examples for generating a new key, exporting the resulting public key and importing a key from another node.

    FLCL KEY GENERATE.PGP(USER=MYTEST.KEY VALIDDAYS=365)
    FLCL KEY EXPORT.PGP(FILE=MYTEST.KEY, ARMOR())
    FLCL KEY IMPORT.PGP(FILE=MYPARTNER.KEY USER=MYPARTNER.KEY)

If you can use the standard FKM5 for your platform, reading PGP files can be done completely transparently. It is possible to define different decryption specifications (3 passphrases and 2 different FKM5) by using CNV.PGP() more than once. To control this, the switches SKPKEY (skip if key does not match) and SKPFMT (skip if invalid format) are may be used.

When writing you can define a list of user IDs or passwords as recipients. These arrays allows to define more than one entity which can read this file.

A PGP file consists of layered packets. An encrypted PGP file usually consists of literal packets containing the plain text. This stream can then be compressed and put into compression packets. The last layer is the encryption using SEIP (symmetrically encrypted and integrity protected) or SENC (only symmetrically encrypted) packets. Each of these levels are valid PGP files and many more combinations are possible. To implement this hierarchical system of PGP file formats, the CNVPGP component internally uses various conversion layers.

Normally, decoding is done up to the literal (parameter LEVEL not set) packet layer to produce the original plain text. If you want stop decoding earlier, for example after decryption, then set LEVEL to 1. To stop after decompression set the parameter LEVEL to 2.

When reading encrypted data that is not integrity protected (i.e. consists of old format SENC packets), a warning is printed to the log because the encrypted data might have been modified. With SENC, however, there is no way to detect encrypted data modifications.

When reading PGP files, packet layers are removed until reaching the literal packet layer. With the LITERR switch you can enforce an error if no literal data can be found. By default, this is disabled because another PGP conversion can follow.

If the block size is too small, situations can occur where level X does not have enough data to provide input to level X+1. In such case a SIZE error occurs. Especially if BZIP2 is used as compression algorithm or a very small block size is used this likely to occur. We recommend to work with the default block sizes, to prevent this error.

#### Examples

Simple write example (with ICSF/CCA FKM5)

     flcl xcnv "input(sav.fil(fio.blk(name=file.bin)))
                outpu(sav.fil(fio.blk(name=file.pgp)
                              cnv.pgp(user='LIMESU01'
                                      fkm5(libr='libfkm5' func='PGPCCA'
                                           para='keystore=CSF.CSFPKDS'
                                          )
                                     )
                             )
                     )

On z/OS, 'LIBFKM5' is the default library and 'PGPCCA' the default function. With HCR77B0 (z/OS2.2) the 'KEYSTORE' must not longer be provided, if the PKDS only solution is used. In this case, only the FKM5 object must be activated.

Simple read example (with PKCS11 FKM5)

     flcl xcnv "input(sav.fil(fio.blk(name=file.pgp)
                              cnv.pgp(fkm5(libr='libfkm5' func='PGPP11
                                           para='lib=cryptoki.so,pin=1234'
                                          )
                                     )
                             )
                     )
                outpu(sav.fil(fio.blk(name='file.out.bin'))) "

In general, it would be useful to define the FKM5 object via a property file to simplify the use of the CNVPGP component.

#### Arguments

- `NUMBER: BUFSIZ=num - Initial buffer size for preallocation [65536]`
- `SWITCH: NOSIGV - Disable signature verification [FALSE]`
- `STRING: PASSWD='bin' - Passphrase for symmetrically encrypted OpenPGP File`
- `SWITCH: SKPKEY - Skip decryption if key not match (try next conversion) [FALSE]`
- `SWITCH: SKPFMT - Skip decryption if data format not match (try next conversion) [FALSE]`
- `SWITCH: FRCENC - Enforce an error of PGP file is not encrypted [FALSE]`
- `SWITCH: FRCINT - Enforce an error if PGP file is not integrity protected [FALSE]`
- `SWITCH: FRCSIG - Enforce an error if PGP file is not signed [FALSE]`
- `SWITCH: LITERR - Enforce an error if no plain text returned [FALSE]`
- `STRING: USERID='str' - Receiver user ID for decryption (only for hidden recipients)`
- `NUMBER: TIMSTP=num - Time stamp (seconds since 1970) used for key selection [0 - current]`
- `NUMBER: LEVELS=num - Limit amount of decodings [0-ALL]`