diff options
| author | Jack Magne <jmagne@dhcp-16-213.sjc.redhat.com> | 2014-07-21 14:58:27 -0700 |
|---|---|---|
| committer | Jack Magne <jmagne@dhcp-16-213.sjc.redhat.com> | 2014-07-23 14:36:04 -0700 |
| commit | 22b394a7e33ef3a4d8d5ce234ee855fee6b83672 (patch) | |
| tree | a230d3d28a368c9e59b189dbb5f5450e9097ef07 /base | |
| parent | 2a6a458a6d0e2e632c4ce1a4dde70b1768cc813e (diff) | |
| download | pki-22b394a7e33ef3a4d8d5ce234ee855fee6b83672.tar.gz pki-22b394a7e33ef3a4d8d5ce234ee855fee6b83672.tar.xz pki-22b394a7e33ef3a4d8d5ce234ee855fee6b83672.zip | |
First cut of end to end 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.
7. Added stub for stand alone Pin Reset processor.
8. CFU review fixes.
Diffstat (limited to 'base')
18 files changed, 1326 insertions, 56 deletions
diff --git a/base/common/src/org/dogtagpki/tps/apdu/CreatePinAPDU.java b/base/common/src/org/dogtagpki/tps/apdu/CreatePinAPDU.java index c37d0d465..ec684230e 100644 --- a/base/common/src/org/dogtagpki/tps/apdu/CreatePinAPDU.java +++ b/base/common/src/org/dogtagpki/tps/apdu/CreatePinAPDU.java @@ -26,6 +26,8 @@ public class CreatePinAPDU extends APDU { public CreatePinAPDU(byte theP1, byte theP2, TPSBuffer theData) { + setCLA((byte) 0x84); + setINS((byte) 0x40); setP1(theP1); 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 d522c2ab4..43ff2ea1d 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) { @@ -124,6 +133,13 @@ public class TPSBuffer { } + public void prepend(TPSBuffer prepend) { + if(prepend == null) + return; + + byte [] preBytes = prepend.toBytesArray(); + prependBytes(preBytes); + } public void add(TPSBuffer addend) { if (addend == null) @@ -151,6 +167,17 @@ public class TPSBuffer { addBytes(addBytes); } + public void prependBytes(byte [] preBytes) { + if (preBytes == null) + return; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + bytes.write(preBytes, 0, preBytes.length); + bytes.write(buf, 0, buf.length); + + buf = bytes.toByteArray(); + } + public void addBytes(byte[] addBytes) { if (addBytes == null) return; diff --git a/base/common/src/org/dogtagpki/tps/main/Util.java b/base/common/src/org/dogtagpki/tps/main/Util.java index bef425215..8e6ffe614 100644 --- a/base/common/src/org/dogtagpki/tps/main/Util.java +++ b/base/common/src/org/dogtagpki/tps/main/Util.java @@ -52,6 +52,13 @@ public class Util { return ret; } + public static byte bool2Byte(boolean value) { + if (value) + return 0x1; + else + return 0x0; + } + public static int hexToBin(char ch) { if ('0' <= ch && ch <= '9') return ch - '0'; @@ -155,7 +162,6 @@ public class Util { return Utils.SpecialEncode(data.toBytesArray()); } - public static TPSBuffer computeMAC(PK11SymKey symKey, TPSBuffer input, TPSBuffer icv) throws EBaseException { TPSBuffer output = null; TPSBuffer result = null; diff --git a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequestMsg.java b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequestMsg.java index e59f80fff..d776fe1cd 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 173a775f4..b15e333b0 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 71096d261..8c765ba65 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 16fec1dd8..84e991e5a 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 aefdb815b..5584b50e8 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 b014bd3d5..16d57f948 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 67ab08bcf..6d469ee8a 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 @@ -22,6 +22,8 @@ import java.io.IOException; 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; @@ -29,17 +31,23 @@ 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; import org.dogtagpki.tps.main.Util; import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus; import org.mozilla.jss.pkcs11.PK11SymKey; +import sun.security.pkcs11.wrapper.PKCS11Constants; + import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; public class SecureChannel { @@ -60,6 +68,12 @@ public class SecureChannel { private TPSBuffer keyInfoData; private SecurityLevel secLevel; + public enum TokenKeyType { + KEY_TYPE_ENCRYPTION, + KEY_TYPE_SIGNING, + KEY_TYPE_SIGNING_AND_ENCRYPTION + } + public SecureChannel(TPSProcessor processor, PK11SymKey sessionKey, PK11SymKey encSessionKey, TPSBuffer drmDesKey, TPSBuffer kekDesKey, TPSBuffer keyCheck, TPSBuffer keyDiversificationData, TPSBuffer cardChallenge, TPSBuffer cardCryptogram, TPSBuffer hostChallenge, TPSBuffer hostCryptogram, TPSBuffer keyInfoData) @@ -94,6 +108,98 @@ public class SecureChannel { public static void main(String[] args) { } + public void appendPKCS11Attribute(TPSBuffer buffer, long type, TPSBuffer attribute) { + + buffer.addLong4Bytes(type); + + buffer.addInt2Bytes(attribute.size()); + buffer.add(attribute); + } + + public void appendKeyCapabilities(TPSBuffer buffer, String keyTypePrefix, String keyType) throws TPSException { + + if (buffer == null || keyTypePrefix == null || keyType == null) { + throw new TPSException("SecureChannel.appdndKeyCabalities: Invalid input datat.", + TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU); + } + + IConfigStore configStore = CMS.getConfigStore(); + + final String keyCapabilities = "keyCapabilities"; + + try { + + boolean value = false; + String configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "encrypt"; + + value = configStore.getBoolean(configName); + + TPSBuffer attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_ENCRYPT, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "sign"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SIGN, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "signRecover"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SIGN_RECOVER, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "decrypt"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_DECRYPT, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "derive"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_DERIVE, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "unwrap"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_UNWRAP, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "wrap"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_WRAP, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "verifyRecover"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_VERIFY_RECOVER, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "verify"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_VERIFY, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "sensitive"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SENSITIVE, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "private"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + appendPKCS11Attribute(buffer, PKCS11Constants.CKA_PRIVATE, attr); + + configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "token"; + value = configStore.getBoolean(configName); + attr = new TPSBuffer(Util.bool2Byte(value)); + 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!", + TPSStatus.STATUS_ERROR_MISCONFIGURATION); + } + } + public void externalAuthenticate() throws TPSException, IOException { CMS.debug("SecureChannel.externalAuthenticate: entering."); @@ -405,6 +511,55 @@ public class SecureChannel { return keyInfoData; } + public void writeObject(TPSBuffer objectID, TPSBuffer objectData) throws TPSException, IOException { + CMS.debug("SecureChannel.writeObject: entering ..."); + + if (objectID == null || objectData == null) { + throw new TPSException("SecureChannel.writeObject: invalid input data."); + } + + final int MAX_WRITE_SIZE = 0xd0; + + int offset = 0; + int toSend = objectData.size(); + int blockSize = 0; + + boolean moreToGo = true; + do { + + if (toSend > MAX_WRITE_SIZE) { + blockSize = MAX_WRITE_SIZE; + } else { + blockSize = toSend; + } + + TPSBuffer blockToSend = objectData.substr(offset, blockSize); + + WriteObjectAPDU write = new WriteObjectAPDU(objectID.toBytesArray(), offset, blockToSend); + + computeAPDU(write); + + APDUResponse response = processor.handleAPDURequest(write); + + if (!response.checkResult()) { + CMS.debug("SecureChannel.writeObject: bad apdu return!"); + //Throw this return code because this happens during enrollment and we don't have + // a more specific error code. + throw new TPSException("SecureChannel.writeObject. Failed in middle of writeObject.", + TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU); + } + + offset += blockSize; + toSend -= blockSize; + + if (toSend <= 0) { + moreToGo = false; + } + + } while (moreToGo); + + } + public TPSBuffer readObject(TPSBuffer objectID, int offset, int len) throws TPSException, IOException { CMS.debug("SecureChannel.readObject: entering ..."); @@ -462,6 +617,228 @@ public class SecureChannel { return result; } + public void createObject(TPSBuffer objectID, TPSBuffer permissions, TPSBuffer object) throws TPSException, + IOException { + + CMS.debug("SecureChannel.createObject: with full object. entering..."); + + if (objectID == null || permissions == null || object == null) { + throw new TPSException("SecureChannel.createObject, with full object. Bad input data.", + TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU); + + } + + createObject(objectID, permissions, object.size()); + + writeObject(objectID, object); + + } + + public void createCertificate(TPSBuffer objectID, TPSBuffer cert) throws TPSException, IOException { + CMS.debug("SecureChannel.createCertificate: entering..."); + + if (objectID == null || cert == null) { + throw new TPSException("SecureChannel.createCertificate. Bad input data.", + TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU); + } + + byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 }; + + TPSBuffer permissions = new TPSBuffer(perms); + + createObject(objectID, permissions, cert); + + } + + public void createPKCS11CertAttrs(TokenKeyType keyType, String id, String label, TPSBuffer keyid) + throws TPSException, IOException { + + TPSBuffer buffer = createPKCS11CertAttrsBuffer(keyType, id, label, keyid); + + byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 }; + + TPSBuffer permissions = new TPSBuffer(perms); + + createObject(new TPSBuffer(id), permissions, buffer); + + } + + public TPSBuffer createPKCS11PriKeyAttrsBuffer(String id, String label, TPSBuffer keyid, + 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) { + 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 }; + + appendPKCS11Attribute(result, PKCS11Constants.CKA_MODULUS, modulus); + appendPKCS11Attribute(result, PKCS11Constants.CKA_KEY_TYPE, new TPSBuffer(keytype)); + appendPKCS11Attribute(result, PKCS11Constants.CKA_CLASS, new TPSBuffer(p11class)); + appendPKCS11Attribute(result, PKCS11Constants.CKA_ID, keyid); + appendKeyCapabilities(result, keyTypePrefix, "private"); + + 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) throws TPSException, IOException { + + CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer: entering..."); + + 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); + + byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 }; + + TPSBuffer permissions = new TPSBuffer(perms); + + createObject(new TPSBuffer(id), permissions, buffer); + } + + public TPSBuffer createPKCS11PublicKeyAttrsBuffer(String id, String label, TPSBuffer keyid, + 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) { + 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_MODULUS, modulus); + 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) throws TPSException, IOException { + + CMS.debug("SecureChannel.createPKCS11PublicKeyAttrsBuffer: entering..."); + + if (id == null || label == null || keyid == null || modulus == null || exponent == 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); + + byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 }; + + TPSBuffer permissions = new TPSBuffer(perms); + + createObject(new TPSBuffer(id), permissions, buffer); + + } + + public void finalizeObjectBuffer(TPSBuffer buffer, String id) { + + TPSBuffer header = new TPSBuffer(); + + header.add((byte) 0); + header.add((byte) id.charAt(0)); + header.add((byte) id.charAt(1)); + header.add((byte) 0); + header.add((byte) 0); + + header.add((byte) ((buffer.size()) / 256)); + header.add((byte) ((buffer.size()) % 256)); + + buffer.prepend(header); + + } + + public TPSBuffer createPKCS11CertAttrsBuffer(TokenKeyType keyType, String id, String label, TPSBuffer keyid) + throws TPSException { + + CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: entering... id: " + id); + if (keyType == null || id == null || label == null || keyid == null) { + throw new TPSException("SecureChannel.createPKCS11CertAttrsBuffer. Bad input data.", + 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(); + + 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)); + appendPKCS11Attribute(result, PKCS11Constants.CKA_TOKEN, new TPSBuffer(tokenFlag)); + + finalizeObjectBuffer(result, id); + + CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: returing: " + result.toHexString()); + + return result; + + } + + public void createObject(TPSBuffer objectID, TPSBuffer permissions, int len) throws TPSException, IOException { + + CMS.debug("SecureChannel.createObject: entering..."); + if (objectID == null || permissions == null || len <= 0) { + throw new TPSException("SecureChannel.createObject. Bad input data.", + TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU); + } + + CreateObjectAPDU create = new CreateObjectAPDU(objectID.toBytesArray(), permissions.toBytesArray(), len); + + computeAPDU(create); + + APDUResponse response = processor.handleAPDURequest(create); + + //Throw this return code because this happens during enrollment and we don't have + // a more specific error code. + if (!response.checkResult()) { + throw new TPSException("SecureChannel.createObject. Failed to create object on token.", + TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU); + } + + } + public int startEnrollment(int pe1, int pe2, TPSBuffer wrappedChallenge, TPSBuffer keyCheck, int algorithm, int keySize, int option) throws TPSException, IOException { @@ -518,4 +895,76 @@ public class SecureChannel { } + public int tokenTypeToInt(TokenKeyType type) { + + if (type == TokenKeyType.KEY_TYPE_ENCRYPTION) + return 0; + + if (type == TokenKeyType.KEY_TYPE_SIGNING) + 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 a854b020d..0cb29e1b2 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 7e3290fb2..fc93814fc 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,23 @@ public class PKCS11Obj { public void addObjectSpec(ObjectSpec p) { + CMS.debug("PKCS11Obj.adObjectSpec entering.. " + p); + for (ObjectSpec objSpec : objectSpecs) { + + long oid = objSpec.getObjectID(); + + if (oid == p.getObjectID()) { + objectSpecs.remove(objSpec); + char[] b1 = new char[2]; + + b1[0] = (char) ((oid >> 24) & 0xff); + b1[1] = (char) ((oid >> 16) & 0xff); + String oidStr = new String(b1); + CMS.debug("PKCS11Obj.addObjectSpec: found dup, removing...: " + oidStr); + break; + } + } + objectSpecs.add(p); } @@ -229,6 +258,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 +277,8 @@ public class PKCS11Obj { header.add((byte) ((compressedDataOffset >> 8) & 0xff)); header.add((byte) (compressedDataOffset & 0xff)); + CMS.debug("PKCS11Obj.getRawHeaderData: returning: " + header.toHexString()); + return header; } @@ -269,6 +302,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 +331,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 +353,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 +366,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 +387,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 +407,8 @@ public class PKCS11Obj { TPSBuffer result = new TPSBuffer(header); result.add(compressed); + CMS.debug("PKCS11Obj.getCompressedData: PKCS11 Data: " + result.toHexString()); + return result; } @@ -591,4 +635,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 c61734a82..88679c84a 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 18c750d29..15ed9223f 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,6 +1,23 @@ +// --- 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.processor.TPSEnrollProcessor.TokenKeyType; +import org.dogtagpki.server.tps.channel.SecureChannel.TokenKeyType; public class CertEnrollInfo { 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 419395f20..427e04e73 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 93ec046ce..300d78d6b 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,11 @@ package org.dogtagpki.server.tps.processor; import java.io.IOException; import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; 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 +17,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 +28,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 +61,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 +107,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 +122,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 +274,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 +400,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 +435,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 +487,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 +548,7 @@ public class TPSEnrollProcessor extends TPSProcessor { //get the params needed all at once IConfigStore configStore = CMS.getConfigStore(); + CertEnrollInfo cEnrollInfo = new CertEnrollInfo(); try { @@ -391,8 +632,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 +648,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 +662,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 +669,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 +748,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 +778,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 +872,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 +879,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 +1266,45 @@ public class TPSEnrollProcessor extends TPSProcessor { return id; } + private TPSBuffer makeKeyIDFromPublicKeyInfo(byte[] publicKeyInfo) throws TPSException { + + 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); + } catch (NoSuchAlgorithmException e) { + throw new TPSException("TPSEnrollProcessor.makeKeyFromPublicKeyInfo: " + e, + 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 000000000..b92cd8b91 --- /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 98e4d4885..735ebc248 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; @@ -132,7 +136,7 @@ public class TPSProcessor { selectedTokenType = theTokenType; } - protected String getSelectedTokenType() { + public String getSelectedTokenType() { return selectedTokenType; } @@ -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.setupSecureChannel: No arguments entering..."); + + 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 pattern; + } + + 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.mapPattern: Exposed: key: " + key + " Param: " + value); + + if (key.equals(patternToMap)) { + CMS.debug("TPSEnrollProcessor.mapPattern: found match: key: " + key + " mapped to: " + value); + patternMapped = value; + break; + } + + } + + result = piece1 + patternMapped + piece2; + + CMS.debug("TPSEnrollProcessor.mapPattern: returning: " + result); + return result; + + } + public static void main(String[] args) { } |
