>From 5b402783c987b54d513124e03057caca86742f9e Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Mon, 18 May 2015 16:14:47 -0700
Subject: [PATCH] Ticket 1307 (part2 keySet mapping)  [RFE] Support multiple
 keySets for different cards for ExternalReg  This patch adds support to
 keyset mapping

---
 base/tps/shared/conf/CS.cfg.in                     | 143 +++++++++++++------
 .../server/tps/cms/TKSRemoteRequestHandler.java    |  51 ++++---
 .../org/dogtagpki/server/tps/engine/TPSEngine.java |  14 +-
 .../server/tps/mapping/BaseMappingResolver.java    |   4 +
 .../server/tps/mapping/FilterMappingParams.java    |   1 +
 .../server/tps/mapping/FilterMappingResolver.java  | 113 +++++++++------
 .../server/tps/processor/TPSEnrollProcessor.java   |  55 +++++++-
 .../server/tps/processor/TPSPinResetProcessor.java |   3 +-
 .../server/tps/processor/TPSProcessor.java         | 155 +++++++++++++++------
 9 files changed, 380 insertions(+), 159 deletions(-)

diff --git a/base/tps/shared/conf/CS.cfg.in b/base/tps/shared/conf/CS.cfg.in
index aadcbfcb18f69a43d5d351ea579d28b22abe1804..541ea0002ceff9bf9d2b8482302b94f1ca0d2901 100644
--- a/base/tps/shared/conf/CS.cfg.in
+++ b/base/tps/shared/conf/CS.cfg.in
@@ -51,13 +51,13 @@ auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred.extlogin=PASSWORD
 auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred.login=password
 auths.instance.ldap1.dnpattern=
 auths.instance.ldap1.ldapByteAttributes=
-auths.instance.ldap1.ldapStringAttributes._000=##############################################
+auths.instance.ldap1.ldapStringAttributes._000=#################################
 auths.instance.ldap1.ldapStringAttributes._001=# For isExternalReg
 auths.instance.ldap1.ldapStringAttributes._002=#   attributes will be available as
 auths.instance.ldap1.ldapStringAttributes._003=#       $<attribute>$
 auths.instance.ldap1.ldapStringAttributes._004=#   attributes example:
 auths.instance.ldap1.ldapStringAttributes._005=#mail,cn,uid,edipi,pcc,firstname,lastname,exec-edipi,exec-pcc,exec-mail,certsToAdd,tokenCUID,tokenType
-auths.instance.ldap1.attributes._006=################################# #############
+auths.instance.ldap1.ldapStringAttributes._006=#################################
 auths.instance.ldap1.ldapStringAttributes=mail,cn,uid
 auths.instance.ldap1.ldap.basedn=[LDAP_ROOT]
 auths.instance.ldap1.externalReg.certs.recoverAttributeName=certsToAdd
@@ -137,17 +137,23 @@ externalReg._004=# enable - is user external registration DB enabled?
 externalReg._005=# authId - auth id of the user external registration DB
 externalReg._006=# delegation.enable - is delegation enabled?
 externalReg._007=#
-externalReg._008=#
-externalReg._009=# format.loginRequest.enable - login required for format?
-externalReg._010=#                   1. requires no login to format
-externalReg._011=#                     or
-externalReg._012=#                   2. user record does not contain tokenType
-externalReg._013=#########################################
+externalReg._008=# default.tokenType - when set, defaults to it if not specified in user
+externalReg._009=#         record
+externalReg._010=#
+externalReg._011=# format.loginRequest.enable - login required for format?
+externalReg._012=#         1. requires no login to format
+externalReg._013=#            or
+externalReg._014=#         2. user record does not contain tokenType
+externalReg._015=#
+externalReg._016=# mappingResolver - when exists, tells whcih mappingResolver to use
+externalReg._017=#         to map to the right keySet
+externalReg._018=#########################################
 externalReg.authId=ldap1
 externalReg.default.tokenType=externalRegAddToToken
 externalReg.delegation.enable=false
 externalReg.enable=false
 externalReg.format.loginRequest.enable=true
+externalReg.mappingResolver=keySetMappingResolver
 failover.pod.enable=false
 general.applet_ext=ijc
 general.pwlength.min=16
@@ -251,6 +257,11 @@ multiroles.enable=true
 multiroles.false.groupEnforceList=Administrators,Auditors,Trusted Managers,Certificate Manager Agents,Registration Manager Agents,Data Recovery Manager Agents,Online Certificate Status Manager Agents,Token Key Service Manager Agents,Enterprise CA Administrators,Enterprise KRA Administrators,Enterprise OCSP Administrators,Enterprise RA Administrators,Enterprise TKS Administrators,Enterprise TPS Administrators,Security Domain Administrators,Subsystem Group,ClonedSubsystems
 multiroles.false.groupEnforceList=Administrators,Auditors,Trusted Managers,Certificate Manager Agents,Registration Manager Agents,Data Recovery Manager Agents,Online Certificate Status Manager Agents,Token Key Service Manager Agents,Enterprise CA Administrators,Enterprise KRA Adminstrators,Enterprise OCSP Administrators,Enterprise RA Administrators,Enterprise TKS Administrators,Enterprise TPS Administrators,Security Domain Administrators,Subsystem Group
 multiroles=true
+op.enroll._000=#########################################
+op.enroll._001=# TPS Profiles
+op.enroll._002=#  - Operations
+op.enroll._003=#   <op> - operation; enroll,pinReset,format
+op.enroll._004=#########################################
 op.enroll.delegateIEtoken._000=#########################################
 op.enroll.delegateIEtoken._001=# Enrollment for externalReg 
 op.enroll.delegateIEtoken._002=#     ID, Encryption
@@ -753,41 +764,6 @@ op.format.externalRegAddToToken.update.applet.encryption=true
 op.format.externalRegAddToToken.update.applet.requiredVersion=1.4.4d40a449
 op.format.externalRegAddToToken.update.symmetricKeys.enable=false
 op.format.externalRegAddToToken.update.symmetricKeys.requiredVersion=1
