From dc952bd857e721b68bc8a1db022958a1ab714681 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@dhcp-16-213.sjc.redhat.com>
Date: Thu, 17 Jul 2014 17:36:16 -0700
Subject: [PATCH] First cut of enrollment feature.

The following features implemented for enrollment.

1. Standard enrollment of a list of RSA certificates.
2. Certificates are only done with token side keygen.
3. Minimual enrollment based pin reset functionality implemented to create
a pin for the enrolled token.
4. Much work done to the PKCS11 object code, which allows us to write the
compressed object blob to the token, allowing coolkey to access it and use
the certs and keys on the token.
5. Tested with Bob Relyea's "smartcard" utility to prove that signing and encryption
operations worked as expected.
6. Some work done to get authentication working with esc.
---
 .../src/org/dogtagpki/tps/apdu/CreatePinAPDU.java  |   3 +-
 .../src/org/dogtagpki/tps/main/TPSBuffer.java      |  10 +
 .../dogtagpki/tps/msg/ExtendedLoginRequestMsg.java |  13 +-
 .../tps/msg/ExtendedLoginResponseMsg.java          |   2 +-
 .../org/dogtagpki/tps/msg/LoginResponseMsg.java    |   2 +-
 .../src/org/dogtagpki/tps/msg/TPSMessage.java      |  12 +-
 .../src/org/dogtagpki/server/tps/TPSSession.java   |   5 +-
 .../server/tps/authentication/AuthUIParameter.java |  10 +-
 .../server/tps/channel/SecureChannel.java          | 141 +++++--
 .../org/dogtagpki/server/tps/engine/TPSEngine.java |   5 +
 .../org/dogtagpki/server/tps/main/PKCS11Obj.java   |  60 ++-
 .../dogtagpki/server/tps/processor/AppletInfo.java |  19 +
 .../server/tps/processor/CertEnrollInfo.java       |  18 +-
 .../server/tps/processor/EnrolledCertsInfo.java    |  50 ++-
 .../server/tps/processor/TPSEnrollProcessor.java   | 454 ++++++++++++++++++++-
 .../server/tps/processor/TPSPinResetProcessor.java |  66 +++
 .../server/tps/processor/TPSProcessor.java         | 173 +++++++-
 17 files changed, 958 insertions(+), 85 deletions(-)
 create mode 100644 base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java

