6.4. Token Operation and Policy Processing

This section discusses major operations (both explicit and implicit) that involve a token. The list below will discuss each feature and its configuration.

Note

See the Token Policiessection in the Red Hat Certificate System 9 Planning, Installation and Deployment Guide for general information.
Format
The Format operation (user-initiated) takes a token in a completely blank state as supplied by the manufacturer, and loads a Coolkey applet on it.
Configuration example:
#specify that we want authentication for format. We almost always want this at true:
op.format.userKey.auth.enable=true
#specify the ldap authentication configuration, so TPS knows where to validate credentials:
op.format.userKey.auth.id=ldap1
#specify the connection the the CA
op.format.userKey.ca.conn=ca1
#specify id of the card manager applet on given token
op.format.userKey.cardmgr_instance=A0000000030000

#specify if we need to match the visa cuid to the nist sp800sp derivation algorithm KDD value. Mostly will be false:
op.format.userKey.cuidMustMatchKDD=false

#enable ability to restrict key changoever to a specific range of key set:
op.format.userKey.enableBoundedGPKeyVersion=true
#enable the phone home url to write to the token:
op.format.userKey.issuerinfo.enable=true
#actual home url to write to token:
op.format.userKey.issuerinfo.value=http://server.example.com:8080/tps/phoneHome
#specify whether to request a login from the client. Mostly true, external reg may want this to be false:
op.format.userKey.loginRequest.enable=true
#Actual range of desired keyset numbers:
op.format.userKey.maximumGPKeyVersion=FF
op.format.userKey.minimumGPKeyVersion=01
#Whether or not to revoke certs on the token after a format, and what the reason will be if so:
op.format.userKey.revokeCert=true
op.format.userKey.revokeCert.reason=0
#This will roll back the reflected keyyset version of the token in the tokendb. After a failed key changeover operation. This is to keep the value in sync with reality in the tokendb. Always false, since this version of TPS avoids this situation now:
op.format.userKey.rollbackKeyVersionOnPutKeyFailure=false

#specify connection to the TKS:
op.format.userKey.tks.conn=tks1
#where to get the actual applet file to write to the token:
op.format.userKey.update.applet.directory=/usr/share/pki/tps/applets
#Allows a completely blank token to be recognized by TPS. Mostly should be true:
op.format.userKey.update.applet.emptyToken.enable=true
#Always should be true, not supported:
op.format.userKey.update.applet.encryption=true
#Actual version of the applet file we want to upgrade to. This file will have a name something like: 1.4.54de7a99.ijc:
op.format.userKey.update.applet.requiredVersion=1.4.54de790f
#Symm key changeover:
op.format.userKey.update.symmetricKeys.enable=false
op.format.userKey.update.symmetricKeys.requiredVersion=1
#Make sure the token db is in sync with reality. Should always be true:
op.format.userKey.validateCardKeyInfoAgainstTokenDB=true
Enrollment
The basic enrollment operation takes a formatted token and places certs and keys onto the token in an effort to personalize the token. The following configuration example will explain how this can be controlled.
The example shows basic enrollment which does not deal with renewal and internal recovery. Settings not discussed here are either covered in the Format section, or not crucial.
op.enroll.userKey.auth.enable=true
op.enroll.userKey.auth.id=ldap1
op.enroll.userKey.cardmgr_instance=A0000000030000
op.enroll.userKey.cuidMustMatchKDD=false

op.enroll.userKey.enableBoundedGPKeyVersion=true
op.enroll.userKey.issuerinfo.enable=true
op.enroll.userKey.issuerinfo.value=http://server.example.com:8080/tps/phoneHome

#configure the encryption cert and keys  we want on the token:

#connection the the CA, which issues the certs:
op.enroll.userKey.keyGen.encryption.ca.conn=ca1
#Profile id we want the CA to use to issue our encrytion cert:
op.enroll.userKey.keyGen.encryption.ca.profileId=caTokenUserEncryptionKeyEnrollment