-op.enroll._000=#########################################
-op.enroll._001=# Default Operations
-op.enroll._002=#
-op.enroll._003=# op.<op>.mapping.order=<n>,<n>,<n>
-op.enroll._004=#    - contains at least one value or a series
-op.enroll._005=#      of comma-separated mapping values which
-op.enroll._006=#      are checked in sequential order
-op.enroll._007=# op.<op>.mapping.<n>.filter.tokenType=userKey
-op.enroll._008=#    - can be either empty or token type
-op.enroll._009=#      specified by the client
-op.enroll._010=# op.<op>.mapping.<n>.filter.tokenATR=
-op.enroll._011=#    - can be either empty or token ATR
-op.enroll._012=#      specified by the client
-op.enroll._013=# op.<op>.mapping.<n>.filter.appletMajorVersion=1
-op.enroll._014=#    - can be either empty or applet major version
-op.enroll._015=#      specified by the client
-op.enroll._016=# op.<op>.mapping.<n>.filter.appletMinorVersion=
-op.enroll._017=#    - can be either empty or applet minor version
-op.enroll._018=#      specified by the client
-op.enroll._019=#    - if major and minor versions are both zero, this
-op.enroll._020=#      indicate there is no applet on the token.
-op.enroll._021=# op.<op>.mapping.<n>.target.tokenType=userKey
-op.enroll._022=#    - if tokenType, tokenATR, appletMajorVersion,
-op.enroll._023=#      and appletMinorVersion are matched, value in
-op.enroll._024=#      targetTokenType will be used to locate
-op.enroll._025=#      the corresponding token profile to
-op.enroll._026=#      process the request.
-op.enroll._027=#
-op.enroll._028=# where
-op.enroll._029=#  <op> - operation; enroll,pinReset,format
-op.enroll._030=#  <n>  - mapping ID; order is specifiable
-op.enroll._031=#
-op.enroll._032=# Token ATR:
-op.enroll._033=#   Web Store  - 3B759400006202020201
-op.enroll._034=#########################################
 op.enroll.allowUnknownToken=true
 op.enroll.mappingResolver=enrollMappingResolver
 op.enroll.soKey.cuidMustMatchKDD=false
@@ -1066,7 +1042,7 @@ op.enroll.soKeyTemporary.pinReset.pin.minLen=4
 op.enroll.soKeyTemporary.pkcs11obj.compress.enable=true
 op.enroll.soKeyTemporary.pkcs11obj.enable=true
 op.enroll.soKeyTemporary.tks.conn=tks1
-op.enroll.soKeyTemporary.tks.keySet=defKeyset
+op.enroll.soKeyTemporary.tks.keySet=defKeySet
 op.enroll.soKey.temporaryToken.tokenType=soKeyTemporary
 op.enroll.soKeyTemporary.update.applet.directory=[TPS_DIR]/applets
 op.enroll.soKeyTemporary.update.applet.emptyToken.enable=true
@@ -1655,7 +1631,63 @@ preop.system.name=TPS
 preop.wizard.name=TPS Setup Wizard
 proxy.securePort=[PKI_PROXY_SECURE_PORT]
 proxy.unsecurePort=[PKI_PROXY_UNSECURE_PORT]
-mappingResolver.list=formatMappingResolver,enrollMappingResolver,pinResetMappingResolver
+mappingResolver._000=#########################################
+mappingResolver._001=# Mapping Resolver
+mappingResolver._002=#   provides a plugin framework for mappingResolver plugins.
+mappingResolver._003=#   By default, the FilterMappingResolver is provided by the
+mappingResolver._004=#   system, where if passes through the specified filters then
+mappingResolver._005=#   the "target" value is assigned as the result
+mappingResolver._006=#
+mappingResolver._007=# mappingResolver.<instance>.mapping.order=<n>,<n>,<n>
+mappingResolver._008=#    - contains at least one value or a series
+mappingResolver._009=#      of comma-separated mapping values which
+mappingResolver._010=#
+mappingResolver._011=# mappingResolver.<instance>.mapping.<n>.filter.appletMajorVersion=1
+mappingResolver._012=#    - can be either empty or applet major version
+mappingResolver._013=#      specified by the client
+mappingResolver._014=#
+mappingResolver._015=# mappingResolver.<instance>.mapping.<n>.filter.appletMinorVersion=
+mappingResolver._016=#    - can be either empty or applet minor version
+mappingResolver._017=#      specified by the client
+mappingResolver._019=#    - if major and minor versions are both zero, this
+mappingResolver._020=#      indicate there is no applet on the token.
+mappingResolver._021=#
+mappingResolver._022=# mappingResolver.<instance>.mapping.<n>.filter.tokenCUID.start
+mappingResolver._023=# mappingResolver.<instance>.mapping.<n>.filter.tokenCUID.end
+mappingResolver._024=#    - start and end sets the range of cuid the token should
+mappingResolver._025=#      fall within to pass this filter
+mappingResolver._026=#
+mappingResolver._027=# mappingResolver.<instance>.mapping.<n>.filter.tokenATR=
+mappingResolver._028=#    - can be either empty or token ATR
+mappingResolver._029=#      specified by the client
+mappingResolver._030=#
+mappingResolver._031=# mappingResolver.<instance>.mapping.<n>.filter.tokenType=
+mappingResolver._032=#    - tokenType can be set as an extension in the client request.
+mappingResolver._033=#      It can be empty.
+mappingResolver._034=#      When such extension is set, it must match the value
+mappingResolver._035=#      in the filter if it is specified
+mappingResolver._036=#
+mappingResolver._037=# mappingResolver.<instance>.mapping.<n>.filter.keySet=
+mappingResolver._038=#    - keySet can be set as an extension in the client request.
+mappingResolver._039=#      It can be empty.
+mappingResolver._040=#      When such extension is set, it must match the value
+mappingResolver._041=#      in the filter if it is specified
+mappingResolver._042=#
+mappingResolver._043=# mappingResolver.<instance>.mapping.<n>.target.tokenType=userKey
+mappingResolver._044=#    - if tokenType, tokenATR, appletMajorVersion,
+mappingResolver._045=#      and appletMinorVersion are matched, value in
+mappingResolver._046=#      targetTokenType will be used to locate
+mappingResolver._047=#      the corresponding token profile to
+mappingResolver._048=#      process the request.
+mappingResolver._049=#
+mappingResolver._050=# where
+mappingResolver._051=#  <instance> - mapping resolver instance
+mappingResolver._052=#  <n>  - mapping ID; order is specifiable
+mappingResolver._053=#
+mappingResolver._054=# Token ATR:
+mappingResolver._055=#   Web Store  - 3B759400006202020201
+mappingResolver._056=#########################################
+mappingResolver.list=formatMappingResolver,enrollMappingResolver,pinResetMappingResolver,keySetMappingResolver
 mappingResolver.enrollMappingResolver.class_id=filterMappingResolverImpl
 mappingResolver.enrollMappingResolver.mapping.0.filter.appletMajorVersion=1
 mappingResolver.enrollMappingResolver.mapping.0.filter.appletMinorVersion=
@@ -1738,6 +1770,27 @@ mappingResolver.pinResetMappingResolver.mapping.0.filter.tokenCUID.start=
 mappingResolver.pinResetMappingResolver.mapping.0.filter.tokenType=
 mappingResolver.pinResetMappingResolver.mapping.0.target.tokenType=userKey
 mappingResolver.pinResetMappingResolver.mapping.order=0