diff --git a/base/common/src/org/dogtagpki/tps/apdu/CreatePinAPDU.java b/base/common/src/org/dogtagpki/tps/apdu/CreatePinAPDU.java
index c37d0d4..8380b40 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/CreatePinAPDU.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/CreatePinAPDU.java
@@ -26,7 +26,8 @@ public class CreatePinAPDU  extends APDU {
 
     public  CreatePinAPDU(byte theP1, byte theP2, TPSBuffer theData) {
 
-        setP1(theP1);
+        setCLA((byte) 0x84);
+        setINS((byte) 0x40);
         setP2(theP2);
         setData(theData);
 
diff --git a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
index 4c17f09..43ff2ea 100644
--- a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
+++ b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
@@ -54,6 +54,15 @@ public class TPSBuffer {
     }
 
     /**
+     * Creates a buffer from only one byte
+     * @param b
+     */
+    public TPSBuffer(byte b) {
+        buf = new byte[1];
+        buf[0] = b;
+    }
+
+    /**
      * Creates a Buffer of length 'len', initialized to zeroes.
      */
     public TPSBuffer(int len) {
@@ -129,6 +138,7 @@ public class TPSBuffer {
             return;
 
         byte [] preBytes = prepend.toBytesArray();
+        prependBytes(preBytes);
     }
     public void add(TPSBuffer addend) {
 
diff --git a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequestMsg.java b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequestMsg.java
index e59f80f..d776fe1 100644
--- a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequestMsg.java
+++ b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequestMsg.java
@@ -28,13 +28,16 @@ public class ExtendedLoginRequestMsg extends TPSMessage {
 
     private Set<String> params;
 
-    public ExtendedLoginRequestMsg(int invalid_pw, int blocked, Set<String> params, String title, String description) {
+    public ExtendedLoginRequestMsg(int invalid_pw, int blocked, Set<String> params, String title, String description)
+            throws UnsupportedEncodingException {
 
         put(INVALID_PWD_NAME, invalid_pw);
         put(BLOCKED_NAME, blocked);
         put(MSG_TYPE_NAME, msgTypeToInt(MsgType.MSG_EXTENDED_LOGIN_REQUEST));
-        put(TITLE_NAME, title);
-        put (DESCRIPTION_NAME, description);
+
+        put(TITLE_NAME, Util.uriEncode(title));
+        put(DESCRIPTION_NAME, Util.uriEncode(description));
+
         this.params = params;
 
     }
@@ -57,7 +60,7 @@ public class ExtendedLoginRequestMsg extends TPSMessage {
 
                 if (curParam != null && curParam.length() > 0) {
 
-                    String name = "&" + PARAMETER_NAME + Integer.toString(i++);
+                    String name = /*"&" + */ REQUIRED_PARAMETER_NAME + Integer.toString(i++);
                     String value = curParam;
 
                     put(name, value);
@@ -72,7 +75,7 @@ public class ExtendedLoginRequestMsg extends TPSMessage {
 
     }
 
-    public static void main(String[] args) {
+    public static void main(String[] args) throws UnsupportedEncodingException {
 
         final String title = "LDAP Authentication";
         final String description = "This authenticates user against the LDAP directory.";
diff --git a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginResponseMsg.java b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginResponseMsg.java
index 173a775..b15e333 100644
--- a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginResponseMsg.java
+++ b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginResponseMsg.java
@@ -37,7 +37,7 @@ public class ExtendedLoginResponseMsg extends TPSMessage {
         put(OPERATION_TYPE_NAME, opTypeToInt(theOp));
         put(MSG_TYPE_NAME, msgTypeToInt(MsgType.MSG_EXTENDED_LOGIN_RESPONSE));
         authParams = theExtensions;
-        put(SCREEN_NAME_NAME, uid);
+        put(UID_NAME, uid);
         put(PASSWORD_NAME, password);
 
     }
diff --git a/base/common/src/org/dogtagpki/tps/msg/LoginResponseMsg.java b/base/common/src/org/dogtagpki/tps/msg/LoginResponseMsg.java
index 71096d2..8c765ba 100644
--- a/base/common/src/org/dogtagpki/tps/msg/LoginResponseMsg.java
+++ b/base/common/src/org/dogtagpki/tps/msg/LoginResponseMsg.java
@@ -23,7 +23,7 @@ public class LoginResponseMsg  extends TPSMessage {
     public LoginResponseMsg(String uid, String password ) {
         put(MSG_TYPE_NAME, msgTypeToInt(MsgType.MSG_LOGIN_RESPONSE));
         put(SCREEN_NAME_NAME,uid);
-        put(PASSWORD_NAME, password);
+        put(PASSWORD_NAME_1, password);
 
     }
 }
diff --git a/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java b/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java
index 16fec1d..84e991e 100644
--- a/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java
+++ b/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java
@@ -67,7 +67,9 @@ public class TPSMessage {
     public static final String INVALID_PWD_NAME = "invalid_pw";
     public static final String BLOCKED_NAME = "blocked";
     public static final String SCREEN_NAME_NAME = "screen_name";
-    public static final String PASSWORD_NAME = "password";
+    public static final String UID_NAME = "UID";
+    public static final String PASSWORD_NAME = "PASSWORD";
+    public static final String PASSWORD_NAME_1 = "password";
     public static final String PIN_REQUIRED_NAME = "pin_required";
     public static final String TITLE_NAME = "title";
     public static final String DESCRIPTION_NAME = "description";
@@ -455,7 +457,7 @@ public class TPSMessage {
         case MSG_EXTENDED_LOGIN_RESPONSE:
             result =
                 new ExtendedLoginResponseMsg(op_val,
-                    get(SCREEN_NAME_NAME),
+                    get(UID_NAME),
                     get(PASSWORD_NAME),
                     extsMap);
             break;
@@ -464,11 +466,15 @@ public class TPSMessage {
         case MSG_LOGIN_RESPONSE:
             result =
                 new LoginResponseMsg(get(SCREEN_NAME_NAME),
-                    get(PASSWORD_NAME));
+                    get(PASSWORD_NAME_1));
             break;
         case MSG_NEW_PIN_REQUEST:
             break;
         case MSG_NEW_PIN_RESPONSE:
+
+            String pin = get(TPSMessage.NEW_PIN_NAME);
+            CMS.debug("TPSMessage.createMessage: MSG_NEW_PIN_RESPONSE pin: " + pin);
+            result = new NewPinResponseMsg(pin);
             break;
         case MSG_SECUREID_REQUEST:
             break;
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSession.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSession.java
index aefdb81..5584b50 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSession.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSession.java
@@ -20,6 +20,7 @@ package org.dogtagpki.server.tps;
 import java.io.IOException;
 
 import org.dogtagpki.server.tps.processor.TPSEnrollProcessor;
+import org.dogtagpki.server.tps.processor.TPSPinResetProcessor;
 import org.dogtagpki.server.tps.processor.TPSProcessor;
 import org.dogtagpki.tps.TPSConnection;
 import org.dogtagpki.tps.main.TPSException;
@@ -93,7 +94,6 @@ public class TPSSession {
         int result = EndOpMsg.RESULT_ERROR;
         BeginOpMsg beginOp = (BeginOpMsg) firstMsg;
         try {
-
             switch (op_type) {
             case OP_FORMAT:
 
@@ -112,6 +112,9 @@ public class TPSSession {
             case OP_RENEW:
                 break;
             case OP_RESET_PIN:
+                result = EndOpMsg.RESULT_GOOD;
+                TPSPinResetProcessor pinResetProcessor = new TPSPinResetProcessor(this);
+                pinResetProcessor.process(beginOp);
                 break;
             case OP_UNBLOCK:
                 break;
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java
index b014bd3..16d57f9 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java
@@ -75,11 +75,17 @@ public class AuthUIParameter {
         if (desc == null)
             desc = getParamDescription("en");
 
+        String typeValue = "string";
+
+        if(paramId.equals("PASSWORD")){
+            typeValue = "password";
+        }
+
         String string =
                 "id=" + paramId +
                         "&name=" + name +
-                        "&description=" + desc +
-                        "&type=string" +
+                        "&desc=" + desc +
+                        "&type=" + typeValue +
                         "&option=";
         return string;
     }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/channel/SecureChannel.java
index 83b6796..67e20df 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/channel/SecureChannel.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/channel/SecureChannel.java
@@ -23,6 +23,7 @@ import org.dogtagpki.server.tps.processor.TPSProcessor;
 import org.dogtagpki.tps.apdu.APDU;
 import org.dogtagpki.tps.apdu.APDUResponse;
 import org.dogtagpki.tps.apdu.CreateObjectAPDU;
+import org.dogtagpki.tps.apdu.CreatePinAPDU;
 import org.dogtagpki.tps.apdu.DeleteFileAPDU;
 import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU;
 import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
@@ -30,9 +31,11 @@ import org.dogtagpki.tps.apdu.GenerateKeyAPDU;
 import org.dogtagpki.tps.apdu.GenerateKeyECCAPDU;
 import org.dogtagpki.tps.apdu.InstallAppletAPDU;
 import org.dogtagpki.tps.apdu.InstallLoadAPDU;
+import org.dogtagpki.tps.apdu.LifecycleAPDU;
 import org.dogtagpki.tps.apdu.LoadFileAPDU;
 import org.dogtagpki.tps.apdu.ReadObjectAPDU;
 import org.dogtagpki.tps.apdu.SetIssuerInfoAPDU;
+import org.dogtagpki.tps.apdu.SetPinAPDU;
 import org.dogtagpki.tps.apdu.WriteObjectAPDU;
 import org.dogtagpki.tps.main.TPSBuffer;
 import org.dogtagpki.tps.main.TPSException;
@@ -134,62 +137,64 @@ public class SecureChannel {
             value = configStore.getBoolean(configName);
 
             TPSBuffer attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_ENCRYPT, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_ENCRYPT, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "sign";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_SIGN, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SIGN, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "signRecover";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_SIGN_RECOVER, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SIGN_RECOVER, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "decrypt";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_DECRYPT, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_DECRYPT, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "derive";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_DERIVE, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_DERIVE, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "unwrap";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_UNWRAP, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_UNWRAP, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "wrap";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_WRAP, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_WRAP, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "verifyRecover";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_VERIFY_RECOVER, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_VERIFY_RECOVER, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "verify";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_VERIFY, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_VERIFY, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "sensitive";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_SENSITIVE, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SENSITIVE, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "private";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_PRIVATE, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_PRIVATE, attr);
 
             configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "token";
             value = configStore.getBoolean(configName);
             attr = new TPSBuffer(Util.bool2Byte(value));
-            appendPKCS11Attribute(buffer, (int) PKCS11Constants.CKA_TOKEN, attr);
+            appendPKCS11Attribute(buffer, PKCS11Constants.CKA_TOKEN, attr);
+
+            CMS.debug("SecureChannel.appendKeyCapabilities: returning: " + buffer.toHexString());
 
         } catch (EBaseException e) {
             throw new TPSException("SecureChannel.appentKeyCapabilities. Can't obtain config value!",
@@ -532,7 +537,7 @@ public class SecureChannel {
 
             TPSBuffer blockToSend = objectData.substr(offset, blockSize);
 
-            WriteObjectAPDU write = new WriteObjectAPDU(objectID.toBytesArray(), blockSize, blockToSend);
+            WriteObjectAPDU write = new WriteObjectAPDU(objectID.toBytesArray(), offset, blockToSend);
 
             computeAPDU(write);
 
@@ -664,16 +669,20 @@ public class SecureChannel {
     }
 
     public TPSBuffer createPKCS11PriKeyAttrsBuffer(String id, String label, TPSBuffer keyid,
-            TPSBuffer modulus, String keyTypePrefix, String keyType) throws TPSException {
+            TPSBuffer modulus, String keyTypePrefix) throws TPSException {
 
         TPSBuffer result = new TPSBuffer();
+
         CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer: entering...");
 
-        if (id == null || label == null || keyid == null || modulus == null || keyTypePrefix == null || keyType == null) {
+        if (id == null || label == null || keyid == null || modulus == null || keyTypePrefix == null) {
             throw new TPSException("SecureChannel.craetePKCS11PriKeyAttrsBuffer: invalid input data.",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
 
+        CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer:  id: " + id + " label: " + label + " keyid: "
+                + keyid.toHexString());
+
         byte keytype[] = { 0, 0, 0, 0 };
         byte p11class[] = { 3, 0, 0, 0 };
 
@@ -685,21 +694,23 @@ public class SecureChannel {
 
         finalizeObjectBuffer(result, id);
 
+        CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer: returing: " + result.toHexString());
+
         return result;
 
     }
 
     public void createPKCS11PriKeyAttrs(String id, String label, TPSBuffer keyid,
-            TPSBuffer modulus, String keyTypePrefix, String keyType) throws TPSException, IOException {
+            TPSBuffer modulus, String keyTypePrefix) throws TPSException, IOException {
 
         CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer: entering...");
 
-        if (id == null || label == null || keyid == null || modulus == null || keyTypePrefix == null || keyType == null) {
+        if (id == null || label == null || keyid == null || modulus == null || keyTypePrefix == null) {
             throw new TPSException("SecureChannel.craetePKCS11PriKeyAttrsBuffer: invalid input data.",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
 
-        TPSBuffer buffer = createPKCS11PriKeyAttrsBuffer(id, label, keyid, modulus, keyTypePrefix, keyType);
+        TPSBuffer buffer = createPKCS11PriKeyAttrsBuffer(id, label, keyid, modulus, keyTypePrefix);
 
         TPSBuffer perms = new TPSBuffer();
 
@@ -715,44 +726,45 @@ public class SecureChannel {
     }
 
     public TPSBuffer createPKCS11PublicKeyAttrsBuffer(String id, String label, TPSBuffer keyid,
-            TPSBuffer modulus, TPSBuffer exponent, String keyTypePrefix, String keyType) throws TPSException {
+            TPSBuffer modulus, TPSBuffer exponent, String keyTypePrefix) throws TPSException {
 
         TPSBuffer result = new TPSBuffer();
         CMS.debug("SecureChannel.createPKCS11PublicKeyAttrsBuffer: entering...");
 
         if (id == null || label == null || keyid == null || modulus == null || exponent == null
-                || keyTypePrefix == null || keyType == null) {
-            throw new TPSException("SecureChannel.craetePKCS11PriKeyAttrsBuffer: invalid input data.",
+                || keyTypePrefix == null) {
+            throw new TPSException("SecureChannel.craetePKCS11PublicKeyAttrsBuffer: invalid input data.",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
 
         byte p11class[] = { 2, 0, 0, 0 };
 
-        appendPKCS11Attribute(result, PKCS11Constants.CKA_PUBLIC_EXPONENT,exponent);
+        appendPKCS11Attribute(result, PKCS11Constants.CKA_PUBLIC_EXPONENT, exponent);
         appendPKCS11Attribute(result, PKCS11Constants.CKA_MODULUS, modulus);
-        appendPKCS11Attribute(result, PKCS11Constants.CKA_CLASS, new TPSBuffer(p11class));
         appendPKCS11Attribute(result, PKCS11Constants.CKA_ID, keyid);
+        appendPKCS11Attribute(result, PKCS11Constants.CKA_CLASS, new TPSBuffer(p11class));
         appendKeyCapabilities(result, keyTypePrefix, "public");
 
         finalizeObjectBuffer(result, id);
 
+        CMS.debug("SecureChannel.createPKCS11PublicKeyAttrsBuffer: returing: " + result.toHexString());
+
         return result;
 
     }
 
-
     public void createPKCS11PublicKeyAttrs(String id, String label, TPSBuffer keyid,
-            TPSBuffer modulus, TPSBuffer exponent, String keyTypePrefix, String keyType) throws TPSException, IOException {
+            TPSBuffer modulus, TPSBuffer exponent, String keyTypePrefix) throws TPSException, IOException {
 
         CMS.debug("SecureChannel.createPKCS11PublicKeyAttrsBuffer: entering...");
 
         if (id == null || label == null || keyid == null || modulus == null || exponent == null
-                || keyTypePrefix == null || keyType == null) {
+                || keyTypePrefix == null) {
             throw new TPSException("SecureChannel.craetePKCS11PriKeyAttrsBuffer: invalid input data.",
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
 
-        TPSBuffer buffer = createPKCS11PriKeyAttrsBuffer(id, label, keyid, modulus, keyTypePrefix, keyType);
+        TPSBuffer buffer = createPKCS11PriKeyAttrsBuffer(id, label, keyid, modulus, keyTypePrefix);
 
         TPSBuffer perms = new TPSBuffer();
 
@@ -777,8 +789,8 @@ public class SecureChannel {
         header.add((byte) 0);
         header.add((byte) 0);
 
-        header.add((byte) ((buffer.size() - 7) / 256));
-        header.add((byte) ((buffer.size() - 7) % 256));
+        header.add((byte) ((buffer.size()) / 256));
+        header.add((byte) ((buffer.size()) % 256));
 
         buffer.prepend(header);
 
@@ -793,13 +805,20 @@ public class SecureChannel {
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
 
         }
+
+        CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: ... id: " + id + " label: " + label + " keyid: "
+                + keyid.toHexString());
+
         byte[] type = { 0x0, 0x0, 0x0, 0x0 };
         byte[] p11class = { 0x1, 0x0, 0x0, 0x0 };
         byte[] tokenFlag = { 0x1 };
 
         TPSBuffer result = new TPSBuffer();
 
-        appendPKCS11Attribute(result, PKCS11Constants.CKA_LABEL, new TPSBuffer(label));
+        CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: label: " + label + " label bytes: "
+                + (new TPSBuffer(label)).toHexString());
+
+        appendPKCS11Attribute(result, PKCS11Constants.CKA_LABEL, new TPSBuffer(label.getBytes()));
         appendPKCS11Attribute(result, PKCS11Constants.CKA_ID, keyid);
         appendPKCS11Attribute(result, PKCS11Constants.CKA_CERTIFICATE_TYPE, new TPSBuffer(type));
         appendPKCS11Attribute(result, PKCS11Constants.CKA_CLASS, new TPSBuffer(p11class));
@@ -807,6 +826,8 @@ public class SecureChannel {
 
         finalizeObjectBuffer(result, id);
 
+        CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: returing: " + result.toHexString());
+
         return result;
 
     }
@@ -897,6 +918,66 @@ public class SecureChannel {
             return 1;
         else
             return 2;
+    }
+
+    public void setLifeycleState(byte flag) throws TPSException, IOException {
+
+        CMS.debug("SecureChannel.setLifecycleState: flage: " + flag);
+
+        LifecycleAPDU life = new LifecycleAPDU(flag);
+
+        computeAPDU(life);
+
+        APDUResponse response = processor.handleAPDURequest(life);
+
+        if (!response.checkResult()) {
+            throw new TPSException("SecureChannel.setLifecycleState. Failed to set Lifecycle State!.",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+    }
+
+    public void createPin(int pinNumber, int maxRetries, String pin) throws TPSException, IOException {
+
+        CMS.debug("SecureChannel.createPin:  entering...");
+
+        if (pin == null) {
+            throw new TPSException("SecureChannel.createPin: invalid intput data.",
+                    TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
+        }
+
+        TPSBuffer pinBuf = new TPSBuffer(pin.getBytes());
+        CreatePinAPDU create = new CreatePinAPDU((byte) pinNumber, (byte) maxRetries, pinBuf);
+
+        computeAPDU(create);
+
+        APDUResponse response = processor.handleAPDURequest(create);
+
+        //If the pin already exists we may get an error here, but we go on.
+
+    }
+
+    public void resetPin(int pinNumber, String new_pin) throws TPSException, IOException {
+
+        CMS.debug("SecureChannel.resetPin");
+
+        if (new_pin == null) {
+            throw new TPSException("SecureChannel.resetPin: invalid intput data.",
+                    TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
+        }
+
+        TPSBuffer newPinBuf = new TPSBuffer(new_pin.getBytes());
+
+        SetPinAPDU reset = new SetPinAPDU((byte) 0x0, (byte) 0x0, newPinBuf);
+
+        computeAPDU(reset);
+
+        APDUResponse response = processor.handleAPDURequest(reset);
+
+        if (!response.checkResult()) {
+            throw new TPSException("SecureChannel.resetPin: failed to reset pin.",
+                    TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
+        }
 
     }
 
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
index a854b02..0cb29e1 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -128,6 +128,11 @@ public class TPSEngine {
     public static final String CFG_DEF_PIN_RESET_PROFILE_RESOLVER = "pinResetMappingResolver";
     public static final String OP_ENROLL_PREFIX = "op.enroll";
     public static final String OP_PIN_RESET_PREFIX = "op.pinReset";
+    public static final String CFG_PIN_RESET_ENABLE = "pinReset.enable";
+    public static final String CFG_PIN_RESET_MIN_LEN = "pinReset.pin.minLen";
+    public static final String CFG_PIN_RESET_MAX_LEN = "pinReset.pin.maxLen";
+    public static final String CFG_PIN_RESET_MAX_RETRIES = "pinReset.pin.maxRetries";
+    public static final String CFG_PIN_RESET_STRING = "create_pin.string";
     public static final String ENROLL_OP = "enroll";
     public static final String FORMAT_OP = "format";
 
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/main/PKCS11Obj.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/main/PKCS11Obj.java
index 7e3290f..95ad61f 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/main/PKCS11Obj.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/main/PKCS11Obj.java
@@ -24,6 +24,9 @@ public class PKCS11Obj {
         objectSpecs = new ArrayList<ObjectSpec>();
     }
 
+    private int oldFormatVersion;
+    private int oldObjectVersion;
+
     private int formatVersion;
     private int objectVersion;
 
@@ -35,9 +38,14 @@ public class PKCS11Obj {
         PKCS11Obj o = new PKCS11Obj();
 
         int formatVersion = b.getIntFrom2Bytes(0);
+
+        CMS.debug("PKCS11Obj.parse: formatVersion read from blob: " + formatVersion);
+
         o.setFormatVersion(formatVersion);
         int objectVersion = b.getIntFrom2Bytes(2);
 
+        CMS.debug("PKCS11Obj.parse: objectVersion read from blob: " + objectVersion);
+
         o.setObjectVersion(objectVersion);
         o.setCUID(b.substr(offset + 4, 10));
 
@@ -47,7 +55,7 @@ public class PKCS11Obj {
         int dataOffset = b.getIntFrom2Bytes(18);
 
         CMS.debug("PKCS11Obj.parse: commpressionType: " + compressionType + " DataSize:"
-                + dataSize + "DataOffset: " + dataOffset);
+                + dataSize + "DataOffset: " + dataOffset + " data:  " + b.toHexString());
 
         TPSBuffer data = new TPSBuffer();
 
@@ -64,6 +72,8 @@ public class PKCS11Obj {
             throw new TPSException("PKCS11Obj.parse: error parsing object data!");
         }
 
+        CMS.debug("PKCS11Obj.parse: uncompressed data: " + data.toHexString());
+
         int objOffset = data.getIntFrom2Bytes(0);
         int objCount = data.getIntFrom2Bytes(2);
 
@@ -75,7 +85,8 @@ public class PKCS11Obj {
         TPSBuffer tokenName = data.substr(5, data.at(4));
         o.setTokenName(tokenName);
 
-        System.out.println("tokenName: " + tokenName.toHexString());
+        if (tokenName != null)
+            System.out.println("tokenName: " + tokenName.toHexString());
         System.out.println("uncompressed data size: " + data.size());
 
         CMS.debug("PKCS11Obj.parse" + "objcount = " + objCount);
@@ -166,6 +177,7 @@ public class PKCS11Obj {
 
     public void setObjectVersion(int v)
     {
+        CMS.debug("PKCS11Obj.setObjectVersion: setting to: " + v);
         objectVersion = v;
     }
 
@@ -212,6 +224,17 @@ public class PKCS11Obj {
 
     public void addObjectSpec(ObjectSpec p)
     {
+        for (ObjectSpec objSpec : objectSpecs) {
+
+            long oid = objSpec.getObjectID();
+
+            if (oid == p.getObjectID()) {
+                objectSpecs.remove(objSpec);
+                CMS.debug("PKCS11Obj.addObjectSpec: found dup, removing... ");
+                break;
+            }
+        }
+
         objectSpecs.add(p);
     }
 
@@ -229,6 +252,8 @@ public class PKCS11Obj {
     private TPSBuffer getRawHeaderData(int compressionType, TPSBuffer data) {
         TPSBuffer header = new TPSBuffer();
 
+        CMS.debug("PKCS11Obj.getRawHeaderData: " + " formatVersion: " + formatVersion + " objectVersion: "
+                + objectVersion);
         header.add((byte) ((formatVersion >> 8) & 0xff));
         header.add((byte) (formatVersion & 0xff));
         header.add((byte) ((objectVersion >> 8) & 0xff));
@@ -246,6 +271,8 @@ public class PKCS11Obj {
         header.add((byte) ((compressedDataOffset >> 8) & 0xff));
         header.add((byte) (compressedDataOffset & 0xff));
 
+        CMS.debug("PKCS11Obj.getRawHeaderData: returing: " + header.toHexString());
+
         return header;
 
     }
@@ -269,6 +296,9 @@ public class PKCS11Obj {
         data.add((byte) (objectCountX & 0xff));
         data.add((byte) (tokenName.size() & 0xff));
         data.add(tokenName);
+
+        CMS.debug("PKCS11Obj:getRawData: objectCount: " + objectCount);
+
         for (int i = 0; i < objectCount; i++) {
             ObjectSpec spec = getObjectSpec(i);
             long objectID = spec.getObjectID();
@@ -295,6 +325,8 @@ public class PKCS11Obj {
                     int u_xclass = (int) ((u_fixedAttrs & 0x70) >> 4);
                     int u_id = (int) (u_fixedAttrs & 0x0f);
                     if (u_c == 'C' && u_xclass == PKCS11Constants.CKO_CERTIFICATE && u_id == id) {
+                        CMS.debug("PKCSObj:getRawData: found cert object: id: " + id + " u_id: " + u_id);
+
                         AttributeSpec u_attr =
                                 u_spec.getAttributeSpec(0);
                         AttributeSpec n_attr = new AttributeSpec();
@@ -315,6 +347,7 @@ public class PKCS11Obj {
                     int x_xclass = (int) ((x_fixedAttrs & 0x70) >> 4);
                     int x_id = (int) (x_fixedAttrs & 0x0f);
                     if (x_xclass == PKCS11Constants.CKO_PUBLIC_KEY && x_id == id) {
+                        CMS.debug("PKCSObj:getRawData: found public key object: id: " + id);
                         data.add(x_spec.getData());
                     }
                 }
@@ -327,6 +360,7 @@ public class PKCS11Obj {
                     int y_xclass = (int) ((y_fixedAttrs & 0x70) >> 4);
                     int y_id = (int) (y_fixedAttrs & 0x0f);
                     if (y_xclass == PKCS11Constants.CKO_PRIVATE_KEY && y_id == id) {
+                        CMS.debug("PKCSObj:getRawData: found private key object: id: " + id);
                         data.add(y_spec.getData());
                     }
                 }
@@ -347,11 +381,13 @@ public class PKCS11Obj {
         return result;
     }
 
-    TPSBuffer getCompressedData() throws TPSException, IOException
+    public TPSBuffer getCompressedData() throws TPSException, IOException
     {
         TPSBuffer data = getRawData(); // new TPSBuffer();
 
         CMS.debug("PKCS11Obj.getCompressedData: " + "before compress length = " + data.size());
+        CMS.debug("PKCS11Obj.getCompressedData: " + "before compress data = " + data.toHexString());
+
         System.out.println("Raw data before compress length: " + data.size());
 
         TPSBuffer src_buffer = new TPSBuffer(data);
@@ -365,6 +401,8 @@ public class PKCS11Obj {
         TPSBuffer result = new TPSBuffer(header);
         result.add(compressed);
 
+        CMS.debug("PKCS11Obj.getCompressedData: PKCS11 Data: " + result.toHexString());
+
         return result;
     }
 
@@ -591,4 +629,20 @@ public class PKCS11Obj {
 
     }
 
+    public int getOldFormatVersion() {
+        return oldFormatVersion;
+    }
+
+    public void setOldFormatVersion(int oldFormatVersion) {
+        this.oldFormatVersion = oldFormatVersion;
+    }
+
+    public int getOldObjectVersion() {
+        return oldObjectVersion;
+    }
+
+    public void setOldObjectVersion(int oldObjectVersion) {
+        this.oldObjectVersion = oldObjectVersion;
+    }
+
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/AppletInfo.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/AppletInfo.java
index c61734a..88679c8 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/AppletInfo.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/AppletInfo.java
@@ -13,6 +13,8 @@ public class AppletInfo {
 
     private TPSBuffer cuid;
     private TPSBuffer msn;
+    private int totalMem;
+    private int freeMem;
 
     public AppletInfo(byte appletMajorVer,byte appletMinorVer,byte appMajorVer,byte appMinorVer) {
 
@@ -74,4 +76,21 @@ public class AppletInfo {
 
     }
 
+    public void setTotalMem(int total_mem) {
+        totalMem = total_mem;
+
+    }
+
+    public int getTotalMem() {
+        return totalMem;
+    }
+
+    public void setFreeMem(int free_mem) {
+        freeMem = free_mem;
+    }
+
+    public int getFreeMem() {
+        return freeMem;
+    }
+
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java
index b4a87fe..15ed922 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java
@@ -1,8 +1,24 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
 package org.dogtagpki.server.tps.processor;
 
 import org.dogtagpki.server.tps.channel.SecureChannel.TokenKeyType;
 
-
 public class CertEnrollInfo {
 
     private TokenKeyType keyTypeEnum;
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/EnrolledCertsInfo.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/EnrolledCertsInfo.java
index 419395f..427e04e 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/EnrolledCertsInfo.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/EnrolledCertsInfo.java
@@ -1,28 +1,54 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
 package org.dogtagpki.server.tps.processor;
 
 import java.util.ArrayList;
 
+import netscape.security.x509.X509CertImpl;
+
 import org.dogtagpki.server.tps.main.PKCS11Obj;
 import org.dogtagpki.tps.main.TPSBuffer;
-import org.mozilla.jss.pkix.cert.Certificate;
 
 public class EnrolledCertsInfo {
 
     EnrolledCertsInfo() {
+        certificates = new ArrayList<X509CertImpl>();
+        ktypes = new ArrayList<String>();
+        origins = new ArrayList<String>();
+        tokenTypes = new ArrayList<String>();
     }
 
-    EnrolledCertsInfo(PKCS11Obj obj, TPSBuffer wrappedChallenge, TPSBuffer plainChallenge, int keyTypeNum) {
+    EnrolledCertsInfo(PKCS11Obj obj, TPSBuffer wrappedChallenge, TPSBuffer plainChallenge, int keyTypeNum,
+            int startProgress, int endProgress) {
+        this();
         this.wrappedChallenge = wrappedChallenge;
         plaintextChallenge = plainChallenge;
         pkcs11objx = obj;
         numCertsToEnroll = keyTypeNum;
+        this.startProgress = startProgress;
+        this.endProgress = endProgress;
     }
 
     //Tables that will get set during processing
     private ArrayList<String> origins;
     private ArrayList<String> ktypes;
     private ArrayList<String> tokenTypes;
-    private ArrayList<Certificate> certificates;
+    private ArrayList<X509CertImpl> certificates;
 
     //Input challenge data
     private TPSBuffer wrappedChallenge;
@@ -32,8 +58,8 @@ public class EnrolledCertsInfo {
     private int numCertsToEnroll;
     private int currentCertIndex;
 
-    static final private int startProgress = 15;
-    static final private int endProgress = 90;
+    private int startProgress;
+    private int endProgress;
 
     public int getCurrentCertIndex() {
         return currentCertIndex;
@@ -106,8 +132,18 @@ public class EnrolledCertsInfo {
         tokenTypes.add(tokenType);
     }
 
-    public void addCertificate(Certificate cert) {
-        certificates.add(cert);
+    public void addCertificate(X509CertImpl x509Cert) {
+        certificates.add(x509Cert);
+    }
+
+    public void setStartProgress(int startP) {
+        startProgress = startP;
+
+    }
+
+    public void setEndProgress(int endP) {
+        endProgress = endP;
+
     }
 
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
index 93ec046..284de1d 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -2,7 +2,12 @@ package org.dogtagpki.server.tps.processor;
 
 import java.io.IOException;
 import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
 import java.security.PublicKey;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Random;
 import java.util.zip.DataFormatException;
 
 import netscape.security.provider.RSAPublicKey;
@@ -13,9 +18,9 @@ import netscape.security.x509.X509CertImpl;
 import org.dogtagpki.server.tps.TPSSession;
 import org.dogtagpki.server.tps.authentication.TPSAuthenticator;
 import org.dogtagpki.server.tps.channel.SecureChannel;
+import org.dogtagpki.server.tps.channel.SecureChannel.TokenKeyType;
 import org.dogtagpki.server.tps.cms.CAEnrollCertResponse;
 import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
-import org.dogtagpki.server.tps.channel.SecureChannel.TokenKeyType;
 import org.dogtagpki.server.tps.engine.TPSEngine;
 import org.dogtagpki.server.tps.main.ObjectSpec;
 import org.dogtagpki.server.tps.main.PKCS11Obj;
@@ -24,12 +29,15 @@ import org.dogtagpki.tps.main.TPSBuffer;
 import org.dogtagpki.tps.main.TPSException;
 import org.dogtagpki.tps.msg.BeginOpMsg;
 import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
 
 import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.IAuthCredentials;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmsutil.util.Utils;
 
 public class TPSEnrollProcessor extends TPSProcessor {
 
@@ -54,7 +62,6 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
     private void enroll() throws TPSException, IOException {
         CMS.debug("TPSEnrollProcessor enroll: entering...");
-
         TPSEngine engine = getTPSEngine();
         AppletInfo appletInfo = getAppletInfo();
         String resolverInstName = getResolverInstanceName();
@@ -101,7 +108,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
         //Call stub to reset pin, method here will be small and call into common pin reset functionality.
         // Will be implemented during pin reset task.
 
-        checkAndHandlePinReset();
+        checkAndHandlePinReset(channel);
 
         String tksConnId = getTKSConnectorID();
         TPSBuffer plaintextChallenge = computeRandomData(16, tksConnId);
@@ -116,19 +123,112 @@ public class TPSEnrollProcessor extends TPSProcessor {
             throw new TPSException("TPSEnrollProcessor.enroll: Failed to parse original token data: " + e.toString());
         }
 
+        pkcs11objx.setCUID(appletInfo.getCUID());
         //ToDo: Add token to token db
 
-        statusUpdate(15, "PROGRESS_PROCESS_PROFILE");
+        statusUpdate(10, "PROGRESS_PROCESS_PROFILE");
 
         EnrolledCertsInfo certsInfo = new EnrolledCertsInfo();
         certsInfo.setWrappedChallenge(wrappedChallenge);
         certsInfo.setPlaintextChallenge(plaintextChallenge);
         certsInfo.setPKCS11Obj(pkcs11objx);
+        certsInfo.setStartProgress(15);
+        certsInfo.setEndProgress(90);
 
         generateCertificates(certsInfo, channel, appletInfo);
 
-        throw new TPSException("TPSEnrollProcessor.enroll: Failed to enroll token!",
-                TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+        String tokenLabel = buildTokenLabel(certsInfo, appletInfo);
+
+        pkcs11objx.setTokenName(new TPSBuffer(tokenLabel.getBytes()));
+
+        int lastObjVer = pkcs11objx.getOldObjectVersion();
+
+        CMS.debug("TPSEnrollProcessor.enroll: getOldObjectVersion: returning: " + lastObjVer);
+
+        if (lastObjVer != 0) {
+            while (lastObjVer == 0xff) {
+                Random randomGenerator = new Random();
+                lastObjVer = randomGenerator.nextInt(1000);
+            }
+
+            lastObjVer = lastObjVer + 1;
+            CMS.debug("TPSEnrollProcessor.enroll: Setting objectVersion to: " + lastObjVer);
+            pkcs11objx.setObjectVersion(lastObjVer);
+
+        }
+
+        pkcs11objx.setFormatVersion(pkcs11objx.getOldFormatVersion());
+
+        // Make sure we have a good secure channel before writing out the final objects
+        channel = setupSecureChannel();
+
+        statusUpdate(92, "PROGRESS_WRITE_OBJECTS");
+
+        writeFinalPKCS11ObjectToToken(pkcs11objx, appletInfo, channel);
+        statusUpdate(98, "PROGRESS_ISSUER_INFO");
+        writeIssuerInfoToToken(channel);
+
+        statusUpdate(99, "PROGRESS_SET_LIFECYCLE");
+        channel.setLifeycleState((byte) 0x0f);
+
+        CMS.debug("TPSEnrollProcessor.enroll: leaving ...");
+
+        statusUpdate(100, "PROGRESS_DONE_ENROLLMENT");
+    }
+
+    private void writeFinalPKCS11ObjectToToken(PKCS11Obj pkcs11objx, AppletInfo ainfo, SecureChannel channel)
+            throws TPSException, IOException {
+        if (pkcs11objx == null || ainfo == null || channel == null) {
+            throw new TPSException("TPSErollProcessor.writeFinalPKCS11ObjectToToken: invalid input data!",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        CMS.debug("TPSEnrollProcessor.writeFinalPKCS11ObjectToToken:  entering...");
+
+        IConfigStore configStore = CMS.getConfigStore();
+
+        String compressConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+                + "pkcs11obj.compress.enable";
+
+        CMS.debug("TPSEnrollProcessor.writeFinalPKCS11ObjectToToken:  config to check: " + compressConfig);
+
+        boolean doCompress = false;
+
+        try {
+            doCompress = configStore.getBoolean(compressConfig, true);
+        } catch (EBaseException e) {
+            throw new TPSException(
+                    "TPSEnrollProcessor.writeFinalPKCS11ObjectToToken: internal error obtaining config value " + e);
+        }
+
+        CMS.debug("TPSEnrollProcessor.writeFinalPKCS11ObjectToToken:  doCompress: " + doCompress);
+
+        TPSBuffer tokenData = null;
+
+        if (doCompress) {
+            tokenData = pkcs11objx.getCompressedData();
+
+        } else {
+            tokenData = pkcs11objx.getData();
+        }
+
+        if (tokenData.size() > ainfo.getTotalMem()) {
+
+            throw new TPSException(
+                    "TPSEnrollProcessor.writeFinalPKCS11ObjectToToken:  NOt enough memory to write certificates!",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+        }
+
+        byte[] zobjectid = { (byte) 'z', (byte) '0', 0, 0 };
+        byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 };
+        TPSBuffer zobjidBuf = new TPSBuffer(zobjectid);
+
+        channel.createObject(zobjidBuf, new TPSBuffer(perms), tokenData.size());
+
+        channel.writeObject(zobjidBuf, tokenData);
+
+        CMS.debug("TPSEnrollProcessor.writeFinalPKCS11ObjectToToken:  leaving successfully ...");
 
     }
 
@@ -175,8 +275,75 @@ public class TPSEnrollProcessor extends TPSProcessor {
         }
     }
 
-    private void checkAndHandlePinReset() {
-        // TODO Auto-generated method stub
+    private void checkAndHandlePinReset(SecureChannel channel) throws TPSException, IOException {
+
+        CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset entering...");
+
+        if (channel == null) {
+            throw new TPSException("TPSProcessor.checkAndHandlePinReset: invalid input data!",
+                    TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
+        }
+
+        IConfigStore configStore = CMS.getConfigStore();
+
+        String pinResetEnableConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+                + TPSEngine.CFG_PIN_RESET_ENABLE;
+
+        CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + pinResetEnableConfig);
+
+        String minLenConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+                + TPSEngine.CFG_PIN_RESET_MIN_LEN;
+
+        CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + minLenConfig);
+
+        String maxLenConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+                + TPSEngine.CFG_PIN_RESET_MAX_LEN;
+
+        CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + maxLenConfig);
+
+        String maxRetriesConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+                + TPSEngine.CFG_PIN_RESET_MAX_RETRIES;
+
+        CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + maxRetriesConfig);
+
+        String pinStringConfig = TPSEngine.CFG_PIN_RESET_STRING;
+
+        CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + pinStringConfig);
+
+        boolean enabled = false;
+        int minLen;
+        int maxLen;
+        int maxRetries;
+        String stringName;
+
+        try {
+
+            enabled = configStore.getBoolean(pinResetEnableConfig, true);
+
+            if (enabled == false) {
+                CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset:  Pin Reset not allowed by configuration, exiting...");
+                return;
+
+            }
+
+            minLen = configStore.getInteger(minLenConfig, 4);
+            maxLen = configStore.getInteger(maxLenConfig, 10);
+            maxRetries = configStore.getInteger(maxRetriesConfig, 0x7f);
+            stringName = configStore.getString(pinStringConfig, "password");
+
+            CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset: config vals: enabled: " + enabled + " minLen: "
+                    + minLen + " maxLen: " + maxLen);
+
+        } catch (EBaseException e) {
+            throw new TPSException(
+                    "TPSEnrollProcessor.checkAndHandlePinReset: internal error in getting value from config.");
+        }
+
+        String new_pin = requestNewPin(minLen, maxLen);
+
+        channel.createPin(0x0, maxRetries, stringName);
+
+        channel.resetPin(0x0, new_pin);
 
     }
 
@@ -234,11 +401,28 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
         TPSBuffer objects = null;
 
+        int lastFormatVersion = 0x0100;
+        int lastObjectVersion;
+        Random randomGenerator = new Random();
+
+        lastObjectVersion = randomGenerator.nextInt(1000);
+
+        CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: Random lastObjectVersion: " + lastObjectVersion);
+
         PKCS11Obj pkcs11objx = new PKCS11Obj();
+        pkcs11objx.setOldFormatVersion(lastFormatVersion);
+        pkcs11objx.setOldObjectVersion(lastObjectVersion);
+
         do {
+
             objects = listObjects(seq);
 
+            if (objects != null) {
+                CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: objects: " + objects.toHexString());
+            }
+
             if (objects == null) {
+                pkcs11objx.setOldObjectVersion(lastObjectVersion);
                 seq = 0;
             } else {
                 seq = 1; // get next entry
@@ -252,8 +436,22 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
                 TPSBuffer obj = channel.readObject(objectID, 0, (int) objectLenVal);
 
-                if ((char) obj.at(0) == 'z' && obj.at(1) == 0x0) {
+                if (obj != null) {
+                    CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: obj: " + obj.toHexString());
+                }
+
+                if ((char) objectID.at(0) == (byte) 'z' && objectID.at(1) == (byte) '0') {
+                    lastFormatVersion = obj.getIntFrom2Bytes(0);
+                    lastObjectVersion = obj.getIntFrom2Bytes(2);
+
+                    CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: Versions read from token:  lastFormatVersion : "
+                            + lastFormatVersion
+                            + " lastObjectVersion: " + lastObjectVersion);
+
                     pkcs11objx = PKCS11Obj.parse(obj, 0);
+
+                    pkcs11objx.setOldFormatVersion(lastFormatVersion);
+                    pkcs11objx.setOldObjectVersion(lastObjectVersion);
                     seq = 0;
 
                 } else {
@@ -290,11 +488,54 @@ public class TPSEnrollProcessor extends TPSProcessor {
             String keyType = getConfiguredKeyType(i);
             certsInfo.setCurrentCertIndex(i);
             generateCertificate(certsInfo, channel, aInfo, keyType);
+            channel = setupSecureChannel();
         }
 
         CMS.debug("TPSProcess.generateCertificates: ends ");
     }
 
+    private String buildTokenLabel(EnrolledCertsInfo certsInfo, AppletInfo ainfo) throws TPSException {
+        String label = null;
+
+        if (certsInfo == null || ainfo == null) {
+            throw new TPSException("TPSEnrollProcessor.buildTokenLabel: invalide input data!",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        CMS.debug("TPSEnrollProcessor.buildTokenLabel: entering...");
+
+        IConfigStore configStore = CMS.getConfigStore();
+
+        String configName = TPSEngine.OP_ENROLL_PREFIX + "." + getSelectedTokenType() + ".keyGen.tokenName";
+        String pattern = null;
+
+        try {
+            pattern = configStore.getString(configName, "$cuid$");
+        } catch (EBaseException e) {
+            throw new TPSException(
+                    "TPSEnrollProcessor.buildTokenLabel: Internal error finding config value: " + e,
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+        }
+
+        CMS.debug("TPSEnrollProcessor.buildTokenLabel: pattern: " + pattern);
+
+        Map<String, String> nv = new LinkedHashMap<String, String>();
+
+        nv.put("cuid", ainfo.getCUIDString());
+        nv.put("msn", ainfo.getMSNString());
+        nv.put("userid", userid);
+        nv.put("auth.cn", userid);
+        nv.put("profileId", getSelectedTokenType());
+
+        label = mapPattern((LinkedHashMap<String, String>) nv, pattern);
+
+        CMS.debug("TPSEnrollProcessor.buildTokenLabel: returning: " + label);
+
+        return label;
+
+    }
+
     private void generateCertificate(EnrolledCertsInfo certsInfo, SecureChannel channel, AppletInfo aInfo,
             String keyType) throws TPSException, IOException {
 
@@ -308,6 +549,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
         //get the params needed all at once
 
         IConfigStore configStore = CMS.getConfigStore();
+        CertEnrollInfo cEnrollInfo = new CertEnrollInfo();
 
         try {
 
@@ -391,8 +633,6 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
             CMS.debug("TPSEnrollProcessor.generateCertificate: keyTypeEnum value: " + keyTypeEnum);
 
-            CertEnrollInfo cEnrollInfo = new CertEnrollInfo();
-
             cEnrollInfo.setKeyTypeEnum(keyTypeEnum);
             cEnrollInfo.setProfileId(profileId);
             cEnrollInfo.setCertId(certId);
@@ -409,8 +649,8 @@ public class TPSEnrollProcessor extends TPSProcessor {
             cEnrollInfo.setKeyType(keyType);
             cEnrollInfo.setKeyTypePrefix(keyTypePrefix);
 
-            int certsStartProgress = cEnrollInfo.getStartProgressValue();
-            int certsEndProgress = cEnrollInfo.getEndProgressValue();
+            int certsStartProgress = certsInfo.getStartProgressValue();
+            int certsEndProgress = certsInfo.getEndProgressValue();
             int currentCertIndex = certsInfo.getCurrentCertIndex();
             int totalNumCerts = certsInfo.getNumCertsToEnroll();
 
@@ -423,8 +663,6 @@ public class TPSEnrollProcessor extends TPSProcessor {
             cEnrollInfo.setStartProgressValue(startCertProgValue);
             cEnrollInfo.setEndProgressValue(endCertProgValue);
 
-            enrollOneCertificate(certsInfo, cEnrollInfo, aInfo, channel);
-
         } catch (EBaseException e) {
 
             throw new TPSException(
@@ -432,6 +670,8 @@ public class TPSEnrollProcessor extends TPSProcessor {
                     TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
         }
 
+        enrollOneCertificate(certsInfo, cEnrollInfo, aInfo, channel);
+
     }
 
     private void enrollOneCertificate(EnrolledCertsInfo certsInfo, CertEnrollInfo cEnrollInfo, AppletInfo aInfo,
@@ -509,12 +749,21 @@ public class TPSEnrollProcessor extends TPSProcessor {
                 CARemoteRequestHandler caRH = new CARemoteRequestHandler(caConnID);
                 TPSBuffer encodedParsedPubKey = new TPSBuffer(parsedPubKey_ba);
                 AppletInfo appletInfo = getAppletInfo();
+                selectCoolKeyApplet();
                 CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: userid =" + userid + ", cuid="
                         + appletInfo.getCUIDString());
                 CAEnrollCertResponse caEnrollResp = caRH.enrollCertificate(encodedParsedPubKey, userid,
                         appletInfo.getCUIDString(), getSelectedTokenType(),
                         cEnrollInfo.getKeyType());
                 String retCertB64 = caEnrollResp.getCertB64();
+
+                CMS.debug("TPSEnrollProcessor.enrollOneCertificate: retCertB64: " + retCertB64);
+
+                byte[] cert_bytes = Utils.base64decode(retCertB64);
+
+                TPSBuffer cert_bytes_buf = new TPSBuffer(cert_bytes);
+                CMS.debug("TPSEnrollProcessor.enrollOneCertificate: retCertB64: " + cert_bytes_buf.toHexString());
+
                 if (retCertB64 != null)
                     CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert b64 =" + retCertB64);
                 else {
@@ -530,6 +779,93 @@ public class TPSEnrollProcessor extends TPSProcessor {
                     throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: new cert not found",
                             TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
                 }
+
+                certsInfo.addCertificate(x509Cert);
+                certsInfo.addKType(cEnrollInfo.getKeyType());
+                certsInfo.addOrigin(aInfo.getCUIDString());
+
+                SubjectPublicKeyInfo publicKeyInfo = null;
+                try {
+                    publicKeyInfo = new SubjectPublicKeyInfo(parsedPubKey);
+                } catch (InvalidBERException e) {
+                    CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: cant get publicKeyInfo object.");
+                    throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: can't get publcKeyInfo object.",
+                            TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+                }
+
+                //Create label ToDo: Do this the correct way later
+
+                String label = buildCertificateLabel(cEnrollInfo, aInfo);
+                CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: cert label: " + label);
+
+                TPSBuffer keyid = new TPSBuffer(makeKeyIDFromPublicKeyInfo(publicKeyInfo.getEncoded()));
+
+                RSAPublicKey rsaPubKey = (RSAPublicKey) parsedPubKey;
+                TPSBuffer modulus = new TPSBuffer(rsaPubKey.getModulus().toByteArray());
+                TPSBuffer exponent = new TPSBuffer(rsaPubKey.getPublicExponent().toByteArray());
+
+                //Write cert to the token
+
+                long l1, l2;
+                long objid;
+                PKCS11Obj pkcs11Obj = certsInfo.getPKCS11Obj();
+
+                String certId = cEnrollInfo.getCertId();
+
+                l1 = (certId.charAt(0) & 0xff) << 24;
+                l2 = (certId.charAt(1) & 0xff) << 16;
+                objid = l1 + l2;
+
+                CMS.debug("TPSEnrollProcess.enrollOneCertificate:  cert objid long: " + objid);
+
+                ObjectSpec certObjSpec = ObjectSpec.parseFromTokenData(objid, new TPSBuffer(cert_bytes));
+                pkcs11Obj.addObjectSpec(certObjSpec);
+
+                String certAttrId = cEnrollInfo.getCertAttrId();
+
+                TPSBuffer certAttrsBuffer = channel.createPKCS11CertAttrsBuffer(cEnrollInfo.getKeyTypeEnum(),
+                        certAttrId, label, keyid);
+
+                l1 = (certAttrId.charAt(0) & 0xff) << 24;
+                l2 = (certAttrId.charAt(1) & 0xff) << 16;
+                objid = l1 + l2;
+
+                CMS.debug("TPSEnrollProcess.enrollOneCertificate:  cert attr objid long: " + objid);
+                ObjectSpec certAttrObjSpec = ObjectSpec.parseFromTokenData(objid, certAttrsBuffer);
+                pkcs11Obj.addObjectSpec(certAttrObjSpec);
+
+                //Add the pri key attrs object
+
+                String priKeyAttrId = cEnrollInfo.getPrivateKeyAttrId();
+
+                l1 = (priKeyAttrId.charAt(0) & 0xff) << 24;
+                l2 = (priKeyAttrId.charAt(1) & 0xff) << 16;
+
+                objid = l1 + l2;
+
+                CMS.debug("TPSEnrollProcess.enrollOneCertificate: pri key objid long: " + objid);
+
+                TPSBuffer privKeyAttrsBuffer = channel.createPKCS11PriKeyAttrsBuffer(priKeyAttrId, label, keyid,
+                        modulus, cEnrollInfo.getKeyTypePrefix());
+
+                ObjectSpec priKeyObjSpec = ObjectSpec.parseFromTokenData(objid, privKeyAttrsBuffer);
+                pkcs11obj.addObjectSpec(priKeyObjSpec);
+
+                // Now add the public key object
+
+                String pubKeyAttrId = cEnrollInfo.getPublicKeyAttrId();
+
+                l1 = (pubKeyAttrId.charAt(0) & 0xff) << 24;
+                l2 = (pubKeyAttrId.charAt(1) & 0xff) << 16;
+
+                objid = l1 + l2;
+                CMS.debug("TPSEnrollProcess.enrollOneCertificate: pub key objid long: " + objid);
+
+                TPSBuffer pubKeyAttrsBuffer = channel.createPKCS11PublicKeyAttrsBuffer(pubKeyAttrId, label, keyid,
+                        modulus, exponent, cEnrollInfo.getKeyTypePrefix());
+                ObjectSpec pubKeyObjSpec = ObjectSpec.parseFromTokenData(objid, pubKeyAttrsBuffer);
+                pkcs11obj.addObjectSpec(pubKeyObjSpec);
+
             } catch (EBaseException e) {
                 CMS.debug("TPSEnrollProcessor.enrollOneCertificate::" + e);
                 throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: Exception thrown: " + e,
@@ -537,8 +873,6 @@ public class TPSEnrollProcessor extends TPSProcessor {
             }
             CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: enrollment ends");
 
-            //ToDo: Finish the rest of this
-
         }
 
         statusUpdate(cEnrollInfo.getEndProgressValue(), "PROGRESS_ENROLL_CERT");
@@ -546,6 +880,52 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
     }
 
+    private String buildCertificateLabel(CertEnrollInfo cEnrollInfo, AppletInfo ainfo) throws TPSException {
+
+        CMS.debug("TPSEnrollProcessor.buildCertificateLabel");
+
+        if (cEnrollInfo == null) {
+            throw new TPSException("TPSErollProcessor.buildCertificateLabel: Invalid input params!",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        String label = null;
+        String pattern = null;
+
+        String defaultLabel = cEnrollInfo.getKeyType() + " key for $userid$";
+
+        IConfigStore configStore = CMS.getConfigStore();
+
+        String configValue = "op." + currentTokenOperation + "." + selectedTokenType + ".keyGen."
+                + cEnrollInfo.getKeyType() + ".label";
+
+        CMS.debug("TPSEnrollProcessor.buildCertificateLabel: label config: " + configValue);
+
+        try {
+            pattern = configStore.getString(
+                    configValue, defaultLabel);
+
+        } catch (EBaseException e) {
+            throw new TPSException(
+                    "TPSEnrollProcessor.buildCertificateLabel: Internal error finding config value: " + e,
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        Map<String, String> nv = new LinkedHashMap<String, String>();
+
+        nv.put("cuid", ainfo.getCUIDString());
+        nv.put("msn", ainfo.getMSNString());
+        nv.put("userid", userid);
+        nv.put("auth.cn", userid);
+        nv.put("profileId", getSelectedTokenType());
+
+        label = mapPattern((LinkedHashMap<String, String>) nv, pattern);
+
+        CMS.debug("TPSEnrollProcessor.buildCertificateLabel: returning: " + label);
+
+        return label;
+    }
+
     /**
      * Extracts information from the public key blob and verify proof.
      *
@@ -887,6 +1267,46 @@ public class TPSEnrollProcessor extends TPSProcessor {
         return id;
     }
 
+    private TPSBuffer makeKeyIDFromPublicKeyInfo(byte[] publicKeyInfo) throws TPSException {
+
+        final String MOZ_PROVIDER_NAME = "Mozilla-JSS";
+        final String alg = "SHA1";
+
+        if (publicKeyInfo == null) {
+            throw new TPSException("TPSEnrollProcessor.makeKeyFromPublicKeyInfo: invalid input data",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        TPSBuffer keyID = null;
+
+        byte[] mozillaDigestOut;
+
+        java.security.MessageDigest mozillaDigest;
+        try {
+            mozillaDigest = java.security.MessageDigest.getInstance(alg, MOZ_PROVIDER_NAME);
+        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
+            throw new TPSException("TPSEnrollProcessor.makeKeyFromPublicKeyInfo:",
+                    TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        mozillaDigestOut = mozillaDigest.digest(publicKeyInfo);
+
+        if (mozillaDigestOut.length == mozillaDigest.getDigestLength()) {
+            System.out.println(mozillaDigest.getAlgorithm() + " " +
+                    " digest output size is " + mozillaDigestOut.length);
+        } else {
+            throw new TPSException("ERROR: digest output size is " +
+                    mozillaDigestOut.length + ", should be " +
+                    mozillaDigest.getDigestLength(), TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+        }
+
+        keyID = new TPSBuffer(mozillaDigestOut);
+
+        CMS.debug("TPSEnrollProcessor.makeKeyFromPublicKeyInfo: " + keyID.toHexString());
+
+        return keyID;
+    }
+
     public static void main(String[] args) {
     }
 
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
new file mode 100644
index 0000000..b92cd8b
--- /dev/null
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
@@ -0,0 +1,66 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.processor;
+
+import java.io.IOException;
+
+import org.dogtagpki.server.tps.TPSSession;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.BeginOpMsg;
+import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class TPSPinResetProcessor extends TPSProcessor {
+
+    public TPSPinResetProcessor(TPSSession session) {
+        super(session);
+        // TODO Auto-generated constructor stub
+    }
+
+    @Override
+    public void process(BeginOpMsg beginMsg) throws TPSException, IOException {
+        if (beginMsg == null) {
+            throw new TPSException("TPSPinResetProcessor.process: invalid input data, not beginMsg provided.",
+                    TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+        }
+        setBeginMessage(beginMsg);
+        setCurrentTokenOperation("pinReset");
+
+        resetPin();
+
+    }
+
+    private void resetPin() throws TPSException {
+
+        //ToDo: Implement full pin reset processor, the pin reset portion
+        // of an enrollment works fine. We just need to finish this to perform
+        // a completely stand alone pin reset of an already enrolled token.
+        CMS.debug("TPSPinResetProcessor.resetPin: entering...");
+
+        throw new TPSException("TPSPinResetProcessor.resetPin: Pin Reset standalone operation not yet supported!",
+                TPSStatus.STATUS_ERROR_MAC_RESET_PIN_PDU);
+
+    }
+
+    public static void main(String[] args) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index 1b95164..05e3738 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -18,11 +18,13 @@
 package org.dogtagpki.server.tps.processor;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
 
@@ -55,6 +57,8 @@ import org.dogtagpki.tps.msg.ExtendedLoginRequestMsg;
 import org.dogtagpki.tps.msg.ExtendedLoginResponseMsg;
 import org.dogtagpki.tps.msg.LoginRequestMsg;
 import org.dogtagpki.tps.msg.LoginResponseMsg;
+import org.dogtagpki.tps.msg.NewPinRequestMsg;
+import org.dogtagpki.tps.msg.NewPinResponseMsg;
 import org.dogtagpki.tps.msg.StatusUpdateRequestMsg;
 import org.dogtagpki.tps.msg.TPSMessage;
 import org.dogtagpki.tps.msg.TokenPDURequestMsg;
@@ -372,6 +376,23 @@ public class TPSProcessor {
 
     }
 
+    protected SecureChannel setupSecureChannel() throws TPSException, IOException {
+        SecureChannel channel = null;
+
+        //Create a standard secure channel with current key set.
+        CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: Key changeover disabled in the configuration.");
+
+        int defKeyVersion = getChannelDefKeyVersion();
+        int defKeyIndex = getChannelDefKeyIndex();
+
+        channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, SecurityLevel.SECURE_MSG_MAC_ENC,
+                getTKSConnectorID());
+
+        channel.externalAuthenticate();
+
+        return channel;
+    }
+
     protected SecureChannel setupSecureChannel(byte keyVersion, byte keyIndex, SecurityLevel securityLevel,
             String connId)
             throws IOException, TPSException {
@@ -560,6 +581,18 @@ public class TPSProcessor {
 
     }
 
+    public void selectCoolKeyApplet() throws TPSException, IOException {
+
+        TPSBuffer netkeyAIDBuff = getNetkeyAID();
+
+        APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, netkeyAIDBuff);
+
+        if (!select.checkResult()) {
+            throw new TPSException("TPSProcessor.upgradeApplet: Cannot select newly created applet!",
+                    TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+        }
+    }
+
     protected byte[] getAppletFileData(String appletFilePath) throws IOException, TPSException {
 
         if (appletFilePath == null) {
@@ -933,14 +966,40 @@ public class TPSProcessor {
 
         // Add issuer info to the token
 
+        writeIssuerInfoToToken(null);
+
+        if (requiresStatusUpdate()) {
+            statusUpdate(100, "PROGRESS_DONE");
+        }
+
+        //ToDo:  Symmetric Key Changeover
+
+        // ToDo: Update Token DB
+        // ToDo:  Revoke certificates
+
+    }
+
+    protected void writeIssuerInfoToToken(SecureChannel origChannel) throws TPSException, IOException,
+            UnsupportedEncodingException {
         if (checkIssuerInfoEnabled()) {
 
+            SecurityLevel secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
+
+            String tksConnId = getTKSConnectorID();
+
             int defKeyIndex = getChannelDefKeyIndex();
             int defKeyVersion = getChannelDefKeyVersion();
 
-            SecureChannel channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, secLevel, tksConnId);
+            SecureChannel channel = null;
 
-            channel.externalAuthenticate();
+            if (origChannel != null) {
+                channel = origChannel;
+            } else {
+
+                channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, secLevel, tksConnId);
+                channel.externalAuthenticate();
+
+            }
 
             String issuer = getIssuerInfoValue();
 
@@ -951,16 +1010,6 @@ public class TPSProcessor {
             channel.setIssuerInfo(issuerInfoBuff);
 
         }
-
-        if (requiresStatusUpdate()) {
-            statusUpdate(100, "PROGRESS_DONE");
-        }
-
-        //ToDo:  Symmetric Key Changeover
-
-        // ToDo: Update Token DB
-        // ToDo:  Revoke certificates
-
     }
 
     protected String getResolverInstanceName() throws TPSException {
@@ -1528,7 +1577,7 @@ public class TPSProcessor {
         if (!requiresStatusUpdate())
             return;
 
-        CMS.debug("In TPSProcessor.statusUpdate status: " + " info: " + info);
+        CMS.debug("In TPSProcessor.statusUpdate status: " + status + " info: " + info);
 
         StatusUpdateRequestMsg statusUpdate = new StatusUpdateRequestMsg(status, info);
         session.write(statusUpdate);
@@ -1606,9 +1655,26 @@ public class TPSProcessor {
             app_minor_version = token_status.at(3);
         }
 
+        int free_mem = 0;
+        int total_mem = 0;
+
+        if (token_status.size() >= 12) {
+            byte tot_high = token_status.at(6);
+            byte tot_low = token_status.at(7);
+
+            byte free_high = token_status.at(10);
+            byte free_low = token_status.at(11);
+
+            total_mem = (tot_high << 8) + tot_low;
+            free_mem = (free_high << 8) + free_low;
+
+        }
+
         result = new AppletInfo(major_version, minor_version, app_major_version, app_minor_version);
         result.setCUID(token_cuid);
         result.setMSN(token_msn);
+        result.setTotalMem(total_mem);
+        result.setFreeMem(free_mem);
 
         CMS.debug("TPSProcessor.getAppletInfo: cuid: " + result.getCUIDString() + " msn: " + result.getMSNString()
                 + " major version: " + result.getMinorVersion() + " minor version: " + result.getMinorVersion()
@@ -1680,6 +1746,87 @@ public class TPSProcessor {
 
     }
 
+    // Request new pin from client
+    protected String requestNewPin(int minLen, int maxLen) throws IOException, TPSException {
+
+        CMS.debug("TPSProcessor.requestNewPin: entering...");
+
+        String newPin = null;
+
+        NewPinRequestMsg new_pin_req = new NewPinRequestMsg(minLen, maxLen);
+
+        session.write(new_pin_req);
+
+        NewPinResponseMsg new_pin_resp = (NewPinResponseMsg) session.read();
+
+        newPin = new_pin_resp.get(NewPinResponseMsg.NEW_PIN_NAME);
+
+        if (newPin.length() < minLen || newPin.length() > maxLen) {
+            throw new TPSException("TPSProcessor.requestNewPin: new pin length outside of length contraints: min: "
+                    + minLen + " max: " + maxLen);
+        }
+
+        return newPin;
+    }
+
+    protected String mapPattern(LinkedHashMap<String, String> map, String pattern) throws TPSException {
+
+        //Right now only support one pattern to match within pattern: for instance:
+        // "encryption key for $userid$ , not only the one "$userid$" pattern.
+
+        String result = null;
+
+        if (pattern == null || map == null) {
+            throw new TPSException("TPSProcessor.mapPattern: Illegal input paramters!",
+                    TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+        }
+
+        final char delim = '$';
+        int firstPos = 0;
+        int nextPos = 0;
+        String patternToMap = null;
+        String patternMapped = null;
+
+        firstPos = pattern.indexOf(delim);
+        nextPos = pattern.indexOf(delim, firstPos + 1);
+
+        if ((nextPos - firstPos) <= 1) {
+            return "token";
+        }
+
+        patternToMap = pattern.substring(firstPos + 1, nextPos);
+
+        CMS.debug("TPSProcessor.mapPattern: patternTo map: " + patternToMap);
+
+        String piece1 = "";
+        if (firstPos >= 1)
+            piece1 = pattern.substring(0, firstPos);
+
+        String piece2 = "";
+        if (nextPos < (pattern.length() - 1))
+            piece2 = pattern.substring(nextPos + 1);
+
+        for (Map.Entry<String, String> entry : map.entrySet()) {
+            String key = entry.getKey();
+
+            String value = entry.getValue();
+            CMS.debug("TPSEnrollProcessor.buildTokenLabel: Exposed: key: " + key + " Param: " + value);
+
+            if (key.equals(patternToMap)) {
+                CMS.debug("TPSEnrollProcessor.buildTokenLabel: found match: key: " + key + " mapped to: " + value);
+                patternMapped = value;
+                break;
+            }
+
+        }
+
+        result = piece1 + patternMapped + piece2;
+
+        CMS.debug("TPSEnrollProcessor.buildTokenLabel: returning: " + result);
+        return result;
+
+    }
+
     public static void main(String[] args) {
     }
 
-- 
1.8.3.1