#These two cover the indexes of the certs written to the token. Each cert needs a unique index or “slot”. In our sample the enc cert will occupy slot 2 and the signing cert, shown later, will occupy slot 1. Avoid overlap with these numbers:
op.enroll.userKey.keyGen.encryption.certAttrId=c2
op.enroll.userKey.keyGen.encryption.certId=C2

op.enroll.userKey.keyGen.encryption.cuid_label=$cuid$
#specify size of generated private key:
op.enroll.userKey.keyGen.encryption.keySize=1024
op.enroll.userKey.keyGen.encryption.keyUsage=0
op.enroll.userKey.keyGen.encryption.keyUser=0
#specify pattern for what the label of the cert will look like when the cert nickname is displayed in browsers and mail clients:
op.enroll.userKey.keyGen.encryption.label=encryption key for $userid$
#specify if we want to overwrite certs on a re-enrollment operation. This is almost always the case:
op.enroll.userKey.keyGen.encryption.overwrite=true

#The next several settings specify the capabilities that the private key on the final token will inherit. For instance this will determine if the cert can be used for encryption or digital signatures. There are settings for both the private and public key.

op.enroll.userKey.keyGen.encryption.private.keyCapabilities.decrypt=true
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.derive=false
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.encrypt=false
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.private=true
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.sensitive=true
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.sign=false
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.signRecover=false
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.token=true
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.unwrap=true
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.verify=false
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.verifyRecover=false
op.enroll.userKey.keyGen.encryption.private.keyCapabilities.wrap=false
op.enroll.userKey.keyGen.encryption.privateKeyAttrId=k4
op.enroll.userKey.keyGen.encryption.privateKeyNumber=4
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.decrypt=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.derive=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.encrypt=true
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.private=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.sensitive=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.sign=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.signRecover=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.token=true
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.unwrap=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.verify=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.verifyRecover=false
op.enroll.userKey.keyGen.encryption.public.keyCapabilities.wrap=true

#The following index numbers correspond to the index or slot that the private and public keys occupy. The common formula we use is that the public key index will be 2 * cert id + 1, and the private key index, shown above will be 2 * cert id. In this example the cert id is 2, so the key ids will be 4 and 5 respectively. When composing these, be careful not to create conflicts. This applies to the signing key section below.

op.enroll.userKey.keyGen.encryption.publicKeyAttrId=k5
op.enroll.userKey.keyGen.encryption.publicKeyNumber=5

#specify if, when a certificate is slated for revocation, based on other rules, we want to check to see if some other token is using this cert in a shared situation. If this is set to true, and this situation is found the cert will not be revoked until the last token wants to revoke this cert:
op.enroll.userKey.keyGen.encryption.recovery.destroyed.holdRevocationUntilLastCredential=false

#specify, if we want server side keygen, if we want to have that generated key archived to the drm. This is almost always the case, since we want the ability to later recover a cert and its encryption private key back to a new token:
op.enroll.userKey.keyGen.encryption.serverKeygen.archive=true
#connection to drm to generate the key for us:
op.enroll.userKey.keyGen.encryption.serverKeygen.drm.conn=kra1
#specify server side keygen of the encryption private key. This most often will be desired:
op.enroll.userKey.keyGen.encryption.serverKeygen.enable=true

#This setting tells us how many certs we want to enroll for this TPS profile, in the case “userKey”. Here we want 2 total certs. The next values then go on to index into the config what two types of certs we want, signing and encryption:
op.enroll.userKey.keyGen.keyType.num=2
op.enroll.userKey.keyGen.keyType.value.0=signing
op.enroll.userKey.keyGen.keyType.value.1=encryption

#configure the signing cert and keys we want on the token the settings for these are similar to the encryption settings already discussed, except the capability flags presented below, since this is a signing key.