+mappingResolver.keySetMappingResolver._000=#########################################
+mappingResolver.keySetMappingResolver._001=# Below is just an example for keySet mapping;
+mappingResolver.keySetMappingResolver._002=# keySet mapping allows support for multiple
+mappingResolver.keySetMappingResolver._003=# keySets for different cards
+mappingResolver.keySetMappingResolver._004=#########################################
+mappingResolver.keySetMappingResolver.class_id=filterMappingResolverImpl
+mappingResolver.keySetMappingResolver.mapping.0.filter.appletMajorVersion=1
+mappingResolver.keySetMappingResolver.mapping.0.filter.appletMinorVersion=
+mappingResolver.keySetMappingResolver.mapping.0.filter.tokenATR=
+mappingResolver.keySetMappingResolver.mapping.0.filter.tokenCUID.end=
+mappingResolver.keySetMappingResolver.mapping.0.filter.tokenCUID.start=
+mappingResolver.keySetMappingResolver.mapping.0.filter.keySet=jForte
+mappingResolver.keySetMappingResolver.mapping.0.target.keySet=jForte
+mappingResolver.keySetMappingResolver.mapping.1.filter.appletMajorVersion=
+mappingResolver.keySetMappingResolver.mapping.1.filter.appletMinorVersion=
+mappingResolver.keySetMappingResolver.mapping.1.filter.tokenATR=
+mappingResolver.keySetMappingResolver.mapping.1.filter.tokenCUID.end=
+mappingResolver.keySetMappingResolver.mapping.1.filter.tokenCUID.start=
+mappingResolver.keySetMappingResolver.mapping.1.filter.keySet=defKeySet
+mappingResolver.keySetMappingResolver.mapping.1.target.keySet=defKeySet
+mappingResolver.keySetMappingResolver.mapping.order=0,1
 registry.file=[PKI_INSTANCE_PATH]/conf/tps/registry.cfg
 selftests._000=##
 selftests._001=## Self Tests
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
index b10ca772ecd791ffd8cd62317d6474a841604273..23fb75cc10d9ef16e2377da41fa5d1f33d514244 100644
--- a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
@@ -59,20 +59,24 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
      *   TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
      *   TKSComputeSessionKeyResponse responseObj =
      *     tksReq.computeSessionKey(
+     *      kdd,
      *      cuid,
      *      keyInfo,
      *      card_challenge,
      *      card_cryptogram,
-     *      host_challenge);
+     *      host_challenge
+     *      tokenType);
      *   - on success return, one can say
      *    TPSBuffer value = responseObj.getSessionKey();
      *      to get response param value session key
      *
+     * @param kdd key derivation data
      * @param cuid token cuid
      * @param keyInfo keyInfo
      * @param card_challenge card challenge
      * @param card_cryptogram card cryptogram
      * @param host_challenge host challenge
+     * @param tokenType
      * @return response TKSComputeSessionKeyResponse class object
      */
     public TKSComputeSessionKeyResponse computeSessionKey(
@@ -82,7 +86,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
             TPSBuffer card_challenge,
             TPSBuffer card_cryptogram,
             TPSBuffer host_challenge,
-            String tokenType)
+            String tokenType, String inKeySet)
             throws EBaseException {
 
         CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): begins.");
@@ -97,8 +101,9 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
                 conf.getBoolean("op.enroll." +
                         tokenType + ".keyGen.encryption.serverKeygen.enable",
                         false);
-        String keySet =
-                conf.getString("connector." + connid + "keySet", "defKeySet");
+        String keySet = inKeySet;
+        if (inKeySet == null)
+            keySet = conf.getString("connector." + connid + "keySet", "defKeySet");
 
         TPSSubsystem subsystem =
                 (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
@@ -214,20 +219,22 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
      *   TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
      *   TKSComputeSessionKeyResponse responseObj =
      *     tksReq.computeSessionKey(
+     *      kdd,
      *      cuid,
      *      keyInfo,
-     *      card_challenge,
-     *      card_cryptogram,
-     *      host_challenge);
+     *      sequenceCounter,
+     *      derivationConstant,
+     *      String tokenType)
      *   - on success return, one can say
      *    TPSBuffer value = responseObj.getSessionKey();
      *      to get response param value session key
      *
+     * @param kdd key derivation data
      * @param cuid token cuid
      * @param keyInfo keyInfo
-     * @param card_challenge card challenge
-     * @param card_cryptogram card cryptogram
-     * @param host_challenge host challenge
+     * @param sequenceCounter
+     * @param derivationConstant
+     * @param tokenType
      * @return response TKSComputeSessionKeyResponse class object
      */
     public TKSComputeSessionKeyResponse computeSessionKeySCP02(
@@ -236,7 +243,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
             TPSBuffer keyInfo,
             TPSBuffer sequenceCounter,
             TPSBuffer derivationConstant,
-            String tokenType)
+            String tokenType, String inKeySet)
             throws EBaseException {
 
         CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): begins.");
@@ -252,8 +259,9 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
                 conf.getBoolean("op.enroll." +
                         tokenType + ".keyGen.encryption.serverKeygen.enable",
                         false);
