summaryrefslogtreecommitdiffstats
path: root/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
diff options
context:
space:
mode:
Diffstat (limited to 'base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java')
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java1045
1 files changed, 1045 insertions, 0 deletions
diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
new file mode 100644
index 000000000..7c3a01ba7
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
@@ -0,0 +1,1045 @@
+// --- 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.channel;
+
+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;
+import org.dogtagpki.tps.apdu.GenerateKeyAPDU;
+import org.dogtagpki.tps.apdu.GenerateKeyECCAPDU;
+import org.dogtagpki.tps.apdu.ImportKeyEncAPDU;
+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.PutKeyAPDU;
+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 {
+
+ // Have not written all code to use all of these as of yet.
+
+ private TPSProcessor processor;
+ private PK11SymKey sessionKey;
+ private PK11SymKey encSessionKey;
+ private TPSBuffer drmDesKey;
+ private TPSBuffer kekDesKey;
+ private TPSBuffer keyCheck;
+ private TPSBuffer keyDiversificationData;
+ private TPSBuffer cardChallenge;
+ private TPSBuffer cardCryptogram;
+ private TPSBuffer hostChallenge;
+ private TPSBuffer hostCryptogram;
+ private TPSBuffer icv;
+ 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)
+ throws TPSException {
+
+ if (processor == null || sessionKey == null | encSessionKey == null || keyDiversificationData == null
+ || cardChallenge == null || cardCryptogram == null || hostChallenge == null || hostCryptogram == null
+ || keyInfoData == null) {
+ throw new TPSException("SecureChannel.SecureChannel: Invalid data in constructor!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ this.processor = processor;
+ this.sessionKey = sessionKey;
+ this.encSessionKey = encSessionKey;
+ this.drmDesKey = drmDesKey;
+ this.setKekDesKey(kekDesKey);
+ this.keyCheck = keyCheck;
+ this.keyDiversificationData = keyDiversificationData;
+ this.cardChallenge = cardChallenge;
+ this.cardCryptogram = cardCryptogram;
+ this.hostChallenge = hostChallenge;
+ this.hostCryptogram = hostCryptogram;
+ this.icv = new TPSBuffer(8);
+ this.keyInfoData = keyInfoData;
+
+ this.secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
+ //ToDo: Write method that reads this from the config
+
+ }
+
+ 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.");
+
+ ExternalAuthenticateAPDU externalAuth = new ExternalAuthenticateAPDU(hostCryptogram,
+ secLevel);
+
+ computeAPDUMac(externalAuth);
+
+ APDUResponse response = processor.handleAPDURequest(externalAuth);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.eternalAuthenticate. Failed to external authenticate to token.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.externalAuthenticate: Successfully completed, exiting ...");
+
+ }
+
+ //This method computes the mac AND encryption if needed.
+ private void computeAPDU(APDU apdu) throws TPSException {
+
+ CMS.debug("SecureChannel.computeAPDU: entering..");
+
+ if (apdu == null) {
+ throw new TPSException("SecureChannel.computeAPDU: bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ computeAPDUMac(apdu);
+
+ if (secLevel == SecurityLevel.SECURE_MSG_MAC_ENC) {
+ try {
+ // CMS.debug("SecureChannel.computeAPDU: Before encryption data value: " + apdu.getData().toHexString());
+ apdu.secureMessage(encSessionKey);
+ // CMS.debug("SecureChannel.computeAPDU: After encryption data value: " + apdu.getData().toHexString());
+ } catch (EBaseException e) {
+ throw new TPSException("SecureChannel.computeAPDU: Can't encrypt outgoing data! " + e);
+ }
+
+ CMS.debug("SecureChannel.computeAPDU: Successfully encrypted apdu data.");
+ }
+ }
+
+ // This method computes MAC only.
+ private void computeAPDUMac(APDU apdu) throws TPSException {
+ TPSBuffer newMac = null;
+ TPSBuffer data = null;
+
+ if (apdu == null) {
+ throw new TPSException("SecureChannel.computeAPDUMac: bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ data = apdu.getDataToMAC();
+
+ CMS.debug("SecureChannel.computeAPDUMac: data To MAC: " + data.toHexString());
+
+ try {
+ newMac = Util.computeMAC(sessionKey, data, icv);
+ } catch (EBaseException e) {
+ CMS.debug("SecureChannel.compuatAPDUMac: Can't compute mac. " + e);
+ throw new TPSException("SecureChannel.compuatAPDUMac: Can't compute mac.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.computeAPDUMac: computed MAC: " + newMac.toHexString());
+
+ apdu.setMAC(newMac);
+
+ icv.set(newMac);
+ }
+
+ public void deleteFileX(TPSBuffer aid) throws TPSException, IOException {
+ CMS.debug("SecureChannel.deleteFileX: entering...");
+ if (aid == null) {
+ throw new TPSException("SecureChannel.deleteFileX: no input aid!");
+ }
+
+ DeleteFileAPDU deleteFile = new DeleteFileAPDU(aid);
+
+ computeAPDU(deleteFile);
+
+ processor.handleAPDURequest(deleteFile);
+
+ }
+
+ // Begin process of loading applet onto token.
+ public void installLoad(TPSBuffer packageAID, TPSBuffer sdAID, int fileLength) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.installLoad: entering ...");
+
+ if (packageAID == null || sdAID == null || fileLength <= 0) {
+ throw new TPSException("SecureChannel.insallLoad bad input parameters!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ InstallLoadAPDU install = new InstallLoadAPDU(packageAID, sdAID, fileLength);
+
+ CMS.debug("SecureChannel.installLoad: Pre computed apdu: " + install.getEncoding().toHexString());
+
+ computeAPDU(install);
+
+ APDUResponse response = processor.handleAPDURequest(install);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.installLoad. Failed to perform installLoad operation.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ }
+
+ //Actually load applet file onto the token.
+
+ public void loadFile(TPSBuffer programFile, int blockSize, int startProgress, int endProgress) throws TPSException,
+ IOException {
+ CMS.debug("SecureChannel.loadFile entering...");
+
+ if (programFile == null || blockSize <= 0) {
+ throw new TPSException("ScureChannel.loadFile. Bad input data.", TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ TPSBuffer length = null;
+
+ TPSBuffer tag = new TPSBuffer(1, (byte) 0xC4);
+
+ int progSize = programFile.size();
+
+ if (progSize < 128) {
+ length = new TPSBuffer(1, (byte) progSize);
+ } else if (progSize <= 255) {
+ length = new TPSBuffer(1, (byte) 0x81);
+ length.add((byte) progSize);
+ } else {
+ length = new TPSBuffer(1, (byte) 0x82);
+ length.add((byte) ((progSize >> 8) & 0xff));
+ length.add((byte) (progSize & 0xff));
+
+ }
+
+ TPSBuffer tbsProgramFile = new TPSBuffer(tag);
+ tbsProgramFile.add(length);
+ tbsProgramFile.add(programFile);
+
+ int totalLen = tbsProgramFile.size();
+ int sizeToSend = totalLen;
+
+ int finalBlockSize = 0;
+ float progressBlockSize = 0;
+
+ if (secLevel == SecurityLevel.SECURE_MSG_MAC_ENC) {
+ // need leave room for possible encryption padding
+ finalBlockSize = blockSize - 0x10;
+ } else {
+ finalBlockSize = blockSize - 8;
+ }
+
+ //rough number is good enough
+ int numLoops = sizeToSend / blockSize;
+
+ if (numLoops == 0) { // We have bogus data here. Good bye.
+ throw new TPSException("SecureChannel.loadFile. Bad input data.", TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+ progressBlockSize = (float) (endProgress - startProgress) / numLoops;
+
+ int count = 0;
+ byte refControl = 0x00;
+
+ do {
+ if (sizeToSend < finalBlockSize) {
+ finalBlockSize = sizeToSend;
+ refControl = (byte) 0x80;
+
+ }
+
+ CMS.debug("SecureChannel.loadFile: taking data substring from: " + (totalLen - sizeToSend) + " size: "
+ + finalBlockSize + " to: " + ((totalLen - sizeToSend) + finalBlockSize));
+
+ TPSBuffer piece = tbsProgramFile.substr(totalLen - sizeToSend, finalBlockSize);
+
+ CMS.debug("SecureChannel.loadFile: attempting to send piece: " + sizeToSend);
+
+ loadFileSegment(refControl, count, piece);
+
+ if (processor.requiresStatusUpdate()) {
+ processor.statusUpdate(startProgress + (int) (count * progressBlockSize), "PROGRESS_APPLET_BLOCK");
+ }
+
+ sizeToSend -= finalBlockSize;
+
+ count++;
+
+ } while (sizeToSend > 0);
+
+ }
+
+ //Load one piece of the applet file onto the token.
+ private void loadFileSegment(byte refControl, int count, TPSBuffer piece) throws TPSException, IOException {
+
+ if (piece == null || count < 0) {
+ throw new TPSException("SecureChannel.loadFileSegment: invalid input data.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ LoadFileAPDU loadFile = new LoadFileAPDU(refControl, (byte) count, piece);
+
+ computeAPDU(loadFile);
+
+ APDUResponse response = processor.handleAPDURequest(loadFile);
+
+ if (!response.checkResult()) {
+ throw new TPSException(
+ "SecureChannel.loadFileSegment. Failed to perform loadFileSegmentInstallLoad operation.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ }
+
+ // Kick off the applet loading process.
+ public void installApplet(TPSBuffer netkeyPAIDBuff, TPSBuffer netkeyAIDBuff, byte appPrivileges,
+ int channelInstanceSize,
+ int channelAppletMemSize) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.installApplet: entering...");
+
+ // Would be tough to put a check on the various input sizes, let the applet
+ // decide if the values are appropriate for channelInstanceSize and channelAppletMemSize
+
+ if (netkeyPAIDBuff == null || netkeyAIDBuff == null || channelInstanceSize < 0 || channelAppletMemSize < 0) {
+ throw new TPSException("SecureChannel.installApplet. Invalid input parameters!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+ }
+
+ InstallAppletAPDU install = new InstallAppletAPDU(netkeyPAIDBuff, netkeyAIDBuff, appPrivileges,
+ channelInstanceSize, channelAppletMemSize);
+
+ computeAPDU(install);
+
+ APDUResponse response = processor.handleAPDURequest(install);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.installApplett. Failed installApplet operation.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ }
+
+ // Burn the phone home URL into the token.
+ public void setIssuerInfo(TPSBuffer issuerInfoBuff) throws TPSException, IOException {
+ CMS.debug("SecureChannel.setIssuerInfo entering...");
+
+ final int finalIssuerLength = 224;
+ final int approxMinUrlSize = 5;
+
+ if (issuerInfoBuff == null || issuerInfoBuff.size() < approxMinUrlSize) {
+ throw new TPSException("SecureChannel.setIssuerInfo: Invalid input data.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ int issuerLen = issuerInfoBuff.size();
+
+ int paddingLen = finalIssuerLength - issuerLen;
+
+ TPSBuffer paddingBuff = new TPSBuffer(paddingLen, (byte) 0x0);
+
+ TPSBuffer finalIssuerBuff = new TPSBuffer(issuerInfoBuff);
+
+ finalIssuerBuff.add(paddingBuff);
+
+ CMS.debug("finalIssuerBuff len: " + finalIssuerBuff.size() + " issuerInfo: " + finalIssuerBuff.toString());
+ SetIssuerInfoAPDU setIssuer = new SetIssuerInfoAPDU((byte) 0x0, (byte) 0x0, finalIssuerBuff);
+
+ computeAPDU(setIssuer);
+
+ APDUResponse response = processor.handleAPDURequest(setIssuer);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.setIssuerInfo. Failed to set issuer info!",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ CMS.debug("SecureChannel.setIssuerInfo: leaving...");
+
+ }
+
+ public TPSBuffer getKeyDiversificationData() {
+ return keyDiversificationData;
+ }
+
+ public TPSBuffer getCardChallenge() {
+ return cardChallenge;
+ }
+
+ public TPSBuffer getHostChallenge() {
+ return hostChallenge;
+ }
+
+ public TPSBuffer getHostCryptogram() {
+ return hostCryptogram;
+ }
+
+ public TPSBuffer getCardCryptogram() {
+ return cardCryptogram;
+ }
+
+ public TPSBuffer getKeyInfoData() {
+ 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 ...");
+
+ if (objectID == null || len == 0) {
+ throw new TPSException("SecureChannel.readObject: invalid input data.",
+ TPSStatus.STATUS_ERROR_READ_OBJECT_PDU);
+ }
+
+ final int MAX_READ_BUFFER_SIZE = 0xd0;
+
+ ReadObjectAPDU read = null;
+ TPSBuffer result = new TPSBuffer();
+
+ int cur_read = 0;
+ int cur_offset = 0;
+ int sum = 0;
+
+ if (len > MAX_READ_BUFFER_SIZE) {
+ cur_offset = offset;
+ cur_read = MAX_READ_BUFFER_SIZE;
+ } else {
+ cur_offset = offset;
+ cur_read = len;
+ }
+
+ while (sum < len) {
+
+ read = new ReadObjectAPDU(objectID.toBytesArray(), cur_offset, cur_read);
+ computeAPDU(read);
+
+ APDUResponse response = processor.handleAPDURequest(read);
+
+ if (!response.checkResult()) {
+ CMS.debug("SecureChannel.readObject: bad apdu return!");
+ throw new TPSException("SecureChannel.installApplett. Failed in middle of readObject.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ TPSBuffer resp = response.getResultDataNoCode();
+
+ result.add(resp);
+
+ sum += resp.size();
+ cur_offset += resp.size();
+
+ if ((len - sum) < MAX_READ_BUFFER_SIZE) {
+ cur_read = len - sum;
+ } else {
+ cur_read = MAX_READ_BUFFER_SIZE;
+ }
+
+ }
+
+ 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 {
+
+ if (wrappedChallenge == null) {
+ throw new TPSException("SecureChannel.startEnrollment. Bad input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("SecureChannel.startEnrollment: entering ...");
+
+ boolean isECC = processor.getTPSEngine().isAlgorithmECC(algorithm);
+
+ GenerateKeyAPDU generate_key_apdu = null;
+ GenerateKeyECCAPDU generate_ecc_key_apdu = null;
+
+ APDUResponse response = null;
+ if (isECC) {
+
+ generate_ecc_key_apdu = new GenerateKeyECCAPDU((byte) pe1, (byte) pe2, (byte) algorithm, keySize,
+ (byte) option, (byte) 0, wrappedChallenge, keyCheck);
+
+ computeAPDU(generate_ecc_key_apdu);
+
+ response = processor.handleAPDURequest(generate_ecc_key_apdu);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.startEnrollment. Failed generate key on token.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ } else {
+
+ generate_key_apdu = new GenerateKeyAPDU((byte) pe1, (byte) pe2, (byte) algorithm, keySize,
+ (byte) option, (byte) 0, wrappedChallenge, keyCheck);
+
+ computeAPDU(generate_key_apdu);
+
+ response = processor.handleAPDURequest(generate_key_apdu);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.startEnrollment. Failed generate key on token.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ }
+
+ TPSBuffer data = response.getData();
+
+ int size = data.getIntFrom2Bytes(0);
+
+ CMS.debug("SecureChannel.startEnrollment: returning key size: " + size);
+
+ return size;
+
+ }
+
+ 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);
+
+ @SuppressWarnings("unused")
+ 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);
+ }
+
+ }
+
+ public void putKeys(byte curVersion, byte curIndex, TPSBuffer keySetData) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.putKeys: entering..");
+
+ if (keySetData == null) {
+ throw new TPSException("SecureChannel.putKeys: Invalid input data!", TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+ }
+
+ byte keyVersion = curVersion;
+
+ if (curVersion == 0xff) {
+ keyVersion = 0x0;
+ }
+
+ PutKeyAPDU putKey = new PutKeyAPDU(keyVersion, (byte) (0x80 | curIndex), keySetData);
+
+ computeAPDU(putKey);
+
+ APDUResponse response = processor.handleAPDURequest(putKey);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.putKeys: failed to upgrade key set!",
+ TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+ }
+
+ }
+
+ public TPSBuffer getDRMWrappedDesKey() {
+ return drmDesKey;
+ }
+
+ public void setDRMWrappedDesKey(TPSBuffer drmDesKey) {
+ this.drmDesKey = drmDesKey;
+ }
+
+ public TPSBuffer getKeyCheck() {
+ return keyCheck;
+ }
+
+ public void setKeyCheck(TPSBuffer theKeyCheck) {
+ this.keyCheck = theKeyCheck;
+ }
+
+ public void importKeyEnc(int pe1, int pe2, TPSBuffer data) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.importKeyEnc entering...");
+
+ if(data == null) {
+ throw new TPSException("SecureChannel.importKeyEnc: Invalid input data!",TPSStatus.STATUS_ERROR_MAC_CERT_PDU);
+ }
+
+ ImportKeyEncAPDU importKeyEnc = new ImportKeyEncAPDU((byte)pe1,(byte) pe2, data);
+
+ computeAPDU(importKeyEnc);
+
+ APDUResponse response = processor.handleAPDURequest(importKeyEnc);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.importKeyEnc: failed to import private key!",
+ TPSStatus.STATUS_ERROR_MAC_CERT_PDU);
+ }
+
+ }
+
+ public TPSBuffer getKekDesKey() {
+ return kekDesKey;
+ }
+
+ public void setKekDesKey(TPSBuffer kekDesKey) {
+ this.kekDesKey = kekDesKey;
+ }
+
+}