op.enroll.userKey.keyGen.signing.ca.conn=ca1
op.enroll.userKey.keyGen.signing.ca.profileId=caTokenUserSigningKeyEnrollment
op.enroll.userKey.keyGen.signing.certAttrId=c1
op.enroll.userKey.keyGen.signing.certId=C1
op.enroll.userKey.keyGen.signing.cuid_label=$cuid$
op.enroll.userKey.keyGen.signing.keySize=1024
op.enroll.userKey.keyGen.signing.keyUsage=0
op.enroll.userKey.keyGen.signing.keyUser=0
op.enroll.userKey.keyGen.signing.label=signing key for $userid$
op.enroll.userKey.keyGen.signing.overwrite=true
op.enroll.userKey.keyGen.signing.private.keyCapabilities.decrypt=false
op.enroll.userKey.keyGen.signing.private.keyCapabilities.derive=false
op.enroll.userKey.keyGen.signing.private.keyCapabilities.encrypt=false
op.enroll.userKey.keyGen.signing.private.keyCapabilities.private=true
op.enroll.userKey.keyGen.signing.private.keyCapabilities.sensitive=true
op.enroll.userKey.keyGen.signing.private.keyCapabilities.sign=true
op.enroll.userKey.keyGen.signing.private.keyCapabilities.signRecover=true
op.enroll.userKey.keyGen.signing.private.keyCapabilities.token=true
op.enroll.userKey.keyGen.signing.private.keyCapabilities.unwrap=false
op.enroll.userKey.keyGen.signing.private.keyCapabilities.verify=false
op.enroll.userKey.keyGen.signing.private.keyCapabilities.verifyRecover=false
op.enroll.userKey.keyGen.signing.private.keyCapabilities.wrap=false
op.enroll.userKey.keyGen.signing.privateKeyAttrId=k2
op.enroll.userKey.keyGen.signing.privateKeyNumber=2
op.enroll.userKey.keyGen.signing.public.keyCapabilities.decrypt=false
op.enroll.userKey.keyGen.signing.public.keyCapabilities.derive=false
op.enroll.userKey.keyGen.signing.public.keyCapabilities.encrypt=false
op.enroll.userKey.keyGen.signing.public.keyCapabilities.private=false
op.enroll.userKey.keyGen.signing.public.keyCapabilities.sensitive=false
op.enroll.userKey.keyGen.signing.public.keyCapabilities.sign=false
op.enroll.userKey.keyGen.signing.public.keyCapabilities.signRecover=false
op.enroll.userKey.keyGen.signing.public.keyCapabilities.token=true
op.enroll.userKey.keyGen.signing.public.keyCapabilities.unwrap=false
op.enroll.userKey.keyGen.signing.public.keyCapabilities.verify=true
op.enroll.userKey.keyGen.signing.public.keyCapabilities.verifyRecover=true
op.enroll.userKey.keyGen.signing.public.keyCapabilities.wrap=false
op.enroll.userKey.keyGen.signing.publicKeyAttrId=k3
op.enroll.userKey.keyGen.signing.publicKeyNumber=3
Pin Reset
The configuration for pin reset is discussed in Section 6.3, “Token Policies”, because pin reset relies on a policy to determine if it is to be legally performed or not.
Renewal
The configuration for renewal is discussed in Section 6.3, “Token Policies”, since renewal relies on a policy to determine if it is legal to perform or not upon an already enrolled token.
Recovery
Recovery is implicitly set into motion when the user of the TPS user interface marks a previously active token into an unfavorable state such as “lost” or “destroyed”. Once this happens, the next enrollment of a new token by the same user will adhere to the following configuration to recover the certificates from the user’s old token, to this new token.
The end result of this operation is that the user will have a new physical token that may contain the encryption certificates recovered from the old token, so that the user can continue to encrypt and decrypt data as needed. A new signing certificate is also usually placed on this token as shown in the sample config examples below.
The following is a list of supported states into which a token can be placed manually in the TPS user interface, as seen in the configuration:
  • tokendb._069=# - DAMAGED (1): Corresponds to destroyed in the recovery configuration. Used when a token has been physically damaged.
  • tokendb._070=# - PERM_LOST (2): Corresponds to keyCompromisein the recovery configuration. Used when a token has been lost permanently.
  • tokendb._071=# - SUSPENDED (3): Corresponds to onHold in the recovery configuration. Used when a token has been temporarily misplaced, but the user expects to find it again.
  • tokendb._072=# - TERMINATED (6): Corresponds to terminated in the recovery configuration. Used to take a token out of service forever for internal reasons.