-        String keySet =
-                conf.getString("connector." + connid + "keySet", "defKeySet");
+        String keySet = inKeySet;
+        if (inKeySet == null)
+            keySet = conf.getString("connector." + connid + "keySet", "defKeySet");
 
         TPSSubsystem subsystem =
                 (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
@@ -365,10 +373,10 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
      * @param cuid token cuid
      * @return response TKSCreateKeySetDataResponse class object
      */
-    public TKSCreateKeySetDataResponse createKeySetData(
+    public TKSCreateKeySetDataResponse createKeySetData (
             TPSBuffer NewMasterVer,
             TPSBuffer version,
-            TPSBuffer cuid, TPSBuffer kdd, int protocol, TPSBuffer wrappedDekSessionKey)
+            TPSBuffer cuid, TPSBuffer kdd, int protocol, TPSBuffer wrappedDekSessionKey, String inKeySet)
             throws EBaseException {
         CMS.debug("TKSRemoteRequestHandler: createKeySetData(): begins.");
         if (cuid == null || NewMasterVer == null || version == null) {
@@ -376,8 +384,9 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
         }
 
         IConfigStore conf = CMS.getConfigStore();
-        String keySet =
-                conf.getString("connector." + connid + "keySet", "defKeySet");
+        String keySet = inKeySet;
+        if (inKeySet == null)
+            keySet = conf.getString("connector." + connid + "keySet", "defKeySet");
 
         TPSSubsystem subsystem =
                 (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
@@ -527,6 +536,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
      *    TPSBuffer value = responseObj.getEncryptedData();
      *      to get response param value encrypted data
      *
+     * @param kdd key derivation data
      * @param cuid token cuid
      * @param version keyInfo
      * @param inData data to be encrypted
@@ -536,7 +546,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
             TPSBuffer kdd,
             TPSBuffer cuid,
             TPSBuffer version,
-            TPSBuffer inData)
+            TPSBuffer inData, String inKeySet)
             throws EBaseException {
         CMS.debug("TKSRemoteRequestHandler: encryptData(): begins.");
         if (cuid == null || kdd == null || version == null || inData == null) {
@@ -545,8 +555,9 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
 
         IConfigStore conf = CMS.getConfigStore();
 
-        String keySet =
-                conf.getString("connector." + connid + "keySet", "defKeySet");
+        String keySet = inKeySet;
+        if (inKeySet == null)
+            keySet = conf.getString("connector." + connid + "keySet", "defKeySet");
 
         TPSSubsystem subsystem =
                 (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
index b24f85d60bad7969cd5dde6e7e9323564639379b..3f45aed061ea740737196335537140082b625f5a 100644
--- a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
+++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -170,7 +170,7 @@ public class TPSEngine {
     public static final String RENEWAL_OP = "renewal";
 
     public static final String OP_FORMAT_PREFIX = "op." + FORMAT_OP;
-    public static final String CFG_PROFILE_RESOLVER = "mappingResolver";
+    public static final String CFG_MAPPING_RESOLVER = "mappingResolver";
     public static final String CFG_DEF_FORMAT_PROFILE_RESOLVER = "formatMappingResolver";
     public static final String CFG_DEF_ENROLL_PROFILE_RESOLVER = "enrollMappingResolver";
     public static final String CFG_DEF_PIN_RESET_PROFILE_RESOLVER = "pinResetMappingResolver";
@@ -219,7 +219,7 @@ public class TPSEngine {
             TPSBuffer sequenceCounter,
             TPSBuffer derivationConstant,
             String connId,
-            String tokenType)
+            String tokenType, String inKeySet)
             throws TPSException {
 
         if (cuid == null || kdd == null || keyInfo == null || sequenceCounter == null || derivationConstant == null
@@ -235,7 +235,7 @@ public class TPSEngine {
         TKSComputeSessionKeyResponse resp = null;
         try {
             tks = new TKSRemoteRequestHandler(connId);
-            resp = tks.computeSessionKeySCP02(kdd,cuid, keyInfo, sequenceCounter, derivationConstant, tokenType);
+            resp = tks.computeSessionKeySCP02(kdd,cuid, keyInfo, sequenceCounter, derivationConstant, tokenType, inKeySet);
         } catch (EBaseException e) {
             throw new TPSException("TPSEngine.computeSessionKeySCP02: Error computing session key!" + e,
                     TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
@@ -258,7 +258,7 @@ public class TPSEngine {
             TPSBuffer host_challenge,
             TPSBuffer card_cryptogram,
             String connId,
-            String tokenType) throws TPSException {
+            String tokenType, String inKeySet) throws TPSException {
 
         if (cuid == null || kdd == null || keyInfo == null || card_challenge == null || host_challenge == null
                 || card_cryptogram == null || connId == null || tokenType == null) {
@@ -275,7 +275,7 @@ public class TPSEngine {
         TKSComputeSessionKeyResponse resp = null;
         try {
             tks = new TKSRemoteRequestHandler(connId);
-            resp = tks.computeSessionKey(kdd,cuid, keyInfo, card_challenge, card_cryptogram, host_challenge, tokenType);
+            resp = tks.computeSessionKey(kdd,cuid, keyInfo, card_challenge, card_cryptogram, host_challenge, tokenType, inKeySet);
         } catch (EBaseException e) {
             throw new TPSException("TPSEngine.computeSessionKey: Error computing session key!" + e,
                     TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
@@ -378,7 +378,7 @@ public class TPSEngine {
 
     }
 
-    public TPSBuffer createKeySetData(TPSBuffer newMasterVersion, TPSBuffer oldVersion, int protocol, TPSBuffer cuid, TPSBuffer kdd, TPSBuffer wrappedDekSessionKey, String connId)
+    public TPSBuffer createKeySetData(TPSBuffer newMasterVersion, TPSBuffer oldVersion, int protocol, TPSBuffer cuid, TPSBuffer kdd, TPSBuffer wrappedDekSessionKey, String connId, String inKeyset)
             throws TPSException {
         CMS.debug("TPSEngine.createKeySetData. entering...");
 
@@ -393,7 +393,7 @@ public class TPSEngine {
 
         try {
             tks = new TKSRemoteRequestHandler(connId);
-            resp = tks.createKeySetData(newMasterVersion, oldVersion, cuid, kdd, protocol,wrappedDekSessionKey);
+            resp = tks.createKeySetData(newMasterVersion, oldVersion, cuid, kdd, protocol,wrappedDekSessionKey, inKeyset);
         } catch (EBaseException e) {
 
             throw new TPSException("TPSEngine.createKeySetData, failure to get key set data from TKS",
diff --git a/base/tps/src/org/dogtagpki/server/tps/mapping/BaseMappingResolver.java b/base/tps/src/org/dogtagpki/server/tps/mapping/BaseMappingResolver.java
index 9b36727be0edc5ce26626173103c1f5dc4ab07f5..e5c03cc9ad38d4192292588da60c9828667107cc 100644
--- a/base/tps/src/org/dogtagpki/server/tps/mapping/BaseMappingResolver.java
+++ b/base/tps/src/org/dogtagpki/server/tps/mapping/BaseMappingResolver.java
@@ -35,4 +35,8 @@ public abstract class BaseMappingResolver {
 
     public abstract String getResolvedMapping(FilterMappingParams pPram)
             throws TPSException;
+
+    public abstract String getResolvedMapping(FilterMappingParams mappingParams, String nameToMap)
+            throws TPSException;
+
 }
diff --git a/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingParams.java b/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingParams.java
index ee89826fb35da6ba9773e46a9151c8f084ee9c17..0ca40e2ad540cbc6f2c5fa452c1fcf821efbd9ba 100644
--- a/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingParams.java
+++ b/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingParams.java
@@ -40,6 +40,7 @@ public class FilterMappingParams {
     public static final String FILTER_PARAM_MSN = "fp_msn";
     public static final String FILTER_PARAM_EXT_TOKEN_TYPE = "fp_ext_tokenType";
     public static final String FILTER_PARAM_EXT_TOKEN_ATR = "fp_ext_tokenATR";
+    public static final String FILTER_PARAM_EXT_KEY_SET = "fp_ext_keySet";
 
     private HashMap<String, String> content = new HashMap<String, String>();
 
diff --git a/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingResolver.java b/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingResolver.java
index c1fcb974e6bb0d8788778669c050329507d6683c..38ea29c48d33269df37ed48d2d2d70acaa68b23b 100644
--- a/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingResolver.java
+++ b/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingResolver.java
@@ -21,8 +21,17 @@ public class FilterMappingResolver extends BaseMappingResolver {
 
     public String getResolvedMapping(FilterMappingParams mappingParams)
             throws TPSException {
-        String method = "FilterMappingResolver.getResolvedMapping: ";
+        //map tokenType by default
+        return getResolvedMapping(mappingParams, "tokenType");
+    }
+
+    // from TPS: RA_Processor::ProcessMappingFilter
+    public String getResolvedMapping(FilterMappingParams mappingParams, String nameToMap)
+            throws TPSException {
+        String method = "FilterMappingResolver.getResolvedMapping for "+ nameToMap + ": ";
         String tokenType = null;
+        String keySet = null;
+
         String mappingOrder = null;
         int major_version = 0;
         int minor_version = 0;
@@ -30,6 +39,9 @@ public class FilterMappingResolver extends BaseMappingResolver {
         // String msn = null;
         String extTokenType = null;
         String extTokenATR = null;
+        String extKeySet = null;
+
+        String targetMappedName = null;
 
         CMS.debug(method + " starts");
 
@@ -45,10 +57,20 @@ public class FilterMappingResolver extends BaseMappingResolver {
         // they don't necessarily have extension
         try {
             extTokenType = mappingParams.getString(FilterMappingParams.FILTER_PARAM_EXT_TOKEN_TYPE);
-            extTokenATR =  mappingParams.getString(FilterMappingParams.FILTER_PARAM_EXT_TOKEN_ATR);
         } catch (TPSException e) {
-            CMS.debug(method + " OK to not have extension. Continue.");
+            CMS.debug(method + " OK to not have tokenType extension. Continue.");
         }
+        try {
+            extTokenATR = mappingParams.getString(FilterMappingParams.FILTER_PARAM_EXT_TOKEN_ATR);
+        } catch (TPSException e) {
+            CMS.debug(method + " OK to not have tokenATR extension. Continue.");
+        }
+        try {
+            extKeySet = mappingParams.getString(FilterMappingParams.FILTER_PARAM_EXT_KEY_SET);
+        } catch (TPSException e) {
+            CMS.debug(method + " OK to not have keySet extension. Continue.");
+        }
+
 
         CMS.debug(method + " mapping params retrieved.");
 
@@ -72,22 +94,21 @@ public class FilterMappingResolver extends BaseMappingResolver {
                     TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
         }
 
-        String targetTokenType = null;
 
         for (String mappingId : mappingOrder.split(",")) {
 
             CMS.debug(method + "  mapping: " + mappingId);
 
-            String mappingConfigName = prefix + ".mapping." + mappingId + ".target.tokenType";
+            String mappingConfigName = prefix + ".mapping." + mappingId + ".target." + nameToMap;
 
             CMS.debug(method + "  mappingConfigName: " + mappingConfigName);
 
             //We need this to exist.
             try {
-                targetTokenType = configStore.getString(mappingConfigName);
+                targetMappedName = configStore.getString(mappingConfigName);
             } catch (EPropertyNotFound e) {
                 throw new TPSException(
-                        method + " Token Type configuration incorrect! No target token type config value found! Config: "
+                        method + " Mapping Resolver configuration incorrect! No target name config value found! Config: "
                                 + mappingConfigName,
                         TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
 
@@ -97,13 +118,15 @@ public class FilterMappingResolver extends BaseMappingResolver {
                                 + mappingConfigName,
                         TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
             }
+            CMS.debug(method + "  targetMappedName: " + targetMappedName);
 
+            /*
+             * For this and remaining names, it is not automatically an error if we don't get anything back
+             * from the config.  It is just not considered.
+             */
             mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenType";
-
             CMS.debug(method + "  mappingConfigName: " + mappingConfigName);
 
-            //For this and remaining cases, it is not automatically an error if we don't get anything back
-            // from the config.
             try {
                 tokenType = configStore.getString(mappingConfigName, null);
             } catch (EBaseException e) {
@@ -111,10 +134,8 @@ public class FilterMappingResolver extends BaseMappingResolver {
                         method + " Internal error obtaining config value. Config: "
                                 + mappingConfigName,
                         TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
-
             }
-
-            CMS.debug(method + "  targetTokenType: " + targetTokenType);
+            CMS.debug(method + " tokenType: " + tokenType);
 
             if (tokenType != null && tokenType.length() > 0) {
 
@@ -122,18 +143,37 @@ public class FilterMappingResolver extends BaseMappingResolver {
                     continue;
                 }
 
-                //String extTokenType = extensions.get("tokenType");
-                //if (extTokenType == null) {
-                //    continue;
-                //}
-
                 if (!extTokenType.equals(tokenType)) {
                     continue;
                 }
             }
 
+            mappingConfigName = prefix + ".mapping." + mappingId + ".filter.keySet";
+            CMS.debug(method + " mappingConfigName: " + mappingConfigName);
+
+            try {
+                keySet = configStore.getString(mappingConfigName, null);
+            } catch (EBaseException e) {
+                throw new TPSException(
+                        method + " Internal error obtaining config value. Config: "
+                                + mappingConfigName,
+                        TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
+            }
+
+            CMS.debug(method + " keySet: " + keySet);
+
+            if (keySet != null && keySet.length() > 0) {
+
+                if (extKeySet == null) {
+                    continue;
+                }
+
+                if (!extKeySet.equals(keySet)) {
+                    continue;
+                }
+            }
+
             mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenATR";
-
             CMS.debug(method + " mappingConfigName: " + mappingConfigName);
 
             String tokenATR = null;
@@ -154,20 +194,12 @@ public class FilterMappingResolver extends BaseMappingResolver {
                     continue;
                 }
 
-                //String extTokenATR = extensions.get("tokenATR");
-
-                //if (extTokenATR == null) {
-                //    continue;
-                //}
-
                 if (!extTokenATR.equals(tokenATR)) {
                     continue;
                 }
-
             }
 
             mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenCUID.start";
-
             CMS.debug(method + " mappingConfigName: " + mappingConfigName);
 
             String tokenCUIDStart = null;
@@ -182,7 +214,7 @@ public class FilterMappingResolver extends BaseMappingResolver {
                         TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
             }
 
-            CMS.debug(method + "  tokenCUIDStart: " + tokenCUIDStart);
+            CMS.debug(method + " tokenCUIDStart: " + tokenCUIDStart);
 
             if (tokenCUIDStart != null && tokenCUIDStart.length() > 0) {
                 if (cuid == null) {
@@ -200,8 +232,7 @@ public class FilterMappingResolver extends BaseMappingResolver {
             }
 
             mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenCUID.end";
-
-            CMS.debug(method + "  mappingConfigName: " + mappingConfigName);
+            CMS.debug(method + " mappingConfigName: " + mappingConfigName);
 
             String tokenCUIDEnd = null;
             try {
@@ -213,7 +244,7 @@ public class FilterMappingResolver extends BaseMappingResolver {
                         TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
             }
 
-            CMS.debug(method + "  tokenCUIDEnd: " + tokenCUIDEnd);
+            CMS.debug(method + " tokenCUIDEnd: " + tokenCUIDEnd);
 
             if (tokenCUIDEnd != null && tokenCUIDEnd.length() > 0) {
                 if (cuid == null) {
@@ -231,8 +262,7 @@ public class FilterMappingResolver extends BaseMappingResolver {
             }
 
             mappingConfigName = prefix + ".mapping." + mappingId + ".filter.appletMajorVersion";
-
-            CMS.debug(method + "  mappingConfigName: " + mappingConfigName);
+            CMS.debug(method + " mappingConfigName: " + mappingConfigName);
 
             String majorVersion = null;
             String minorVersion = null;
@@ -246,7 +276,7 @@ public class FilterMappingResolver extends BaseMappingResolver {
                         TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
             }
 
-            CMS.debug(method + "  majorVersion: " + majorVersion);
+            CMS.debug(method + " majorVersion: " + majorVersion);
             if (majorVersion != null && majorVersion.length() > 0) {
 
                 int major = Integer.parseInt(majorVersion);
@@ -257,7 +287,6 @@ public class FilterMappingResolver extends BaseMappingResolver {
             }
 
             mappingConfigName = prefix + ".mapping." + mappingId + ".filter.appletMinorVersion";
-
             CMS.debug(method + "  mappingConfigName: " + mappingConfigName);
 
             try {
@@ -268,7 +297,7 @@ public class FilterMappingResolver extends BaseMappingResolver {
                                 + mappingConfigName,
                         TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
             }
-            CMS.debug(method + "  minorVersion " + minorVersion);
+            CMS.debug(method + " minorVersion " + minorVersion);
 
             if (minorVersion != null && minorVersion.length() > 0) {
 
@@ -279,18 +308,18 @@ public class FilterMappingResolver extends BaseMappingResolver {
                 }
             }
 
-            //if we make it this far, we have a token type
-            CMS.debug(method + " Selected Token type: " + targetTokenType);
+            //if we make it this far, we have a mapped name
+            CMS.debug(method + " Selected Token type: " + targetMappedName);
             break;
         }
 
-        if (targetTokenType == null) {
-            CMS.debug(method + " end found: " + targetTokenType);
-            throw new TPSException(method + " Can't find token type!",
+        if (targetMappedName == null) {
+            CMS.debug(method + " ends, found: " + targetMappedName);
+            throw new TPSException(method + " Can't map to target name!",
                     TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
         }
 
-        return targetTokenType;
+        return targetMappedName;
 
     }
 
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
index 75e2d0e6aa005ad57cf6e4cf05b74d4a0ad3ce1b..8c7535626dfb516c65b8760831864310a2938547 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -40,6 +40,8 @@ import org.dogtagpki.server.tps.main.ExternalRegAttrs;
 import org.dogtagpki.server.tps.main.ExternalRegCertToRecover;
 import org.dogtagpki.server.tps.main.ObjectSpec;
 import org.dogtagpki.server.tps.main.PKCS11Obj;
+import org.dogtagpki.server.tps.mapping.BaseMappingResolver;
+import org.dogtagpki.server.tps.mapping.FilterMappingParams;
 import org.dogtagpki.tps.main.TPSBuffer;
 import org.dogtagpki.tps.main.TPSException;
 import org.dogtagpki.tps.main.Util;
@@ -225,17 +227,62 @@ public class TPSEnrollProcessor extends TPSProcessor {
                     throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION);
                 }
             }
+
+            CMS.debug("In TPSEnrollProcessor.enroll isExternalReg: about to process keySet resolver");
+            /*
+             * Note: externalReg.mappingResolver=none indicates no resolver
+             *    plugin used
+             */
+            try {
+            String resolverInstName = getKeySetResolverInstanceName();
+
+                if (!resolverInstName.equals("none") && (selectedKeySet == null)) {
+                    FilterMappingParams mappingParams = createFilterMappingParams(resolverInstName,
+                            appletInfo.getCUIDhexString(), appletInfo.getMSNString(),
+                            appletInfo.getMajorVersion(), appletInfo.getMinorVersion());
+                    TPSSubsystem subsystem =
+                            (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+                    BaseMappingResolver resolverInst =
+                            subsystem.getMappingResolverManager().getResolverInstance(resolverInstName);
+                    String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet");
+                    setSelectedKeySet(keySet);
+                    CMS.debug(method + " resolved keySet: " + keySet);
+                }
+            } catch (TPSException e) {
+                auditMsg = e.toString();
+                tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
+                        "failure");
+
+                throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+            }
         } else {
             CMS.debug("In TPSEnrollProcessor.enroll isExternalReg: OFF");
             /*
-             * Note: op.enroll.tokenProfileResolver=none indicates no resolver
+             * Note: op.enroll.mappingResolver=none indicates no resolver
              *    plugin used (tokenType resolved perhaps via authentication)
              */
+            try {
             String resolverInstName = getResolverInstanceName();
 
-            tokenType = resolveTokenProfile(resolverInstName, appletInfo.getCUIDhexString(), appletInfo.getMSNString(),
-                    appletInfo.getMajorVersion(), appletInfo.getMinorVersion());
-            CMS.debug(method + " resolved tokenType: " + tokenType);
+                if (!resolverInstName.equals("none") && (selectedTokenType == null)) {
+                    FilterMappingParams mappingParams = createFilterMappingParams(resolverInstName,
+                            appletInfo.getCUIDhexString(), appletInfo.getMSNString(),
+                            appletInfo.getMajorVersion(), appletInfo.getMinorVersion());
+                    TPSSubsystem subsystem =
+                            (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+                    BaseMappingResolver resolverInst =
+                            subsystem.getMappingResolverManager().getResolverInstance(resolverInstName);
+                    tokenType = resolverInst.getResolvedMapping(mappingParams);
+                    setSelectedTokenType(tokenType);
+                    CMS.debug(method + " resolved tokenType: " + tokenType);
+                }
+            } catch (TPSException e) {
+                auditMsg = e.toString();
+                tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
+                        "failure");
+
+                throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+            }
         }
 
         checkProfileStateOK();
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
index 5d029a180fffdec599fdd2774f9d8154bfaed763..10c74ff18a53ba0ce2357096f0b6dd29a3ce075a 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
@@ -25,6 +25,7 @@ import org.dogtagpki.server.tps.channel.SecureChannel;
 import org.dogtagpki.server.tps.dbs.ActivityDatabase;
 import org.dogtagpki.server.tps.dbs.TokenRecord;
 import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.server.tps.mapping.FilterMappingParams;
 import org.dogtagpki.tps.main.TPSException;
 import org.dogtagpki.tps.msg.BeginOpMsg;
 import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
@@ -103,7 +104,7 @@ public class TPSPinResetProcessor extends TPSProcessor {
 
         String tokenType = null;
 
-        tokenType = resolveTokenProfile(resolverInstName, appletInfo.getCUIDhexString(), appletInfo.getMSNString(),
+        FilterMappingParams mappingParams = createFilterMappingParams(resolverInstName, appletInfo.getCUIDhexString(), appletInfo.getMSNString(),
                 appletInfo.getMajorVersion(), appletInfo.getMinorVersion());
         CMS.debug(method + ": resolved tokenType: " + tokenType);
 
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index 00303432cdeb96f80f62f9ed228c627947178163..5347e5ad29952c8db5de43473cb4dd99f1804092 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -118,6 +118,7 @@ public class TPSProcessor {
     protected TPSSession session;
     //protected TokenRecord tokenRecord;
     protected String selectedTokenType;
+    protected String selectedKeySet;
     IAuthToken authToken;
     List<String> ldapStringAttrs;
 
@@ -182,6 +183,22 @@ public class TPSProcessor {
         return selectedTokenType;
     }
 
+    protected void setSelectedKeySet(String theKeySet) {
+
+        if (theKeySet == null) {
+            throw new NullPointerException("TPSProcessor.setSelectedKeySet: Attempt to set invalid null key set!");
+        }
+        CMS.debug("TPS_Processor.setSelectedKeySet: keySet=" +
+                theKeySet);
+        selectedKeySet = theKeySet;
+
+    }
+
+    public String getSelectedKeySet() {
+        return selectedKeySet;
+    }
+
+
     protected TPSBuffer extractTokenMSN(TPSBuffer cplc_data) throws TPSException {
         //Just make sure no one is inputing bogus cplc_data
         if (cplc_data == null || cplc_data.size() < CPLC_DATA_SIZE) {
@@ -370,7 +387,7 @@ public class TPSProcessor {
 
         try {
             tks = new TKSRemoteRequestHandler(connId);
-            data = tks.encryptData(appletInfo.getKDD(),appletInfo.getCUID(), keyInfo, plaintextChallenge);
+            data = tks.encryptData(appletInfo.getKDD(),appletInfo.getCUID(), keyInfo, plaintextChallenge, getSelectedKeySet());
         } catch (EBaseException e) {
             throw new TPSException("TPSProcessor.encryptData: Erorr getting wrapped data from TKS!",
                     TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
@@ -616,7 +633,7 @@ public class TPSProcessor {
 
             resp = engine.computeSessionKey(keyDiversificationData, appletInfo.getCUID(), keyInfoData,
                     cardChallenge, hostChallenge, cardCryptogram,
-                    connId, getSelectedTokenType());
+                    connId, getSelectedTokenType(), getSelectedKeySet());
 
             hostCryptogram = resp.getHostCryptogram();
 
@@ -691,7 +708,7 @@ public class TPSProcessor {
             CMS.debug("TPSProcessor.generateSecureChannel Trying secure channel protocol 02");
             respEnc02 = engine.computeSessionKeySCP02(keyDiversificationData, appletInfo.getCUID(), keyInfoData,
                     sequenceCounter, new TPSBuffer(SecureChannel.ENCDerivationConstant),
-                    connId, getSelectedTokenType());
+                    connId, getSelectedTokenType(), getSelectedKeySet());
 
             TPSBuffer encSessionKeyWrappedSCP02 = respEnc02.getSessionKey();
             encSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
@@ -705,7 +722,7 @@ public class TPSProcessor {
 
             respCMac02 = engine.computeSessionKeySCP02(keyDiversificationData, appletInfo.getCUID(), keyInfoData,
                     sequenceCounter, new TPSBuffer(SecureChannel.C_MACDerivationConstant),
-                    connId, getSelectedTokenType());
+                    connId, getSelectedTokenType(), getSelectedKeySet());
 
             TPSBuffer cmacSessionKeyWrappedSCP02 = respCMac02.getSessionKey();
 
@@ -720,7 +737,7 @@ public class TPSProcessor {
 
             respRMac02 = engine.computeSessionKeySCP02(keyDiversificationData, appletInfo.getCUID(), keyInfoData,
                     sequenceCounter, new TPSBuffer(SecureChannel.R_MACDerivationConstant),
-                    connId, getSelectedTokenType());
+                    connId, getSelectedTokenType(), getSelectedKeySet());
 
             TPSBuffer rmacSessionKeyWrappedSCP02 = respRMac02.getSessionKey();
 
@@ -735,7 +752,7 @@ public class TPSProcessor {
 
             respDek02 = engine.computeSessionKeySCP02(keyDiversificationData, appletInfo.getCUID(), keyInfoData,
                     sequenceCounter, new TPSBuffer(SecureChannel.DEKDerivationConstant),
-                    connId, getSelectedTokenType());
+                    connId, getSelectedTokenType(), getSelectedKeySet());
 
             CMS.debug("Past engine.computeSessionKeyData: After dek key request.");
 
@@ -1623,7 +1640,8 @@ public class TPSProcessor {
                 erAttrs.addCertToRecover(erCert);
             }
         } else {
-            CMS.debug(method + ": certsToRecover attribute not found");
+            CMS.debug(method + ": certsToRecover attribute " + erAttrs.ldapAttrNameCertsToRecover +
+                    " not found");
         }
 
         /*
@@ -1720,7 +1738,6 @@ public class TPSProcessor {
                 + " app_major_version: " + app_major_version + " app_minor_version: " + app_minor_version);
 
         String tokenType = "tokenType";
-        String resolverInstName = getResolverInstanceName();
 
         IAuthCredentials userCred =
                 new com.netscape.certsrv.authentication.AuthCredentials();
@@ -1816,6 +1833,33 @@ public class TPSProcessor {
                 session.setExternalRegAttrs(erAttrs);
                 setSelectedTokenType(erAttrs.getTokenType());
             }
+            CMS.debug("In TPSProcessor.format: isExternalReg: about to process keySet resolver");
+            /*
+             * Note: externalReg.mappingResolver=none indicates no resolver
+             *    plugin used
+             */
+            try {
+            String resolverInstName = getKeySetResolverInstanceName();
+
+                if (!resolverInstName.equals("none") && (selectedKeySet == null)) {
+                    FilterMappingParams mappingParams = createFilterMappingParams(resolverInstName,
+                            appletInfo.getCUIDhexString(), appletInfo.getMSNString(),
+                            appletInfo.getMajorVersion(), appletInfo.getMinorVersion());
+                    TPSSubsystem subsystem =
+                            (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+                    BaseMappingResolver resolverInst =
+                            subsystem.getMappingResolverManager().getResolverInstance(resolverInstName);
+                    String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet");
+                    setSelectedKeySet(keySet);
+                    CMS.debug("In TPSProcessor.format: resolved keySet: " + keySet);
+                }
+            } catch (TPSException e) {
+                auditMsg = e.toString();
+                tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
+                        "failure");
+
+                throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+            }
         } else {
             CMS.debug("In TPSProcessor.format isExternalReg: OFF");
             /*
@@ -1824,7 +1868,19 @@ public class TPSProcessor {
              */
 
             try {
-                tokenType = resolveTokenProfile(resolverInstName, cuid, msn, major_version, minor_version);
+                String resolverInstName = getResolverInstanceName();
+
+                if (!resolverInstName.equals("none") && (selectedKeySet == null)) {
+                    FilterMappingParams mappingParams  = createFilterMappingParams(resolverInstName, cuid, msn, major_version, minor_version);
+
+                    TPSSubsystem subsystem =
+                            (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+                    BaseMappingResolver resolverInst =
+                            subsystem.getMappingResolverManager().getResolverInstance(resolverInstName);
+                    tokenType = resolverInst.getResolvedMapping(mappingParams);
+                    setSelectedTokenType(tokenType);
+                    CMS.debug("In TPSProcessor.format: resolved tokenType: " + tokenType);
+                }
             } catch (TPSException e) {
                 auditMsg = e.toString();
                 tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
@@ -2033,7 +2089,7 @@ public class TPSProcessor {
         }
 
         String config = opPrefix +
-                "." + TPSEngine.CFG_PROFILE_RESOLVER;
+                "." + TPSEngine.CFG_MAPPING_RESOLVER;
 
         CMS.debug("TPSProcessor.getResolverInstanceName: config: " + config);
         try {
@@ -2048,6 +2104,33 @@ public class TPSProcessor {
         return resolverInstName;
     }
 
+    protected String getKeySetResolverInstanceName() throws TPSException {
+        String method = "TPSProcessor.getKeySetResolverInstanceName: ";
+        CMS.debug(method + " begins");
+        IConfigStore configStore = CMS.getConfigStore();
+        String resolverInstName = null;
+
+        if (!isExternalReg) {
+            CMS.debug(method + "externalReg not enabled; keySet mapping currently only supported in externalReg.");
+            return null;
+        }
+        String config = "externalReg" +
+                "." + TPSEngine.CFG_MAPPING_RESOLVER;
+
+        CMS.debug(method + " config: " + config);
+        try {
+            resolverInstName = configStore.getString(config, "none");
+        } catch (EBaseException e) {
+            // not finding it is not an error
+        }
+        if (resolverInstName.equals(""))
+            resolverInstName = "none";
+
+        CMS.debug(method + " returning: " + resolverInstName);
+
+        return resolverInstName;
+    }
+
     /**
      * @param resolverInstName
      * @param cuid
@@ -2056,52 +2139,44 @@ public class TPSProcessor {
      * @param minor_version
      * @return
      */
-    protected String resolveTokenProfile(
+    protected FilterMappingParams createFilterMappingParams(
             String resolverInstName,
             String cuid,
             String msn,
             byte major_version,
             byte minor_version)
             throws TPSException {
-        String tokenType;
+        String method = "TPSProcessor.createFilterMappingParams: ";
+        FilterMappingParams mappingParams = new FilterMappingParams();
 
-        if (!resolverInstName.equals("none") && (selectedTokenType == null)) {
 
             try {
-                FilterMappingParams pParams = new FilterMappingParams();
-                CMS.debug("In TPSProcessor.resolveTokenProfile : after new MappingFilterParams");
-                pParams.set(FilterMappingParams.FILTER_PARAM_MAJOR_VERSION,
+                mappingParams = new FilterMappingParams();
+                CMS.debug(method + " after new MappingFilterParams");
+                mappingParams.set(FilterMappingParams.FILTER_PARAM_MAJOR_VERSION,
                         String.valueOf(major_version));
-                pParams.set(FilterMappingParams.FILTER_PARAM_MINOR_VERSION,
+                mappingParams.set(FilterMappingParams.FILTER_PARAM_MINOR_VERSION,
                         String.valueOf(minor_version));
-                pParams.set(FilterMappingParams.FILTER_PARAM_CUID, cuid);
-                pParams.set(FilterMappingParams.FILTER_PARAM_MSN, msn);
+                mappingParams.set(FilterMappingParams.FILTER_PARAM_CUID, cuid);
+                mappingParams.set(FilterMappingParams.FILTER_PARAM_MSN, msn);
+                // fill in the extensions from client, if any
                 if (beginMsg.getExtensions() != null) {
-                    pParams.set(FilterMappingParams.FILTER_PARAM_EXT_TOKEN_TYPE,
+                    mappingParams.set(FilterMappingParams.FILTER_PARAM_EXT_TOKEN_TYPE,
                             beginMsg.getExtensions().get("tokenType"));
-                    pParams.set(FilterMappingParams.FILTER_PARAM_EXT_TOKEN_ATR,
+                    mappingParams.set(FilterMappingParams.FILTER_PARAM_EXT_TOKEN_ATR,
                             beginMsg.getExtensions().get("tokenATR"));
+                    mappingParams.set(FilterMappingParams.FILTER_PARAM_EXT_KEY_SET,
+                            beginMsg.getExtensions().get("keyset"));
                 }
-                CMS.debug("In TPSProcessor.resolveTokenProfile : after setting MappingFilterParams");
-                TPSSubsystem subsystem =
-                        (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
-                BaseMappingResolver resolverInst =
-                        subsystem.getMappingResolverManager().getResolverInstance(resolverInstName);
-                tokenType = resolverInst.getResolvedMapping(pParams);
-                CMS.debug("In TPSProcessor.resolveTokenProfile : profile resolver result: " + tokenType);
-                setSelectedTokenType(tokenType);
-            } catch (EBaseException et) {
-                CMS.debug("In TPSProcessor.resolveTokenProfile exception:" + et);
-                throw new TPSException("TPSProcessor.resolveTokenProfile failed.",
+                CMS.debug(method + " MappingFilterParams set");
+
+            } catch (Exception et) {
+                CMS.debug(method + " exception:" + et);
+                throw new TPSException(method + " failed.",
                         TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED);
             }
 
-        } else {
-            //Already have a token type, return it
-            tokenType = getSelectedTokenType();
-        }
-
-        return tokenType;
+        return mappingParams;
     }
 
     protected String getIssuerInfoValue() throws TPSException {
@@ -2821,7 +2896,7 @@ public class TPSProcessor {
                 }
 
                 TPSBuffer keySetData = engine.createKeySetData(newVersion, curKeyInfo, protocol,
-                        appletInfo.getCUID(),channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId);
+                        appletInfo.getCUID(),channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId, getSelectedKeySet());
 
                 CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: new keySetData from TKS: " + keySetData.toHexString());
 
@@ -2843,7 +2918,7 @@ public class TPSProcessor {
 
                         byte[] nv_dev = { (byte) 0x1, (byte) 0x1 };
                         TPSBuffer devKeySetData = engine.createKeySetData(new TPSBuffer(nv_dev), curKeyInfo, protocol,
-                              appletInfo.getCUID(),  channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId);
+                              appletInfo.getCUID(),  channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId, getSelectedKeySet());
 
                         CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: about to get rid of keyset 0xFF and replace it with keyset 0x1 with developer key set");
                         channel.putKeys((byte) 0x0, (byte) 0x1, devKeySetData);
-- 
1.8.4.2