Example recovery configuration:
#When a token is marked destroyed, don’t revoke the certs on the token unless all other tokens do not have the certs included:
op.enroll.userKey.keyGen.encryption.recovery.destroyed.holdRevocationUntilLastCredential=false
#specify if we even want to revoke certs a token is marked destroyed:
op.enroll.userKey.keyGen.encryption.recovery.destroyed.revokeCert=false
#if we want to revoke any certs here, specify the reason for revocation that will be sent to the CA:
op.enroll.userKey.keyGen.encryption.recovery.destroyed.revokeCert.reason=0
#speficy if we want to revoke expired certs when marking the token destroyed:
op.enroll.userKey.keyGen.encryption.recovery.destroyed.revokeExpiredCerts=false
Additional settings are used to specify what kind of supported static recovery should be used when performing a recovery operation to a new token (when the original token has been marked destroyed). The following schemes are supported:
  • Recover Last (RecoverLast): Recover the latest encryption certificate to be placed on the token.
  • Generate New Key and Recover Last (GenerateNewKeyAndRecoverLast): Same as Recover Last, but also generate a new encryption certificate and upload it to the token as well. The new token will then have two certificates.
  • Generate New Key (GenerateNewKey): Generate a new encryption certificate and place it on the token. Do not recover any old certificates.
For example:
op.enroll.userKey.keyGen.encryption.recovery.destroyed.scheme=RecoverLast
The following configuration example determines how to recover tokens marked as permanently lost:
op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.holdRevocationUntilLastCredential=false
op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.revokeCert=true
op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.revokeCert.reason=1
op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.revokeExpiredCerts=false
op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.scheme=GenerateNewKey

# Section when a token is marked terminated.

op.enroll.userKey.keyGen.encryption.recovery.terminated.holdRevocationUntilLastCredential=false
op.enroll.userKey.keyGen.encryption.recovery.terminated.revokeCert=true
op.enroll.userKey.keyGen.encryption.recovery.terminated.revokeCert.reason=1
op.enroll.userKey.keyGen.encryption.recovery.terminated.revokeExpiredCerts=false
op.enroll.userKey.keyGen.encryption.recovery.terminated.scheme=GenerateNewKey

# This section details the recovery profile with respect to which certs and of what kind get recovered on the token.

op.enroll.userKey.keyGen.recovery.destroyed.keyType.num=2
op.enroll.userKey.keyGen.recovery.destroyed.keyType.value.0=signing
op.enroll.userKey.keyGen.recovery.destroyed.keyType.value.1=encryption
Finally, the following example determines what the system will do about the signing certificate that was on the old token. In most cases, the GenerateNewKey recovery scheme should be used in order to avoid potentially having multiple copies of a signing private key available (for example, one that is recovered on a new token, and one on an old token that was permanently lost but found by somebody else).
op.enroll.userKey.keyGen.recovery.keyCompromise.keyType.value.0=signing
op.enroll.userKey.keyGen.recovery.keyCompromise.keyType.value.1=encryption
op.enroll.userKey.keyGen.recovery.onHold.keyType.num=2
op.enroll.userKey.keyGen.recovery.onHold.keyType.value.0=signing
op.enroll.userKey.keyGen.recovery.onHold.keyType.value.1=encryption

op.enroll.userKey.keyGen.signing.recovery.destroyed.holdRevocationUntilLastCredential=false
op.enroll.userKey.keyGen.signing.recovery.destroyed.revokeCert=true
op.enroll.userKey.keyGen.signing.recovery.destroyed.revokeCert.reason=0
op.enroll.userKey.keyGen.signing.recovery.destroyed.revokeExpiredCerts=false
op.enroll.userKey.keyGen.signing.recovery.destroyed.scheme=GenerateNewKey
op.enroll.userKey.keyGen.signing.recovery.keyCompromise.holdRevocationUntilLastCredential=false
op.enroll.userKey.keyGen.signing.recovery.keyCompromise.revokeCert=true
op.enroll.userKey.keyGen.signing.recovery.keyCompromise.revokeCert.reason=1
op.enroll.userKey.keyGen.signing.recovery.keyCompromise.revokeExpiredCerts=false
op.enroll.userKey.keyGen.signing.recovery.keyCompromise.scheme=GenerateNewKey
op.enroll.userKey.keyGen.signing.recovery.onHold.holdRevocationUntilLastCredential=false
op.enroll.userKey.keyGen.signing.recovery.onHold.revokeCert=true

op.enroll.userKey.keyGen.signing.recovery.onHold.revokeCert.reason=6
op.enroll.userKey.keyGen.signing.recovery.onHold.revokeExpiredCerts=false
op.enroll.userKey.keyGen.signing.recovery.onHold.scheme=GenerateNewKey
op.enroll.userKey.keyGen.signing.recovery.terminated.holdRevocationUntilLastCredential=false
op.enroll.userKey.keyGen.signing.recovery.terminated.revokeCert=true
op.enroll.userKey.keyGen.signing.recovery.terminated.revokeCert.reason=1
op.enroll.userKey.keyGen.signing.recovery.terminated.revokeExpiredCerts=false
op.enroll.userKey.keyGen.signing.recovery.terminated.scheme=GenerateNewKey

# Configuration for the case when we mark a token “onHold” or temporarily lost

op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.revokeCert=true
op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.revokeCert.reason=0
op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.scheme=RecoverLast
op.enroll.userKeyTemporary.keyGen.recovery.onHold.keyType.num=2
op.enroll.userKeyTemporary.keyGen.recovery.onHold.keyType.value.0=signing
op.enroll.userKeyTemporary.keyGen.recovery.onHold.keyType.value.1=encryption
op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.revokeCert=true
op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.revokeCert.reason=0
op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.scheme=GenerateNewKey
Applet Update
The following example shows how to configure a Coolkey applet update operation. This operation can be performed during format, enrollment, and PIN reset operations:
op.format.userKey.update.applet.directory=/usr/share/pki/tps/applets
op.format.userKey.update.applet.emptyToken.enable=true
op.format.userKey.update.applet.encryption=true
op.format.userKey.update.applet.requiredVersion=1.4.54de790f
Some of these options have already been demonstrated in the Format section. They provide information needed to determine if applet upgrade should be allowed, where to find the applet files, and the applet version to upgrade the token to. The version in the requiredVersion maps to a file name inside the directory.
Key Update
This operation, which can take place during format, enrollment, and PIN reset operations, allows the user to have their Global Platform key set version upgraded from the default supplied by the manufacturer.
TPS
The following options will instruct the TPS to upgrade the keyset from 1 to 2 during the next format operation requested on behalf of a given token. After this is done, the TKS must derive the three new keys that will be written to the token, Afterwards, the token must be used with the same TPS and TKS installation, otherwise it will become locked.
op.format.userKey.update.symmetricKeys.enable=true
op.format.userKey.update.symmetricKeys.requiredVersion=2
You can also specify a version lower than current to downgrade the keyset instead.
TKS
As mentioned above, the TKS must be configured to generate the new keys to write to the token. First, the new master key identifier, 02, must be mapped to its PKCS #11 object nickname in the TKS CS.cfg, as shown in the following example:
tks.mk_mappings.#02#01=internal:new_master
tks.defKeySet.mk_mappings.#02#01=internal:new_master
The above will map a key set number to an actual master key which exists in the TKS NSS database.
Master keys are identified by IDs such as 01. The TKS maps these IDs to PKCS #11 object nicknames specified in the masterKeyId part of the mapping. Therefore, the first number is updated as the master key version is updated, and the second number stays consistent.
When attempting to upgrade from version 1 to version 2, the mapping determines how to find the master key nickname which will be used to derive the 3 parts of the new key set.
The setting of internal in the above example references the name of the token where the master key resides. It could also be an external HSM module with a name such as nethsm. The strong new_master is an example of the master key nickname itself.