summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/common/src/org/dogtagpki/tps/apdu/APDU.java35
-rw-r--r--base/common/src/org/dogtagpki/tps/apdu/DeleteFileGP211APDU.java31
-rw-r--r--base/common/src/org/dogtagpki/tps/apdu/ExternalAuthenticateAPDUGP211.java125
-rw-r--r--base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java11
-rw-r--r--base/common/src/org/dogtagpki/tps/apdu/InstallAppletAPDUGP211.java101
-rw-r--r--base/common/src/org/dogtagpki/tps/apdu/InstallLoadGP211APDU.java51
-rw-r--r--base/common/src/org/dogtagpki/tps/apdu/LoadFileAPDUGP211.java48
-rw-r--r--base/common/src/org/dogtagpki/tps/main/TPSBuffer.java10
-rw-r--r--base/common/src/org/dogtagpki/tps/main/TPSException.java4
-rw-r--r--base/common/src/org/dogtagpki/tps/main/Util.java165
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java1400
-rw-r--r--base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java4
-rw-r--r--base/symkey/src/com/netscape/symkey/Buffer.cpp6
-rw-r--r--base/symkey/src/com/netscape/symkey/EncryptData.cpp5
-rw-r--r--base/symkey/src/com/netscape/symkey/SessionKey.cpp604
-rw-r--r--base/symkey/src/com/netscape/symkey/SessionKey.java17
-rw-r--r--base/symkey/src/com/netscape/symkey/SymKey.cpp446
-rw-r--r--base/symkey/src/com/netscape/symkey/SymKey.h5
-rw-r--r--base/tks/shared/conf/CS.cfg.in2
-rw-r--r--base/tps/shared/conf/CS.cfg.in2
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java108
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java536
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java159
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java66
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java14
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java532
26 files changed, 3800 insertions, 687 deletions
diff --git a/base/common/src/org/dogtagpki/tps/apdu/APDU.java b/base/common/src/org/dogtagpki/tps/apdu/APDU.java
index c1aa51716..86f07ee70 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/APDU.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/APDU.java
@@ -67,6 +67,7 @@ public abstract class APDU {
protected TPSBuffer data = null;
protected TPSBuffer plainText = null;
protected TPSBuffer mac = null;
+ protected TPSBuffer trailer = null;
public APDU() {
data = new TPSBuffer();
@@ -101,6 +102,10 @@ public abstract class APDU {
mac = theMac;
}
+ public void setTrailer(TPSBuffer theTrailer) {
+ trailer = theTrailer;
+ }
+
/**
* Retrieves APDU's encoding.
* The encoding of APDU is as follows:
@@ -140,6 +145,10 @@ public abstract class APDU {
encoding.add(mac);
}
+ if (trailer != null) {
+ encoding.add(trailer);
+ }
+
return encoding;
}
@@ -156,7 +165,7 @@ public abstract class APDU {
return mac;
}
- public void secureMessage(PK11SymKey encKey) throws EBaseException {
+ public void secureMessage(PK11SymKey encKey, byte protocol) throws EBaseException {
if (encKey == null) {
throw new EBaseException("APDU.secureData: No input encrytion session key!");
@@ -169,14 +178,24 @@ public abstract class APDU {
TPSBuffer dataEncrypted = null;
dataToEnc = new TPSBuffer();
- dataToEnc.add((byte) data.size());
+
+ if(protocol == (byte) 1) {
+ dataToEnc.add((byte) data.size());
+ }
+
dataToEnc.add(data);
int dataSize = dataToEnc.size();
int rem = dataSize % 8;
if (rem == 0) {
- padNeeded = 0;
+
+ if (protocol == (byte) 1) {
+ padNeeded = 0;
+ }
+ else if (protocol == (byte) 2) {
+ padNeeded = 8;
+ }
} else if (dataSize < 8) {
padNeeded = 8 - dataSize;
} else {
@@ -198,6 +217,16 @@ public abstract class APDU {
data.set(dataEncrypted);
}
+ public void secureMessageSCP02(PK11SymKey encKey) throws EBaseException {
+
+ if (encKey == null) {
+ throw new EBaseException("APDU.secureDataSCP02: Invalid input data!");
+ }
+
+ secureMessage(encKey,(byte) 2);
+
+ }
+
public Type getType() {
return Type.APDU_UNDEFINED;
}
diff --git a/base/common/src/org/dogtagpki/tps/apdu/DeleteFileGP211APDU.java b/base/common/src/org/dogtagpki/tps/apdu/DeleteFileGP211APDU.java
new file mode 100644
index 000000000..ec91f50d6
--- /dev/null
+++ b/base/common/src/org/dogtagpki/tps/apdu/DeleteFileGP211APDU.java
@@ -0,0 +1,31 @@
+package org.dogtagpki.tps.apdu;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+public class DeleteFileGP211APDU extends APDU {
+ public DeleteFileGP211APDU(TPSBuffer aid) {
+ trailer = new TPSBuffer();
+ trailer.add((byte) 0x0);
+
+ setCLA((byte) 0x84);
+ setINS((byte) 0xE4);
+ setP1((byte) 0x00);
+ setP2((byte) 0x80);
+
+ TPSBuffer AIDTLV = new TPSBuffer();
+
+ AIDTLV.add((byte) 0x4f);
+ AIDTLV.add((byte) aid.size());
+
+ AIDTLV.add(aid);
+
+ setData(AIDTLV);
+
+ }
+
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/base/common/src/org/dogtagpki/tps/apdu/ExternalAuthenticateAPDUGP211.java b/base/common/src/org/dogtagpki/tps/apdu/ExternalAuthenticateAPDUGP211.java
new file mode 100644
index 000000000..bd687848c
--- /dev/null
+++ b/base/common/src/org/dogtagpki/tps/apdu/ExternalAuthenticateAPDUGP211.java
@@ -0,0 +1,125 @@
+// --- 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.tps.apdu;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+public class ExternalAuthenticateAPDUGP211 extends APDU {
+
+ public enum SecurityLevel {
+ SECURE_MSG_NONE, //not yet supported
+ CMAC,
+ CDEC_CMAC,
+ RMAC,
+ CMAC_RMAC,
+ CDEC_CMAC_RMAC
+
+ }
+
+ public ExternalAuthenticateAPDUGP211(TPSBuffer theData, SecurityLevel securityLevel) {
+ setCLA((byte) 0x84);
+ setINS((byte) 0x82);
+
+ setP1(securityLevelToByte(securityLevel));
+ setP2((byte) 0x0);
+
+ setData(theData);
+ }
+
+ public TPSBuffer getHostCryptogram()
+ {
+ return getData();
+ }
+
+ @Override
+ public APDU.Type getType()
+ {
+ return APDU.Type.APDU_EXTERNAL_AUTHENTICATE;
+ }
+
+ public static byte securityLevelToByte(SecurityLevel level) {
+ byte result = 0;
+
+ switch (level) {
+ case SECURE_MSG_NONE:
+ result = 0x0;
+ break;
+ case CMAC:
+ result = 0x1;
+ break;
+ case CDEC_CMAC:
+ result = 0x03;
+ break;
+ case RMAC:
+ result = 0x10;
+ break;
+
+ case CMAC_RMAC:
+ result = 0x11;
+ break;
+
+ case CDEC_CMAC_RMAC:
+ result = 0x13;
+ break;
+
+ default:
+ result = 0;
+ break;
+
+ }
+
+ return result;
+ }
+
+ public static SecurityLevel byteToSecurityLevel(byte level) {
+
+ SecurityLevel result = SecurityLevel.SECURE_MSG_NONE;
+
+ switch (level) {
+
+ case 0:
+ result = SecurityLevel.SECURE_MSG_NONE;
+ break;
+ case 1:
+ result = SecurityLevel.CMAC;
+ break;
+ case 0x03:
+ result = SecurityLevel.CDEC_CMAC;
+ break;
+ case 0x10:
+ result = SecurityLevel.RMAC;
+ break;
+
+ case 0x13:
+ result = SecurityLevel.CDEC_CMAC_RMAC;
+ break;
+ default:
+ result = SecurityLevel.SECURE_MSG_NONE;
+ break;
+ }
+
+ return result;
+
+ }
+
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java b/base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java
index 7cd52fcd1..6a2e8ed13 100644
--- a/base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java
+++ b/base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java
@@ -32,6 +32,17 @@ public class GetDataAPDU extends APDU {
setP2((byte) 0x7F);
}
+ public GetDataAPDU(byte[] identifier) {
+
+ this();
+
+ if(identifier != null && identifier.length == 2) {
+ setP1(identifier[0]);
+ setP2(identifier[1]);
+ }
+
+ }
+
@Override
public Type getType()
{
diff --git a/base/common/src/org/dogtagpki/tps/apdu/InstallAppletAPDUGP211.java b/base/common/src/org/dogtagpki/tps/apdu/InstallAppletAPDUGP211.java
new file mode 100644
index 000000000..a2bae0e14
--- /dev/null
+++ b/base/common/src/org/dogtagpki/tps/apdu/InstallAppletAPDUGP211.java
@@ -0,0 +1,101 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+package org.dogtagpki.tps.apdu;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+public class InstallAppletAPDUGP211 extends APDU {
+
+ public InstallAppletAPDUGP211(TPSBuffer packageAID, TPSBuffer appletAID,
+ byte appPrivileges, int instanceSize, int appletMemorySize)
+ {
+ trailer = new TPSBuffer();
+ trailer.add((byte)0x0);
+ setCLA((byte) 0x84);
+ setINS((byte) 0xE6);
+ setP1((byte) 0x0C);
+ setP2((byte) 0x00);
+
+ data = new TPSBuffer();
+ data.add((byte) packageAID.size());
+ data.add(packageAID);
+ data.add((byte) appletAID.size());
+ data.add(appletAID);
+ data.add((byte) appletAID.size());
+ data.add(appletAID);
+
+ data.add((byte) 0x01); // length of application privileges byte
+ data.add(appPrivileges);
+
+ TPSBuffer installParams = new TPSBuffer();
+ installParams.add((byte) 0xEF);
+ installParams.add((byte) 0x04);
+ installParams.add((byte) 0xC8);
+ installParams.add((byte) 0x02);
+
+ installParams.add((byte) ((instanceSize >> 8) & 0xff));
+ installParams.add((byte) (instanceSize & 0xff));
+ installParams.add((byte) 0xC9);
+
+ //Now add some applet specific init data that the applet supports
+ //Length of applet specific data
+
+ installParams.add((byte) 0x04);
+
+ //Issuer info length.
+ //Leave this to zero since TPS already writes phone home info to card.
+ installParams.add((byte) 0x00);
+
+ //Length of applet memory size
+ installParams.add((byte) 0x02);
+
+ // Applet memory block size
+
+ installParams.add((byte) ((appletMemorySize >> 8) & 0xff));
+ installParams.add((byte) (appletMemorySize & 0xff));
+
+ data.add((byte) installParams.size());
+ data.add(installParams);
+ data.add((byte) 0x00); // size of token return data
+ }
+
+ /**
+ * Constructs Install Applet APDU.
+ */
+ public InstallAppletAPDUGP211(TPSBuffer theData)
+ {
+ trailer = new TPSBuffer();
+ trailer.add((byte)0x0);
+ setCLA((byte) 0x84);
+ setINS((byte) 0xE6);
+ setP1((byte) 0x0C);
+ setP2((byte) 0x00);
+ setData(theData);
+ }
+
+ @Override
+ public Type getType()
+ {
+ return Type.APDU_INSTALL_APPLET;
+ }
+
+}
diff --git a/base/common/src/org/dogtagpki/tps/apdu/InstallLoadGP211APDU.java b/base/common/src/org/dogtagpki/tps/apdu/InstallLoadGP211APDU.java
new file mode 100644
index 000000000..d277fc6a1
--- /dev/null
+++ b/base/common/src/org/dogtagpki/tps/apdu/InstallLoadGP211APDU.java
@@ -0,0 +1,51 @@
+package org.dogtagpki.tps.apdu;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class InstallLoadGP211APDU extends APDU {
+
+ public InstallLoadGP211APDU(TPSBuffer packageAID, TPSBuffer sdAID,
+ int fileLen) {
+ setCLA((byte) 0x84);
+ setINS((byte) 0xE6);
+ setP1((byte) 0x02);
+ setP2((byte) 0x00);
+
+
+ CMS.debug("InstlalLoadGP211APDU: packageAID " + packageAID.toHexString() + " aid size: " + packageAID.size() + " fileLen: " + fileLen);
+
+ TPSBuffer inputData = new TPSBuffer();
+
+ // inputData.add((byte) 0x0);
+
+ inputData.add((byte) packageAID.size());
+ inputData.add(packageAID);
+ inputData.add((byte) sdAID.size());
+ inputData.add(sdAID);
+
+ //work in file size here
+
+ inputData.add((byte) 0x00);
+ inputData.add((byte) 0x06);
+
+ inputData.add((byte) 0xEF);
+ inputData.add((byte) 0x04);
+ inputData.add((byte) 0xc6);
+
+
+ inputData.add((byte) 0x02);
+ int finalLen = fileLen + 24 + sdAID.size();
+ inputData.addInt2Bytes(finalLen);
+
+ //assume no load file data block hash
+ inputData.add((byte) 0x0);
+
+ setData(inputData);
+
+ trailer = new TPSBuffer();
+ trailer.add((byte)0x0);
+ }
+
+}
diff --git a/base/common/src/org/dogtagpki/tps/apdu/LoadFileAPDUGP211.java b/base/common/src/org/dogtagpki/tps/apdu/LoadFileAPDUGP211.java
new file mode 100644
index 000000000..23e1ed790
--- /dev/null
+++ b/base/common/src/org/dogtagpki/tps/apdu/LoadFileAPDUGP211.java
@@ -0,0 +1,48 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+package org.dogtagpki.tps.apdu;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+public class LoadFileAPDUGP211 extends APDU {
+ /**
+ * Constructs Load File APDU.
+ */
+ public LoadFileAPDUGP211(byte refControl, byte blockNum, TPSBuffer theData)
+ {
+ trailer = new TPSBuffer();
+ setCLA((byte) 0x84);
+ setINS((byte) 0xE8);
+ setP1(refControl);
+ setP2(blockNum);
+
+ setData(theData);
+
+ }
+
+ @Override
+ public Type getType()
+ {
+ return Type.APDU_LOAD_FILE;
+ }
+
+}
+
diff --git a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
index 242f0825e..24c0b490a 100644
--- a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
+++ b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
@@ -156,6 +156,12 @@ public class TPSBuffer {
buf = newContents.toBytesArray();
}
+ public void set(byte [] newContents) {
+ if (newContents == null)
+ return;
+ buf = newContents;
+ }
+
/**
* Append operators.
*/
@@ -361,6 +367,10 @@ public class TPSBuffer {
return l1 + l2 + l3 + l4;
}
+ public void reset() {
+ buf = new byte[0];
+ }
+
public static void main(String[] args) {
byte[] first = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a };
diff --git a/base/common/src/org/dogtagpki/tps/main/TPSException.java b/base/common/src/org/dogtagpki/tps/main/TPSException.java
index 0d89aae5b..940e89ad1 100644
--- a/base/common/src/org/dogtagpki/tps/main/TPSException.java
+++ b/base/common/src/org/dogtagpki/tps/main/TPSException.java
@@ -26,8 +26,8 @@ public class TPSException extends EBaseException {
private static final long serialVersionUID = -678878301521643436L;
private TPSStatus status;
- public TPSException(String msg) {
- super(msg);
+ public TPSException(String e) {
+ super(e);
status = TPSStatus.STATUS_ERROR_CONTACT_ADMIN;
}
diff --git a/base/common/src/org/dogtagpki/tps/main/Util.java b/base/common/src/org/dogtagpki/tps/main/Util.java
index c10262208..2973bb8ec 100644
--- a/base/common/src/org/dogtagpki/tps/main/Util.java
+++ b/base/common/src/org/dogtagpki/tps/main/Util.java
@@ -43,6 +43,7 @@ import org.mozilla.jss.pkcs11.PK11SymKey;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.cmsutil.util.Utils;
+import com.netscape.symkey.SessionKey;
public class Util {
@@ -171,6 +172,166 @@ public class Util {
return Utils.SpecialEncode(data.toBytesArray());
}
+ public static TPSBuffer computeEncEcbDes(PK11SymKey symKey, TPSBuffer input) throws EBaseException {
+
+ //Asssume 8 bytes message
+ if (symKey == null || input == null || input.size() != 8) {
+ throw new EBaseException("Util.computeEncEcbDes: invalid input data!");
+ }
+
+ CMS.debug("Util.computeEncEcbDes entering... ");
+
+ TPSBuffer result = null;
+ CryptoToken token = null;
+
+ int inputLen = input.size();
+
+ TPSBuffer message = new TPSBuffer(input);
+
+ CMS.debug("Util.computeEncEcbDes: input data. " + message.toHexString() + " input len: " + inputLen);
+
+ try {
+
+ token = CryptoManager.getInstance().getInternalKeyStorageToken();
+
+ PK11SymKey des = SessionKey.DeriveDESKeyFrom3DesKey(token.getName(), symKey, 0x00000121 /*CKM_DES_ECB */);
+
+ if (des == null) {
+ throw new EBaseException("Util.computeEncEcbDes: Can't derive single des key from triple des key!");
+ }
+
+ TPSBuffer desDebug = new TPSBuffer(des.getEncoded());
+
+ CMS.debug("des key debug bytes: " + desDebug.toHexString());
+
+ Cipher cipher = token.getCipherContext(EncryptionAlgorithm.DES_ECB);
+
+ result = new TPSBuffer();
+
+ cipher.initEncrypt(des);
+ byte[] ciphResult = cipher.doFinal(message.toBytesArray());
+
+ if (ciphResult.length != 8) {
+ throw new EBaseException("Invalid cipher in Util.computeEncEcbDes");
+ }
+
+ result.set(ciphResult);
+
+ CMS.debug("Util.computeEncEcbDes: encrypted bloc: " + result.toHexString());
+
+ } catch (Exception e) {
+ throw new EBaseException("Util.computeMACdes3des: Cryptographic problem encountered! " + e.toString());
+ }
+
+ return result;
+ }
+
+ public static TPSBuffer computeMACdes3des(PK11SymKey symKey, TPSBuffer input, TPSBuffer initialIcv)
+ throws EBaseException {
+
+ if (symKey == null || input == null || initialIcv == null || initialIcv.size() != 8) {
+ throw new EBaseException("Util.coputeMACdes3des: invalid input data!");
+ }
+
+ CMS.debug("Util.computeMACdes3des entering... Initial icv: " + initialIcv.toHexString());
+
+ TPSBuffer output = null;
+ TPSBuffer mac = null;
+ CryptoToken token = null;
+
+ int inputLen = input.size();
+
+ TPSBuffer message = new TPSBuffer(input);
+ CMS.debug("Util.computeMACdes3des entering... Input message: " + message.toHexString() + " message.size(): "
+ + message.size());
+
+ //Add the padding, looks like we need this even if the remainder is 0
+ int remainder = inputLen % 8;
+
+ CMS.debug("Util.computeMACdes3des remainder: " + remainder);
+
+ TPSBuffer macPad = new TPSBuffer(8);
+ macPad.setAt(0, (byte) 0x80);
+
+ TPSBuffer padBuff = macPad.substr(0, 8 - remainder);
+
+ message.add(padBuff);
+ inputLen += (8 - remainder);
+
+ CMS.debug("Util.computeMACdes3des: padded input data. " + message.toHexString() + " input len: " + inputLen);
+
+ try {
+
+ token = CryptoManager.getInstance().getInternalKeyStorageToken();
+
+ PK11SymKey des = SessionKey.DeriveDESKeyFrom3DesKey(token.getName(), symKey, 0x00000122 /* CKM_DES_CBC */);
+
+ if (des == null) {
+ throw new EBaseException("Util.computeMACdes3des: Can't derive single des key from tripe des key!");
+ }
+
+ TPSBuffer desDebug = new TPSBuffer(des.getEncoded());
+
+ CMS.debug("des key debug bytes: " + desDebug.toHexString());
+
+ Cipher cipher = token.getCipherContext(EncryptionAlgorithm.DES_CBC);
+ Cipher cipher3des = token.getCipherContext(EncryptionAlgorithm.DES3_CBC);
+ mac = new TPSBuffer(initialIcv);
+
+ AlgorithmParameterSpec algSpec = new IVParameterSpec(initialIcv.toBytesArray());
+
+ int inputOffset = 0;
+
+ while (inputLen > 8)
+ {
+
+ mac.set(message.substr(inputOffset, 8));
+
+ // CMS.debug("About to encrypt1des: " + mac.toHexString());
+ cipher.initEncrypt(des, algSpec);
+ byte[] ciphResult = cipher.doFinal(mac.toBytesArray());
+
+ if (ciphResult.length != mac.size()) {
+ throw new EBaseException("Invalid cipher in Util.computeMAC");
+ }
+
+ mac.set(ciphResult);
+ algSpec = new IVParameterSpec(ciphResult);
+
+ // CMS.debug("Util.computeMACdes3des: des encrypted bloc: " + mac.toHexString());
+
+ inputLen -= 8;
+ inputOffset += 8;
+ }
+
+ // Now do the 3DES portion of the operation
+
+ TPSBuffer newICV = new TPSBuffer(mac);
+
+ CMS.debug("Util.computeMACdes3des: inputOffset: " + inputOffset);
+
+ mac.set(message.substr(inputOffset, 8));
+
+ CMS.debug("About to encrypt 3des: " + mac.toHexString() + " icv: " + newICV.toHexString());
+
+ cipher3des.initEncrypt(symKey, new IVParameterSpec(newICV.toBytesArray()));
+ byte[] ciphResultFinal = cipher3des.doFinal(mac.toBytesArray());
+
+ if (ciphResultFinal.length != mac.size()) {
+ throw new EBaseException("Invalid cipher in Util.computeMAC");
+ }
+
+ output = new TPSBuffer(ciphResultFinal);
+
+ CMS.debug("Util.computeMACdes3des: final mac results: " + output.toHexString());
+
+ } catch (Exception e) {
+ throw new EBaseException("Util.computeMACdes3des: Cryptographic problem encountered! " + e.toString());
+ }
+
+ return output;
+ }
+
public static TPSBuffer computeMAC(PK11SymKey symKey, TPSBuffer input, TPSBuffer icv) throws EBaseException {
TPSBuffer output = null;
TPSBuffer result = null;
@@ -271,6 +432,8 @@ public class Util {
throw new EBaseException("Util.encryptData: called with no sym key or no data!");
}
+ CMS.debug("Util.encryptData: dataToEnc: " + dataToEnc.toHexString());
+
CryptoToken token = null;
try {
@@ -280,9 +443,11 @@ public class Util {
AlgorithmParameterSpec algSpec = null;
int len = EncryptionAlgorithm.DES3_CBC.getIVLength();
+
byte[] iv = new byte[len]; // Assume iv set to 0's as in current TPS
algSpec = new IVParameterSpec(iv);
+
cipher.initEncrypt(encKey, algSpec);
byte[] encryptedBytes = cipher.doFinal(dataToEnc.toBytesArray());
diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
index 2cca81bcf..711701be8 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/tks/TokenServlet.java
@@ -29,7 +29,9 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.dogtagpki.server.connector.IRemoteRequest;
import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.KeyWrapper;
@@ -48,8 +50,6 @@ import com.netscape.cms.servlet.base.CMSServlet;
import com.netscape.cms.servlet.common.CMSRequest;
import com.netscape.symkey.SessionKey;
-import org.dogtagpki.server.connector.IRemoteRequest;
-
/**
* A class representings an administration servlet for Token Key
* Service Authority. This servlet is responsible to serve
@@ -107,6 +107,12 @@ public class TokenServlet extends CMSServlet {
private final static String LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE =
"LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE_4";
+ // Derivation Constants for SCP02
+ public final static byte[] C_MACDerivationConstant = { (byte) 0x01, (byte) 0x01 };
+ public final static byte[] ENCDerivationConstant = { 0x01, (byte) 0x82 };
+ public final static byte[] DEKDerivationConstant = { 0x01, (byte) 0x81 };
+ public final static byte[] R_MACDerivationConstant = { 0x01, 0x02 };
+
/**
* Constructs tks servlet.
*/
@@ -216,86 +222,92 @@ public class TokenServlet extends CMSServlet {
}
- // AC: KDF SPEC CHANGE - read new setting value from config file
+ // AC: KDF SPEC CHANGE - read new setting value from config file
// (This value allows configuration of which master keys use the NIST SP800-108 KDF and which use the original KDF for backwards compatibility)
// CAREFUL: Result returned may be negative due to java's lack of unsigned types.
// Negative values need to be treated as higher key numbers than positive key numbers.
- private static byte read_setting_nistSP800_108KdfOnKeyVersion(String keySet) throws Exception{
+ private static byte read_setting_nistSP800_108KdfOnKeyVersion(String keySet) throws Exception {
String nistSP800_108KdfOnKeyVersion_map = "tks." + keySet + ".nistSP800-108KdfOnKeyVersion";
// KDF phase1: default to 00
String nistSP800_108KdfOnKeyVersion_value =
- CMS.getConfigStore().getString(nistSP800_108KdfOnKeyVersion_map, "00" /*null*/);
+ CMS.getConfigStore().getString(nistSP800_108KdfOnKeyVersion_map, "00" /*null*/);
short nistSP800_108KdfOnKeyVersion_short = 0;
// if value does not exist in file
- if (nistSP800_108KdfOnKeyVersion_value == null){
+ if (nistSP800_108KdfOnKeyVersion_value == null) {
// throw
// (we want admins to pay attention to this configuration item rather than guessing for them)
- throw new Exception("Required configuration value \"" + nistSP800_108KdfOnKeyVersion_map + "\" missing from configuration file.");
+ throw new Exception("Required configuration value \"" + nistSP800_108KdfOnKeyVersion_map
+ + "\" missing from configuration file.");
}
// convert setting value (in ASCII-hex) to short
- try{
+ try {
nistSP800_108KdfOnKeyVersion_short = Short.parseShort(nistSP800_108KdfOnKeyVersion_value, 16);
- if ((nistSP800_108KdfOnKeyVersion_short < 0) || (nistSP800_108KdfOnKeyVersion_short > (short)0x00FF)){
+ if ((nistSP800_108KdfOnKeyVersion_short < 0) || (nistSP800_108KdfOnKeyVersion_short > (short) 0x00FF)) {
throw new Exception("Out of range.");
}
- } catch(Throwable t){
- throw new Exception("Configuration value \"" + nistSP800_108KdfOnKeyVersion_map + "\" is in incorrect format. " +
- "Correct format is \"" + nistSP800_108KdfOnKeyVersion_map + "=xx\" where xx is key version specified in ASCII-HEX format.", t);
+ } catch (Throwable t) {
+ throw new Exception("Configuration value \"" + nistSP800_108KdfOnKeyVersion_map
+ + "\" is in incorrect format. " +
+ "Correct format is \"" + nistSP800_108KdfOnKeyVersion_map
+ + "=xx\" where xx is key version specified in ASCII-HEX format.", t);
}
// convert to byte (anything higher than 0x7F is represented as a negative)
- byte nistSP800_108KdfOnKeyVersion_byte = (byte)nistSP800_108KdfOnKeyVersion_short;
+ byte nistSP800_108KdfOnKeyVersion_byte = (byte) nistSP800_108KdfOnKeyVersion_short;
return nistSP800_108KdfOnKeyVersion_byte;
}
-
- // AC: KDF SPEC CHANGE - read new setting value from config file
+
+ // AC: KDF SPEC CHANGE - read new setting value from config file
// (This value allows configuration of the NIST SP800-108 KDF:
// If "true" we use the CUID parameter within the NIST SP800-108 KDF.
// If "false" we use the KDD parameter within the NIST SP800-108 KDF.
- private static boolean read_setting_nistSP800_108KdfUseCuidAsKdd(String keySet) throws Exception{
+ private static boolean read_setting_nistSP800_108KdfUseCuidAsKdd(String keySet) throws Exception {
String setting_map = "tks." + keySet + ".nistSP800-108KdfUseCuidAsKdd";
// KDF phase1: default to "false"
String setting_str =
- CMS.getConfigStore().getString(setting_map, "false" /*null*/);
+ CMS.getConfigStore().getString(setting_map, "false" /*null*/);
boolean setting_boolean = false;
// if value does not exist in file
- if (setting_str == null){
+ if (setting_str == null) {
// throw
// (we want admins to pay attention to this configuration item rather than guessing for them)
throw new Exception("Required configuration value \"" + setting_map + "\" missing from configuration file.");
}
// convert setting value to boolean
- try{
+ try {
setting_boolean = Boolean.parseBoolean(setting_str);
- }catch(Throwable t){
- throw new Exception("Configuration value \"" + setting_map + "\" is in incorrect format. Should be either \"true\" or \"false\".", t);
+ } catch (Throwable t) {
+ throw new Exception("Configuration value \"" + setting_map
+ + "\" is in incorrect format. Should be either \"true\" or \"false\".", t);
}
return setting_boolean;
}
-
+
// AC: KDF SPEC CHANGE - Audit logging helper functions.
// Converts a byte array to an ASCII-hex string.
- // We implemented this ourselves rather than using this.pp.toHexArray() because
- // the team preferred CUID and KDD strings to be without ":" separators every byte.
+ // We implemented this ourselves rather than using this.pp.toHexArray() because
+ // the team preferred CUID and KDD strings to be without ":" separators every byte.
final char[] bytesToHex_hexArray = "0123456789ABCDEF".toCharArray();
- private String bytesToHex(byte[] bytes){
+
+ private String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
- for (int i = 0; i < bytes.length; i++){
+ for (int i = 0; i < bytes.length; i++) {
int thisChar = bytes[i] & 0x000000FF;
- hexChars[i * 2] = bytesToHex_hexArray[thisChar >>> 4]; // div 16
- hexChars[i*2 + 1] = bytesToHex_hexArray[thisChar & 0x0F];
+ hexChars[i * 2] = bytesToHex_hexArray[thisChar >>> 4]; // div 16
+ hexChars[i * 2 + 1] = bytesToHex_hexArray[thisChar & 0x0F];
}
return new String(hexChars);
}
-
+
// AC: KDF SPEC CHANGE - Audit logging helper functions.
// Safely converts a keyInfo byte array to a Key version hex string in the format: 0xa
- // Since key version is always the first byte, this function returns the unsigned hex string representation of parameter[0].
+ // Since key version is always the first byte, this function returns the unsigned hex string representation of parameter[0].
// Returns "null" if parameter is null.
// Returns "invalid" if parameter.length < 1
- private String log_string_from_keyInfo(byte[] xkeyInfo){
- return (xkeyInfo == null) ? "null" : (xkeyInfo.length < 1 ? "invalid" : "0x" + Integer.toHexString((int)(xkeyInfo[0]) & 0x000000FF) );
+ private String log_string_from_keyInfo(byte[] xkeyInfo) {
+ return (xkeyInfo == null) ? "null" : (xkeyInfo.length < 1 ? "invalid" : "0x"
+ + Integer.toHexString((xkeyInfo[0]) & 0x000000FF));
}
-
+
// AC: KDF SPEC CHANGE - Audit logging helper functions.
// Safely converts a byte array containing specialDecoded information to an ASCII-hex string.
// Parameters:
@@ -303,21 +315,551 @@ public class TokenServlet extends CMSServlet {
// Returns:
// if specialDecoded is blank, returns "null"
// if specialDecoded != null, returns <ASCII-HEX string representation of specialDecoded>
- private String log_string_from_specialDecoded_byte_array(byte[] specialDecoded){
- if (specialDecoded == null){
+ private String log_string_from_specialDecoded_byte_array(byte[] specialDecoded) {
+ if (specialDecoded == null) {
return "null";
- }else{
+ } else {
return bytesToHex(specialDecoded);
}
}
-
+
+ /* Compute Session Key for SCP02
+ * For simplicity compute just one session key,unless it is the DEK key case.
+ */
+
+ private void processComputeSessionKeySCP02(HttpServletRequest req, HttpServletResponse resp) throws EBaseException {
+
+ CMS.debug("TokenServlet.processComputeSessionKeySCP02 entering..");
+ String auditMessage = null;
+ String errorMsg = "";
+ String badParams = "";
+ String transportKeyName = "";
+ boolean missingParam = false;
+ String selectedToken = null;
+ String keyNickName = null;
+ byte[] drm_trans_wrapped_desKey = null;
+
+ byte[] xKDD = null;
+ byte nistSP800_108KdfOnKeyVersion = (byte) 0xff;
+ boolean nistSP800_108KdfUseCuidAsKdd = false;
+
+ IConfigStore sconfig = CMS.getConfigStore();
+
+ boolean isCryptoValidate = false;
+ byte[] keyInfo, CUID = null, session_key = null;
+
+ Exception missingSettingException = null;
+
+ String rCUID = req.getParameter(IRemoteRequest.TOKEN_CUID);
+
+ String rKDD = req.getParameter("KDD");
+ if ((rKDD == null) || (rKDD.length() == 0)) {
+ // KDF phase1: default to rCUID if not present
+ CMS.debug("TokenServlet: KDD not supplied, set to CUID before TPS change");
+ rKDD = rCUID;
+ }
+
+ String rKeyInfo = req.getParameter(IRemoteRequest.TOKEN_KEYINFO);
+
+ if ((rKeyInfo == null) || (rKeyInfo.equals(""))) {
+ badParams += " KeyInfo,";
+ CMS.debug("TokenServlet: processComputeSessionKeySCP02(): missing request parameter: key info");
+ missingParam = true;
+ }
+
+ keyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
+
+ String keySet = req.getParameter(IRemoteRequest.TOKEN_KEYSET);
+
+ if (keySet == null || keySet.equals("")) {
+ keySet = "defKeySet";
+ }
+ CMS.debug("TokenServlet.processComputeSessionKeySCP02: keySet selected: " + keySet + " keyInfo: " + rKeyInfo);
+
+ boolean serversideKeygen = false;
+
+ String rDerivationConstant = req.getParameter(IRemoteRequest.DERIVATION_CONSTANT);
+ String rSequenceCounter = req.getParameter(IRemoteRequest.SEQUENCE_COUNTER);
+
+ if ((rDerivationConstant == null) || (rDerivationConstant.equals(""))) {
+ badParams += " derivation_constant,";
+ CMS.debug("TokenServlet.processComputeSessionKeySCP02(): missing request parameter: derivation constant.");
+ missingParam = true;
+ }
+
+ if ((rSequenceCounter == null) || (rSequenceCounter.equals(""))) {
+ badParams += " sequence_counter,";
+ CMS.debug("TokenServlet.processComputeSessionKeySCP02(): missing request parameter: sequence counter.");
+ missingParam = true;
+ }
+
+ SessionContext sContext = SessionContext.getContext();
+
+ String agentId = "";
+ if (sContext != null) {
+ agentId =
+ (String) sContext.get(SessionContext.USER_ID);
+ }
+
+ auditMessage = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST,
+ rCUID,
+ rKDD, // AC: KDF SPEC CHANGE - Log both CUID and KDD.
+ ILogger.SUCCESS,
+ agentId);
+
+ audit(auditMessage);
+
+ if (!missingParam) {
+ CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
+
+ if (CUID == null || CUID.length != 10) {
+ badParams += " CUID length,";
+ CMS.debug("TokenServlet.processCompureSessionKeySCP02: Invalid CUID length");
+ missingParam = true;
+ }
+
+ xKDD = com.netscape.cmsutil.util.Utils.SpecialDecode(rKDD);
+ if (xKDD == null || xKDD.length != 10) {
+ badParams += " KDD length,";
+ CMS.debug("TokenServlet: Invalid KDD length");
+ missingParam = true;
+ }
+
+ keyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
+ if (keyInfo == null || keyInfo.length != 2) {
+ badParams += " KeyInfo length,";
+ CMS.debug("TokenServlet: Invalid key info length.");
+ missingParam = true;
+ }
+
+ try {
+ nistSP800_108KdfOnKeyVersion = TokenServlet.read_setting_nistSP800_108KdfOnKeyVersion(keySet);
+ nistSP800_108KdfUseCuidAsKdd = TokenServlet.read_setting_nistSP800_108KdfUseCuidAsKdd(keySet);
+
+ // log settings read in to debug log along with xkeyInfo
+ CMS.debug("TokenServlet: ComputeSessionKeySCP02(): keyInfo[0] = 0x"
+ + Integer.toHexString((keyInfo[0]) & 0x0000000FF)
+ + ", xkeyInfo[1] = 0x"
+ + Integer.toHexString((keyInfo[1]) & 0x0000000FF)
+ );
+ CMS.debug("TokenServlet: ComputeSessionKeySCP02(): Nist SP800-108 KDF will be used for key versions >= 0x"
+ + Integer.toHexString((nistSP800_108KdfOnKeyVersion) & 0x0000000FF)
+ );
+ if (nistSP800_108KdfUseCuidAsKdd == true) {
+ CMS.debug("TokenServlet: ComputeSessionKeySCP02(): Nist SP800-108 KDF (if used) will use CUID instead of KDD.");
+ } else {
+ CMS.debug("TokenServlet: ComputeSessionKeySCP02(): Nist SP800-108 KDF (if used) will use KDD.");
+ }
+ // conform to the set-an-error-flag mentality
+ } catch (Exception e) {
+ missingSettingException = e;
+ CMS.debug("TokenServlet: ComputeSessionKeySCP02(): Exception reading Nist SP800-108 KDF config values: "
+ + e.toString());
+ }
+
+ }
+
+ String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo; //#xx#xx
+ String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null);
+ if (mappingValue == null) {
+ selectedToken =
+ CMS.getConfigStore().getString("tks.defaultSlot", "internal");
+ keyNickName = rKeyInfo;
+ } else {
+ StringTokenizer st = new StringTokenizer(mappingValue, ":");
+ if (st.hasMoreTokens())
+ selectedToken = st.nextToken();
+ if (st.hasMoreTokens())
+ keyNickName = st.nextToken();
+ }
+
+ keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo; //#xx#xx
+ try {
+ mappingValue = CMS.getConfigStore().getString(keyInfoMap, null);
+ } catch (EBaseException e1) {
+
+ e1.printStackTrace();
+ }
+ if (mappingValue == null) {
+ try {
+ selectedToken =
+ CMS.getConfigStore().getString("tks.defaultSlot", "internal");
+ } catch (EBaseException e) {
+
+ e.printStackTrace();
+ }
+ keyNickName = rKeyInfo;
+ } else {
+ StringTokenizer st = new StringTokenizer(mappingValue, ":");
+ if (st.hasMoreTokens())
+ selectedToken = st.nextToken();
+ if (st.hasMoreTokens())
+ keyNickName = st.nextToken();
+ }
+
+ CMS.debug("TokenServlet: processComputeSessionKeySCP02(): final keyNickname: " + keyNickName);
+ String useSoftToken_s = null;
+ try {
+ useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true");
+ } catch (EBaseException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ if (!useSoftToken_s.equalsIgnoreCase("true"))
+ useSoftToken_s = "false";
+
+ String rServersideKeygen = req.getParameter(IRemoteRequest.SERVER_SIDE_KEYGEN);
+ if (rServersideKeygen.equals("true")) {
+ CMS.debug("TokenServlet.processComputeSessionKeySCP02: serversideKeygen requested");
+ serversideKeygen = true;
+ } else {
+ CMS.debug("TokenServlet.processComputeSessionKeySCP02: serversideKeygen not requested");
+ }
+
+ transportKeyName = null;
+ try {
+ transportKeyName = getSharedSecretName(sconfig);
+ } catch (EBaseException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ CMS.debug("TokenServlet.processComputeSessionKeySCP02: Can't find transport key name!");
+
+ }
+
+ CMS.debug("TokenServlet: processComputeSessionKeySCP02(): tksSharedSymKeyName: " + transportKeyName);
+
+ CMS.debug("TokenServlet: ComputeSessionKeySCP02(): tksSharedSymKeyName: " + transportKeyName);
+
+ try {
+ isCryptoValidate = sconfig.getBoolean("cardcryptogram.validate.enable", true);
+ } catch (EBaseException eee) {
+ }
+
+ byte macKeyArray[] = null;
+ byte sequenceCounter[] = null;
+ byte derivationConstant[] = null;
+
+ boolean errorFound = false;
+
+ String dek_wrapped_desKeyString = null;
+ String keycheck_s = null;
+
+ if (selectedToken != null && keyNickName != null && transportKeyName != null && missingSettingException == null) {
+ try {
+ macKeyArray = com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks."
+ + keySet + ".mac_key"));
+
+ sequenceCounter = com.netscape.cmsutil.util.Utils.SpecialDecode(rSequenceCounter);
+ derivationConstant = com.netscape.cmsutil.util.Utils.SpecialDecode(rDerivationConstant);
+
+ //Use old style for the moment.
+ //ToDo: We need to use the nistXP800 params we have collected and send them down to symkey
+ //Perform in next ticket to fully implement nistXP800
+
+ session_key = SessionKey.ComputeSessionKeySCP02(
+ selectedToken, keyNickName,
+ keyInfo, CUID, macKeyArray, sequenceCounter, derivationConstant, useSoftToken_s, keySet,
+ transportKeyName);
+
+ if (session_key == null) {
+ CMS.debug("TokenServlet.computeSessionKeySCP02:Tried ComputeSessionKey, got NULL ");
+ throw new EBaseException("Can't compute session key for SCP02!");
+
+ }
+
+ //Only do this for the dekSessionKey and if we are in the server side keygen case.
+ if (derivationConstant[0] == DEKDerivationConstant[0]
+ && derivationConstant[1] == DEKDerivationConstant[1] && serversideKeygen == true) {
+
+ CMS.debug("TokenServlet.computeSessionKeySCP02: We have the server side keygen case while generating the dek session key, wrap and return symkeys for the drm and token.");
+
+ /**
+ * 0. generate des key
+ * 1. encrypt des key with dek key
+ * 2. encrypt des key with DRM transport key
+ * These two wrapped items are to be sent back to
+ * TPS. 2nd item is to DRM
+ **/
+
+ PK11SymKey desKey = null;
+ PK11SymKey dekKey = null;
+
+ /*generate it on whichever token the master key is at*/
+ if (useSoftToken_s.equals("true")) {
+ CMS.debug("TokenServlet.computeSessionKeySCP02: key encryption key generated on internal");
+
+ desKey = SessionKey.GenerateSymkey("internal");
+
+ } else {
+ CMS.debug("TokenServlet.computeSessionKeySCP02: key encryption key generated on "
+ + selectedToken);
+ desKey = SessionKey.GenerateSymkey(selectedToken);
+ }
+ if (desKey != null)
+ CMS.debug("TokenServlet.computeSessionKeySCP02: key encryption key generated for " + rCUID);
+ else {
+ CMS.debug("TokenServlet.computeSessionKeySCP02: key encryption key generation failed for "
+ + rCUID);
+ throw new EBaseException(
+ "TokenServlet.computeSessionKeySCP02: can't generate key encryption key");
+ }
+
+ CryptoToken token = null;
+ if (useSoftToken_s.equals("true")) {
+ //token = CryptoManager.getInstance().getTokenByName(selectedToken);
+ token = CryptoManager.getInstance().getInternalCryptoToken();
+ } else {
+ token = CryptoManager.getInstance().getTokenByName(selectedToken);
+ }
+
+ //Now we have to create a sym key object for the wrapped session_key (dekKey)
+ // session_key wrapped by the shared Secret
+
+ PK11SymKey sharedSecret = getSharedSecretKey();
+
+ if (sharedSecret == null) {
+ throw new EBaseException(
+ "TokenServlet.computeSessionKeySCP02: Can't find share secret sym key!");
+ }
+
+ dekKey = SessionKey.UnwrapSessionKeyWithSharedSecret(token.getName(), sharedSecret,
+ session_key);
+
+ if (dekKey == null) {
+ throw new EBaseException(
+ "TokenServlet.computeSessionKeySCP02: Can't unwrap DEK key onto the token!");
+ }
+
+ /*
+ * ECBencrypt actually takes the 24 byte DES2 key
+ * and discard the last 8 bytes before it encrypts.
+ * This is done so that the applet can digest it
+ */
+ byte[] encDesKey =
+ SessionKey.ECBencrypt(dekKey,
+ desKey);
+
+ if (encDesKey == null) {
+ throw new EBaseException("TokenServlet.computeSessionKeySCP02: Can't encrypt DEK key!");
+ }
+
+ dek_wrapped_desKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(encDesKey);
+
+ byte[] keycheck =
+ SessionKey.ComputeKeyCheck(desKey);
+
+ if (keycheck == null) {
+ throw new EBaseException(
+ "TokenServlet.computeSessionKeySCP02: Can't compute key check for encrypted DEK key!");
+ }
+
+ keycheck_s =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(keycheck);
+
+ //use DRM transport cert to wrap desKey
+ String drmTransNickname = CMS.getConfigStore().getString("tks.drm_transport_cert_nickname", "");
+
+ if ((drmTransNickname == null) || (drmTransNickname == "")) {
+ CMS.debug("TokenServlet.computeSessionKeySCP02:did not find DRM transport certificate nickname");
+ throw new EBaseException("can't find DRM transport certificate nickname");
+ } else {
+ CMS.debug("TokenServlet.computeSessionKeySCP02:drmtransport_cert_nickname=" + drmTransNickname);
+ }
+
+ X509Certificate drmTransCert = null;
+ drmTransCert = CryptoManager.getInstance().findCertByNickname(drmTransNickname);
+ // wrap kek session key with DRM transport public key
+
+ PublicKey pubKey = drmTransCert.getPublicKey();
+ String pubKeyAlgo = pubKey.getAlgorithm();
+
+ KeyWrapper keyWrapper = null;
+ //For wrapping symmetric keys don't need IV, use ECB
+ if (pubKeyAlgo.equals("EC")) {
+ keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.AES_ECB);
+ keyWrapper.initWrap(pubKey, null);
+ } else {
+ keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.RSA);
+ keyWrapper.initWrap(pubKey, null);
+ }
+
+ drm_trans_wrapped_desKey = keyWrapper.wrap(desKey);
+ CMS.debug("computeSessionKey.computeSessionKeySCP02:desKey wrapped with drm transportation key.");
+
+ CMS.debug("computeSessionKey.computeSessionKeySCP02:desKey: Just unwrapped the dekKey onto the token to be wrapped on the way out.");
+
+ }
+
+ } catch (Exception e) {
+ CMS.debug("TokenServlet.computeSessionKeySCP02 Computing Session Key: " + e.toString());
+ errorFound = true;
+
+ }
+
+ }
+
+ String status = "0";
+ String value = "";
+ String outputString = "";
+
+ boolean statusDeclared = false;
+
+ if (session_key != null && session_key.length > 0 && errorFound == false) {
+ outputString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(session_key);
+ } else {
+
+ status = "1";
+ statusDeclared = true;
+ }
+
+ if (selectedToken == null || keyNickName == null) {
+ if (!statusDeclared) {
+ status = "4";
+ statusDeclared = true;
+ }
+ }
+
+ if (missingSettingException != null) {
+ if (!statusDeclared) {
+ status = "6";
+ statusDeclared = true;
+ }
+ }
+
+ if (missingParam) {
+ status = "3";
+ }
+
+ String drm_trans_wrapped_desKeyString = null;
+
+ if (!status.equals("0")) {
+ if (status.equals("1")) {
+ errorMsg = "Problem generating session key info.";
+ }
+
+ if (status.equals("4")) {
+ errorMsg = "Problem obtaining token information.";
+ }
+
+ if (status.equals("3")) {
+ if (badParams.endsWith(",")) {
+ badParams = badParams.substring(0, badParams.length() - 1);
+ }
+ errorMsg = "Missing input parameters :" + badParams;
+ }
+
+ if (status.equals("6")) {
+ errorMsg = "Problem reading required configuration value.";
+ }
+
+ } else {
+
+ if (serversideKeygen == true) {
+
+ if (drm_trans_wrapped_desKey != null && drm_trans_wrapped_desKey.length > 0) {
+ drm_trans_wrapped_desKeyString =
+ com.netscape.cmsutil.util.Utils.SpecialEncode(drm_trans_wrapped_desKey);
+ }
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(IRemoteRequest.RESPONSE_STATUS + "=0&");
+ sb.append(IRemoteRequest.TKS_RESPONSE_SessionKey + "=");
+ sb.append(outputString);
+
+ //Now add the trans wrapped des key
+
+ if (drm_trans_wrapped_desKeyString != null) {
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey + "=");
+ sb.append(drm_trans_wrapped_desKeyString);
+ }
+
+ if (dek_wrapped_desKeyString != null) {
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KEK_DesKey + "=");
+ sb.append(dek_wrapped_desKeyString);
+ }
+
+ if (keycheck_s != null) {
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KeyCheck + "=");
+ sb.append(keycheck_s);
+ }
+
+ value = sb.toString();
+ } else {
+ StringBuffer sb = new StringBuffer();
+ sb.append(IRemoteRequest.RESPONSE_STATUS + "=0&");
+ sb.append(IRemoteRequest.TKS_RESPONSE_SessionKey + "=");
+ sb.append(outputString);
+ value = sb.toString();
+ }
+
+ }
+
+ CMS.debug("TokenServlet:outputString.encode " + value);
+
+ try {
+ resp.setContentLength(value.length());
+ CMS.debug("TokenServlet:outputString.length " + value.length());
+ OutputStream ooss = resp.getOutputStream();
+ ooss.write(value.getBytes());
+ ooss.flush();
+ mRenderResult = false;
+ } catch (IOException e) {
+ CMS.debug("TokenServlet: " + e.toString());
+ }
+
+ if (status.equals("0")) {
+
+ String[] logParams = { log_string_from_specialDecoded_byte_array(CUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.SUCCESS, // Outcome
+ status, // status
+ agentId, // AgentID
+ isCryptoValidate ? "true" : "false", // IsCryptoValidate
+ serversideKeygen ? "true" : "false", // IsServerSideKeygen
+ selectedToken, // SelectedToken
+ keyNickName, // KeyNickName
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(keyInfo), // KeyInfo_KeyVersion
+ "0x" + Integer.toHexString(nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
+ Boolean.toString(nistSP800_108KdfUseCuidAsKdd) // NistSP800_108KdfUseCuidAsKdd
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS,
+ logParams);
+
+ } else {
+
+ String[] logParams = { log_string_from_specialDecoded_byte_array(CUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.FAILURE, // Outcome
+ status, // status
+ agentId, // AgentID
+ isCryptoValidate ? "true" : "false", // IsCryptoValidate
+ serversideKeygen ? "true" : "false", // IsServerSideKeygen
+ selectedToken, // SelectedToken
+ keyNickName, // KeyNickName
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(keyInfo), // KeyInfo_KeyVersion
+ "0x" + Integer.toHexString(nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
+ Boolean.toString(nistSP800_108KdfUseCuidAsKdd), // NistSP800_108KdfUseCuidAsKdd
+ errorMsg // Error
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,
+ logParams);
+ }
+
+ audit(auditMessage);
+
+ }
private void processComputeSessionKey(HttpServletRequest req,
HttpServletResponse resp) throws EBaseException {
- byte[] card_challenge ,host_challenge,keyInfo, xCUID, session_key, xKDD; // AC: KDF SPEC CHANGE: removed duplicative 'CUID' variable and added xKDD
+ byte[] card_challenge, host_challenge, keyInfo, xCUID, session_key, xKDD; // AC: KDF SPEC CHANGE: removed duplicative 'CUID' variable and added xKDD
// AC: KDF SPEC CHANGE - new config file values (needed for symkey)
- byte nistSP800_108KdfOnKeyVersion = (byte)0xff;
+ byte nistSP800_108KdfOnKeyVersion = (byte) 0xff;
boolean nistSP800_108KdfUseCuidAsKdd = false;
byte[] card_crypto, host_cryptogram, input_card_crypto;
@@ -327,7 +869,6 @@ public class TokenServlet extends CMSServlet {
String errorMsg = "";
String badParams = "";
String transportKeyName = "";
-
String rCUID = req.getParameter(IRemoteRequest.TOKEN_CUID);
// AC: KDF SPEC CHANGE - read new KDD parameter from TPS
@@ -353,10 +894,10 @@ public class TokenServlet extends CMSServlet {
IConfigStore sconfig = CMS.getConfigStore();
boolean isCryptoValidate = true;
boolean missingParam = false;
-
+
// AC: KDF SPEC CHANGE - flag for if there is an error reading our new setting
Exception missingSetting_exception = null;
-
+
session_key = null;
card_crypto = null;
host_cryptogram = null;
@@ -373,11 +914,11 @@ public class TokenServlet extends CMSServlet {
// AC: KDF SPEC CHANGE: Need to log both KDD and CUID
auditMessage = CMS.getLogMessage(
- LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST,
- rCUID,
- rKDD, // AC: KDF SPEC CHANGE - Log both CUID and KDD.
- ILogger.SUCCESS,
- agentId);
+ LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST,
+ rCUID,
+ rKDD, // AC: KDF SPEC CHANGE - Log both CUID and KDD.
+ ILogger.SUCCESS,
+ agentId);
audit(auditMessage);
@@ -415,7 +956,7 @@ public class TokenServlet extends CMSServlet {
badParams += " CUID,";
missingParam = true;
}
-
+
// AC: KDF SPEC CHANGE - read new KDD parameter from TPS
if ((rKDD == null) || (rKDD.length() == 0)) {
CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: KDD");
@@ -445,11 +986,11 @@ public class TokenServlet extends CMSServlet {
String keyNickName = null;
boolean sameCardCrypto = true;
- // AC: KDF SPEC CHANGE
- xCUID = null; // avoid errors about non-initialization
- xKDD = null; // avoid errors about non-initialization
- xkeyInfo = null; // avoid errors about non-initialization
-
+ // AC: KDF SPEC CHANGE
+ xCUID = null; // avoid errors about non-initialization
+ xKDD = null; // avoid errors about non-initialization
+ xkeyInfo = null; // avoid errors about non-initialization
+
if (!missingParam) {
xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
@@ -458,15 +999,15 @@ public class TokenServlet extends CMSServlet {
CMS.debug("TokenServlet: Invalid CUID length");
missingParam = true;
}
-
+
// AC: KDF SPEC CHANGE - read new KDD parameter from TPS
xKDD = com.netscape.cmsutil.util.Utils.SpecialDecode(rKDD);
if (xKDD == null || xKDD.length != 10) {
- badParams += " KDD length,";
- CMS.debug("TokenServlet: Invalid KDD length");
- missingParam = true;
+ badParams += " KDD length,";
+ CMS.debug("TokenServlet: Invalid KDD length");
+ missingParam = true;
}
-
+
xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
if (xkeyInfo == null || xkeyInfo.length != 2) {
badParams += " KeyInfo length,";
@@ -490,9 +1031,6 @@ public class TokenServlet extends CMSServlet {
}
- // AC: KDF SPEC CHANGE - Remove duplicative variable.
- // CUID = null;
-
if (!missingParam) {
card_challenge =
com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_challenge);
@@ -500,32 +1038,31 @@ public class TokenServlet extends CMSServlet {
host_challenge = com.netscape.cmsutil.util.Utils.SpecialDecode(rhost_challenge);
keyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo);
- // CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
- // AC: KDF SPEC CHANGE: Removed duplicative variable/processing.
-
// AC: KDF SPEC CHANGE - read new config file values (needed for symkey)
- try{
+ //ToDo: Will use these values after completing next ticket
+ try {
nistSP800_108KdfOnKeyVersion = TokenServlet.read_setting_nistSP800_108KdfOnKeyVersion(keySet);
nistSP800_108KdfUseCuidAsKdd = TokenServlet.read_setting_nistSP800_108KdfUseCuidAsKdd(keySet);
// log settings read in to debug log along with xkeyInfo
CMS.debug("TokenServlet: ComputeSessionKey(): xkeyInfo[0] = 0x"
- + Integer.toHexString((int)(xkeyInfo[0]) & 0x0000000FF)
- + ", xkeyInfo[1] = 0x"
- + Integer.toHexString((int)(xkeyInfo[1]) & 0x0000000FF)
- );
+ + Integer.toHexString((xkeyInfo[0]) & 0x0000000FF)
+ + ", xkeyInfo[1] = 0x"
+ + Integer.toHexString((xkeyInfo[1]) & 0x0000000FF)
+ );
CMS.debug("TokenServlet: ComputeSessionKey(): Nist SP800-108 KDF will be used for key versions >= 0x"
- + Integer.toHexString((int)(nistSP800_108KdfOnKeyVersion) & 0x0000000FF)
- );
- if (nistSP800_108KdfUseCuidAsKdd == true){
+ + Integer.toHexString((nistSP800_108KdfOnKeyVersion) & 0x0000000FF)
+ );
+ if (nistSP800_108KdfUseCuidAsKdd == true) {
CMS.debug("TokenServlet: ComputeSessionKey(): Nist SP800-108 KDF (if used) will use CUID instead of KDD.");
- }else{
+ } else {
CMS.debug("TokenServlet: ComputeSessionKey(): Nist SP800-108 KDF (if used) will use KDD.");
}
- // conform to the set-an-error-flag mentality
- }catch(Exception e){
+ // conform to the set-an-error-flag mentality
+ } catch (Exception e) {
missingSetting_exception = e;
- CMS.debug("TokenServlet: ComputeSessionKey(): Exception reading Nist SP800-108 KDF config values: " + e.toString());
+ CMS.debug("TokenServlet: ComputeSessionKey(): Exception reading Nist SP800-108 KDF config values: "
+ + e.toString());
}
String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo; //#xx#xx
@@ -555,12 +1092,12 @@ public class TokenServlet extends CMSServlet {
+ selectedToken + " keyNickName=" + keyNickName);
session_key = SessionKey.ComputeSessionKey(
selectedToken, keyNickName, card_challenge,
- host_challenge,keyInfo,
- nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
- nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
- xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
- xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- macKeyArray, useSoftToken_s, keySet, transportKeyName );
+ host_challenge, keyInfo,
+ nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+ nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+ xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+ xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+ macKeyArray, useSoftToken_s, keySet, transportKeyName);
if (session_key == null) {
CMS.debug("TokenServlet:Tried ComputeSessionKey, got NULL ");
@@ -573,12 +1110,12 @@ public class TokenServlet extends CMSServlet {
+ keySet + ".auth_key"));
enc_session_key = SessionKey.ComputeEncSessionKey(
selectedToken, keyNickName, card_challenge,
- host_challenge,keyInfo,
- nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
- nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
- xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
- xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- encKeyArray, useSoftToken_s, keySet);
+ host_challenge, keyInfo,
+ nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+ nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+ xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+ xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+ encKeyArray, useSoftToken_s, keySet);
if (enc_session_key == null) {
CMS.debug("TokenServlet:Tried ComputeEncSessionKey, got NULL ");
@@ -603,12 +1140,12 @@ public class TokenServlet extends CMSServlet {
kek_key = SessionKey.ComputeKekKey(
selectedToken, keyNickName, card_challenge,
- host_challenge,keyInfo,
- nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
- nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
- xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
- xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- kekKeyArray, useSoftToken_s,keySet);
+ host_challenge, keyInfo,
+ nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+ nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+ xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+ xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+ kekKeyArray, useSoftToken_s, keySet);
CMS.debug("TokenServlet: called ComputeKekKey");
@@ -647,15 +1184,15 @@ public class TokenServlet extends CMSServlet {
if (desKey != null) {
// AC: KDF SPEC CHANGE - Output using CUID and KDD
CMS.debug("TokenServlet: key encryption key generated for CUID=" +
- trim(pp.toHexString(xCUID)) +
- ", KDD=" +
- trim(pp.toHexString(xKDD)));
+ trim(pp.toHexString(xCUID)) +
+ ", KDD=" +
+ trim(pp.toHexString(xKDD)));
} else {
// AC: KDF SPEC CHANGE - Output using CUID and KDD
CMS.debug("TokenServlet: key encryption key generation failed for CUID=" +
- trim(pp.toHexString(xCUID)) +
- ", KDD=" +
- trim(pp.toHexString(xKDD)));
+ trim(pp.toHexString(xCUID)) +
+ ", KDD=" +
+ trim(pp.toHexString(xKDD)));
throw new Exception("can't generate key encryption key");
}
@@ -729,12 +1266,12 @@ public class TokenServlet extends CMSServlet {
+ keySet + ".auth_key"));
host_cryptogram = SessionKey.ComputeCryptogram(
selectedToken, keyNickName, card_challenge,
- host_challenge,keyInfo,
- nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
- nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
- xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
- xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- 0, authKeyArray, useSoftToken_s, keySet);
+ host_challenge, keyInfo,
+ nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+ nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+ xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+ xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+ 0, authKeyArray, useSoftToken_s, keySet);
if (host_cryptogram == null) {
CMS.debug("TokenServlet:Tried ComputeCryptogram, got NULL ");
@@ -743,13 +1280,12 @@ public class TokenServlet extends CMSServlet {
}
card_crypto = SessionKey.ComputeCryptogram(
selectedToken, keyNickName, card_challenge,
- host_challenge,keyInfo,
- nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
- nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
- xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
- xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- 1, authKeyArray, useSoftToken_s, keySet);
-
+ host_challenge, keyInfo,
+ nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+ nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+ xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+ xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+ 1, authKeyArray, useSoftToken_s, keySet);
if (card_crypto == null) {
CMS.debug("TokenServlet:Tried ComputeCryptogram, got NULL ");
@@ -781,9 +1317,9 @@ public class TokenServlet extends CMSServlet {
CMS.getLogger().log(ILogger.EV_AUDIT,
ILogger.S_TKS,
ILogger.LL_INFO, "processComputeSessionKey for CUID=" +
- trim(pp.toHexString(xCUID)) +
- ", KDD=" +
- trim(pp.toHexString(xKDD)));
+ trim(pp.toHexString(xCUID)) +
+ ", KDD=" +
+ trim(pp.toHexString(xKDD)));
} catch (Exception e) {
CMS.debug(e);
CMS.debug("TokenServlet Computing Session Key: " + e.toString());
@@ -831,32 +1367,32 @@ public class TokenServlet extends CMSServlet {
com.netscape.cmsutil.util.Utils.SpecialEncode(host_cryptogram);
} else {
// AC: Bugfix: Don't override status's value if an error was already flagged
- if (status.equals("0") == true){
+ if (status.equals("0") == true) {
status = "2";
}
}
if (selectedToken == null || keyNickName == null) {
// AC: Bugfix: Don't override status's value if an error was already flagged
- if (status.equals("0") == true){
+ if (status.equals("0") == true) {
status = "4";
}
}
if (!sameCardCrypto) {
// AC: Bugfix: Don't override status's value if an error was already flagged
- if (status.equals("0") == true){
+ if (status.equals("0") == true) {
// AC: Bugfix: Don't mis-represent host cryptogram mismatch errors as TPS parameter issues
status = "5";
}
}
// AC: KDF SPEC CHANGE - check for settings file issue (flag)
- if (missingSetting_exception != null){
+ if (missingSetting_exception != null) {
// AC: Intentionally override previous errors if config file settings were missing.
status = "6";
}
-
+
if (missingParam) {
// AC: Intentionally override previous errors if parameters were missing.
status = "3";
@@ -874,7 +1410,7 @@ public class TokenServlet extends CMSServlet {
// AC: Bugfix: Don't mis-represent card cryptogram mismatch errors as TPS parameter issues
if (status.equals("5")) {
- errorMsg = "Card cryptogram mismatch. Token likely has incorrect keys.";
+ errorMsg = "Card cryptogram mismatch. Token likely has incorrect keys.";
}
if (status.equals("4")) {
@@ -893,32 +1429,33 @@ public class TokenServlet extends CMSServlet {
errorMsg = "Missing input parameters :" + badParams;
}
- value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
+ value = IRemoteRequest.RESPONSE_STATUS + "=" + status;
} else {
if (serversideKeygen == true) {
StringBuffer sb = new StringBuffer();
- sb.append(IRemoteRequest.RESPONSE_STATUS+"=0&");
- sb.append(IRemoteRequest.TKS_RESPONSE_SessionKey+"=");
+ sb.append(IRemoteRequest.RESPONSE_STATUS + "=0&");
+ sb.append(IRemoteRequest.TKS_RESPONSE_SessionKey + "=");
sb.append(outputString);
- sb.append("&"+IRemoteRequest.TKS_RESPONSE_HostCryptogram+"=");
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_HostCryptogram + "=");
sb.append(cryptogram);
- sb.append("&"+IRemoteRequest.TKS_RESPONSE_EncSessionKey+"=");
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_EncSessionKey + "=");
sb.append(encSessionKeyString);
- sb.append("&"+IRemoteRequest.TKS_RESPONSE_KEK_DesKey+"=");
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KEK_DesKey + "=");
sb.append(kek_wrapped_desKeyString);
- sb.append("&"+IRemoteRequest.TKS_RESPONSE_KeyCheck+"=");
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KeyCheck + "=");
sb.append(keycheck_s);
- sb.append("&"+IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey+"=");
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey + "=");
sb.append(drm_trans_wrapped_desKeyString);
value = sb.toString();
} else {
+
StringBuffer sb = new StringBuffer();
- sb.append(IRemoteRequest.RESPONSE_STATUS+"=0&");
- sb.append(IRemoteRequest.TKS_RESPONSE_SessionKey+"=");
+ sb.append(IRemoteRequest.RESPONSE_STATUS + "=0&");
+ sb.append(IRemoteRequest.TKS_RESPONSE_SessionKey + "=");
sb.append(outputString);
- sb.append("&"+IRemoteRequest.TKS_RESPONSE_HostCryptogram+"=");
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_HostCryptogram + "=");
sb.append(cryptogram);
- sb.append("&"+IRemoteRequest.TKS_RESPONSE_EncSessionKey+"=");
+ sb.append("&" + IRemoteRequest.TKS_RESPONSE_EncSessionKey + "=");
sb.append(encSessionKeyString);
value = sb.toString();
}
@@ -941,41 +1478,44 @@ public class TokenServlet extends CMSServlet {
// AC: KDF SPEC CHANGE - Log both CUID and KDD.
// Also added TKSKeyset, KeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
// Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
- String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
- log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
- ILogger.SUCCESS, // Outcome
- status, // status
- agentId, // AgentID
- isCryptoValidate? "true":"false", // IsCryptoValidate
- serversideKeygen? "true":"false", // IsServerSideKeygen
- selectedToken, // SelectedToken
- keyNickName, // KeyNickName
- keySet, // TKSKeyset
- log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
- "0x" + Integer.toHexString((int)nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
- Boolean.toString(nistSP800_108KdfUseCuidAsKdd) // NistSP800_108KdfUseCuidAsKdd
- };
- auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, logParams);
+ String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.SUCCESS, // Outcome
+ status, // status
+ agentId, // AgentID
+ isCryptoValidate ? "true" : "false", // IsCryptoValidate
+ serversideKeygen ? "true" : "false", // IsServerSideKeygen
+ selectedToken, // SelectedToken
+ keyNickName, // KeyNickName
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
+ "0x" + Integer.toHexString(nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
+ Boolean.toString(nistSP800_108KdfUseCuidAsKdd) // NistSP800_108KdfUseCuidAsKdd
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS,
+ logParams);
+
} else {
// AC: KDF SPEC CHANGE - Log both CUID and KDD
// Also added TKSKeyset, KeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
// Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
- String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
- log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
- ILogger.FAILURE, // Outcome
- status, // status
- agentId, // AgentID
- isCryptoValidate? "true":"false", // IsCryptoValidate
- serversideKeygen? "true":"false", // IsServerSideKeygen
- selectedToken, // SelectedToken
- keyNickName, // KeyNickName
- keySet, // TKSKeyset
- log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
- "0x" + Integer.toHexString((int)nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
- Boolean.toString(nistSP800_108KdfUseCuidAsKdd), // NistSP800_108KdfUseCuidAsKdd
- errorMsg // Error
- };
- auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE, logParams);
+ String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.FAILURE, // Outcome
+ status, // status
+ agentId, // AgentID
+ isCryptoValidate ? "true" : "false", // IsCryptoValidate
+ serversideKeygen ? "true" : "false", // IsServerSideKeygen
+ selectedToken, // SelectedToken
+ keyNickName, // KeyNickName
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
+ "0x" + Integer.toHexString(nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
+ Boolean.toString(nistSP800_108KdfUseCuidAsKdd), // NistSP800_108KdfUseCuidAsKdd
+ errorMsg // Error
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,
+ logParams);
}
@@ -1014,18 +1554,18 @@ public class TokenServlet extends CMSServlet {
private void processDiversifyKey(HttpServletRequest req,
HttpServletResponse resp) throws EBaseException {
- byte[] KeySetData,KeysValues,xCUID,xKDD; // AC: KDF SPEC CHANGE: removed duplicative 'CUID' variable and added xKDD
+ byte[] KeySetData, xCUID, xKDD; // AC: KDF SPEC CHANGE: removed duplicative 'CUID' variable and added xKDD
// AC: BUGFIX: Record the actual parameters to DiversifyKey in the audit log.
String oldKeyNickName = null;
String newKeyNickName = null;
// AC: KDF SPEC CHANGE - new config file values (needed for symkey)
- byte nistSP800_108KdfOnKeyVersion = (byte)0xff;
+ byte nistSP800_108KdfOnKeyVersion = (byte) 0xff;
boolean nistSP800_108KdfUseCuidAsKdd = false;
// AC: BUGFIX for key versions higher than 09: We need to initialize these variables in order for the compiler not to complain when we pass them to DiversifyKey.
- byte[] xkeyInfo = null,xnewkeyInfo = null;
+ byte[] xkeyInfo = null, xnewkeyInfo = null;
// AC: KDF SPEC CHANGE - flag for if there is an error reading our new setting
Exception missingSetting_exception = null;
@@ -1033,6 +1573,7 @@ public class TokenServlet extends CMSServlet {
boolean missingParam = false;
String errorMsg = "";
String badParams = "";
+ byte[] xWrappedDekKey = null;
IConfigStore sconfig = CMS.getConfigStore();
String rnewKeyInfo = req.getParameter(IRemoteRequest.TOKEN_NEW_KEYINFO);
@@ -1048,6 +1589,9 @@ public class TokenServlet extends CMSServlet {
rKDD = rCUID;
}
+ String rProtocol = req.getParameter(IRemoteRequest.CHANNEL_PROTOCOL);
+ String rWrappedDekKey = req.getParameter(IRemoteRequest.WRAPPED_DEK_SESSION_KEY);
+ int protocol = 1;
String auditMessage = "";
String keySet = req.getParameter(IRemoteRequest.TOKEN_KEYSET);
@@ -1066,13 +1610,13 @@ public class TokenServlet extends CMSServlet {
// AC: KDF SPEC CHANGE: Need to log both KDD and CUID
auditMessage = CMS.getLogMessage(
- LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST,
- rCUID,
- rKDD, // AC: KDF SPEC CHANGE - Log both CUID and KDD.
- ILogger.SUCCESS,
- agentId,
- oldMasterKeyName,
- newMasterKeyName);
+ LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST,
+ rCUID,
+ rKDD, // AC: KDF SPEC CHANGE - Log both CUID and KDD.
+ ILogger.SUCCESS,
+ agentId,
+ oldMasterKeyName,
+ newMasterKeyName);
audit(auditMessage);
@@ -1081,14 +1625,14 @@ public class TokenServlet extends CMSServlet {
CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: CUID");
missingParam = true;
}
-
+
// AC: KDF SPEC CHANGE - read new KDD parameter from TPS
if ((rKDD == null) || (rKDD.length() == 0)) {
CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: KDD");
badParams += " KDD,";
missingParam = true;
}
-
+
if ((rnewKeyInfo == null) || (rnewKeyInfo.equals(""))) {
badParams += " newKeyInfo,";
CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: newKeyInfo");
@@ -1100,10 +1644,10 @@ public class TokenServlet extends CMSServlet {
missingParam = true;
}
- // AC: KDF SPEC CHANGE
- xCUID = null; // avoid errors about non-initialization
- xKDD = null; // avoid errors about non-initialization
- xkeyInfo = null; // avoid errors about non-initialization
+ // AC: KDF SPEC CHANGE
+ xCUID = null; // avoid errors about non-initialization
+ xKDD = null; // avoid errors about non-initialization
+ xkeyInfo = null; // avoid errors about non-initialization
xnewkeyInfo = null; // avoid errors about non-initialization
if (!missingParam) {
@@ -1119,6 +1663,29 @@ public class TokenServlet extends CMSServlet {
CMS.debug("TokenServlet: Invalid new key info length");
missingParam = true;
}
+
+ if (rProtocol != null) {
+ try {
+ protocol = Integer.parseInt(rProtocol);
+ } catch (NumberFormatException e) {
+ protocol = 1;
+ }
+ }
+ CMS.debug("process DiversifyKey: protocol value: " + protocol);
+
+ if (protocol == 2) {
+
+ if ((rWrappedDekKey == null) || (rWrappedDekKey.equals(""))) {
+ badParams += " WrappedDekKey,";
+ CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: WrappedDekKey, with SCP02.");
+ missingParam = true;
+ } else {
+
+ CMS.debug("process DiversifyKey: wrappedDekKey value: " + rWrappedDekKey);
+ xWrappedDekKey = com.netscape.cmsutil.util.Utils.SpecialDecode(rWrappedDekKey);
+ }
+
+ }
}
String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true");
if (!useSoftToken_s.equalsIgnoreCase("true"))
@@ -1142,36 +1709,39 @@ public class TokenServlet extends CMSServlet {
}
}
if (!missingParam) {
- // CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); // AC: KDF SPEC CHANGE: Removed duplicative variable/processing.
+ // CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); // AC: KDF SPEC CHANGE: Removed duplicative variable/processing.
+
+ // AC: KDF SPEC CHANGE - read new config file values (needed for symkey)
- // AC: KDF SPEC CHANGE - read new config file values (needed for symkey)
- try{
- nistSP800_108KdfOnKeyVersion = TokenServlet.read_setting_nistSP800_108KdfOnKeyVersion(keySet);
- nistSP800_108KdfUseCuidAsKdd = TokenServlet.read_setting_nistSP800_108KdfUseCuidAsKdd(keySet);
+ //ToDo: Refactor this, this same block occurs several times in the file
+ try {
+ nistSP800_108KdfOnKeyVersion = TokenServlet.read_setting_nistSP800_108KdfOnKeyVersion(keySet);
+ nistSP800_108KdfUseCuidAsKdd = TokenServlet.read_setting_nistSP800_108KdfUseCuidAsKdd(keySet);
- // log settings read in to debug log along with xkeyInfo and xnewkeyInfo
- CMS.debug("TokenServlet: processDiversifyKey(): xkeyInfo[0] (old) = 0x"
- + Integer.toHexString((int)(xkeyInfo[0]) & 0x0000000FF)
+ // log settings read in to debug log along with xkeyInfo and xnewkeyInfo
+ CMS.debug("TokenServlet: processDiversifyKey(): xkeyInfo[0] (old) = 0x"
+ + Integer.toHexString((xkeyInfo[0]) & 0x0000000FF)
+ ", xkeyInfo[1] (old) = 0x"
- + Integer.toHexString((int)(xkeyInfo[1]) & 0x0000000FF)
+ + Integer.toHexString((xkeyInfo[1]) & 0x0000000FF)
+ ", xnewkeyInfo[0] = 0x"
- + Integer.toHexString((int)(xnewkeyInfo[0]) & 0x000000FF)
+ + Integer.toHexString((xnewkeyInfo[0]) & 0x000000FF)
+ ", xnewkeyInfo[1] = 0x"
- + Integer.toHexString((int)(xnewkeyInfo[1]) & 0x000000FF)
- );
- CMS.debug("TokenServlet: processDiversifyKey(): Nist SP800-108 KDF will be used for key versions >= 0x"
- + Integer.toHexString((int)(nistSP800_108KdfOnKeyVersion) & 0x0000000FF)
- );
- if (nistSP800_108KdfUseCuidAsKdd == true){
- CMS.debug("TokenServlet: processDiversifyKey(): Nist SP800-108 KDF (if used) will use CUID instead of KDD.");
- }else{
- CMS.debug("TokenServlet: processDiversifyKey(): Nist SP800-108 KDF (if used) will use KDD.");
- }
- // conform to the set-an-error-flag mentality
- }catch(Exception e){
- missingSetting_exception = e;
- CMS.debug("TokenServlet: processDiversifyKey(): Exception reading Nist SP800-108 KDF config values: " + e.toString());
- }
+ + Integer.toHexString((xnewkeyInfo[1]) & 0x000000FF)
+ );
+ CMS.debug("TokenServlet: processDiversifyKey(): Nist SP800-108 KDF will be used for key versions >= 0x"
+ + Integer.toHexString((nistSP800_108KdfOnKeyVersion) & 0x0000000FF)
+ );
+ if (nistSP800_108KdfUseCuidAsKdd == true) {
+ CMS.debug("TokenServlet: processDiversifyKey(): Nist SP800-108 KDF (if used) will use CUID instead of KDD.");
+ } else {
+ CMS.debug("TokenServlet: processDiversifyKey(): Nist SP800-108 KDF (if used) will use KDD.");
+ }
+ // conform to the set-an-error-flag mentality
+ } catch (Exception e) {
+ missingSetting_exception = e;
+ CMS.debug("TokenServlet: processDiversifyKey(): Exception reading Nist SP800-108 KDF config values: "
+ + e.toString());
+ }
if (mKeyNickName != null)
oldMasterKeyName = mKeyNickName;
@@ -1208,55 +1778,53 @@ public class TokenServlet extends CMSServlet {
newKeyNickName);
byte kekKeyArray[] =
- com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
-
- // AC: KDF SPEC CHANGE - check for error reading settings
- if (missingSetting_exception == null){
- KeySetData = SessionKey.DiversifyKey(oldSelectedToken,
- newSelectedToken, oldKeyNickName,
- newKeyNickName,
- xkeyInfo, // AC: KDF SPEC CHANGE - pass in old key info so symkey can make decision about which KDF version to use
- xnewkeyInfo, // AC: BUGFIX for key versions higher than 09: We need to specialDecode keyInfo parameters before sending them into symkey! This means the parameters must be byte[]
- nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
- nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
- xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
- xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- kekKeyArray, useSoftToken_s, keySet);
-
- if (KeySetData == null || KeySetData.length <= 1) {
+ com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
+
+ // AC: KDF SPEC CHANGE - check for error reading settings
+ if (missingSetting_exception == null) {
+ KeySetData = SessionKey.DiversifyKey(oldSelectedToken,
+ newSelectedToken, oldKeyNickName,
+ newKeyNickName,
+ xkeyInfo, // AC: KDF SPEC CHANGE - pass in old key info so symkey can make decision about which KDF version to use
+ xnewkeyInfo, // AC: BUGFIX for key versions higher than 09: We need to specialDecode keyInfo parameters before sending them into symkey! This means the parameters must be byte[]
+ nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+ nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+ xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+ xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+ (protocol == 2) ? xWrappedDekKey : kekKeyArray, useSoftToken_s, keySet, (byte) protocol);
+
+ if (KeySetData == null || KeySetData.length <= 1) {
+ CMS.getLogger().log(ILogger.EV_AUDIT,
+ ILogger.S_TKS,
+ ILogger.LL_INFO, "process DiversifyKey: Missing MasterKey in Slot");
+ }
+
CMS.getLogger().log(ILogger.EV_AUDIT,
ILogger.S_TKS,
- ILogger.LL_INFO, "process DiversifyKey: Missing MasterKey in Slot");
- }
-
- CMS.getLogger().log(ILogger.EV_AUDIT,
- ILogger.S_TKS,
- ILogger.LL_INFO,
- "process DiversifyKey for CUID=" +
- trim(pp.toHexString(xCUID)) + // AC: KDF SPEC CHANGE: Log both CUID and KDD
- ", KDD=" +
- trim(pp.toHexString(xKDD))
- + ";from oldMasterKeyName=" + oldSelectedToken + ":" + oldKeyNickName
- + ";to newMasterKeyName=" + newSelectedToken + ":" + newKeyNickName);
+ ILogger.LL_INFO,
+ "process DiversifyKey for CUID=" +
+ trim(pp.toHexString(xCUID)) + // AC: KDF SPEC CHANGE: Log both CUID and KDD
+ ", KDD=" +
+ trim(pp.toHexString(xKDD))
+ + ";from oldMasterKeyName=" + oldSelectedToken + ":" + oldKeyNickName
+ + ";to newMasterKeyName=" + newSelectedToken + ":" + newKeyNickName);
- resp.setContentType("text/html");
+ resp.setContentType("text/html");
- } // AC: KDF SPEC CHANGE - endif no error reading settings from settings file
+ } // AC: KDF SPEC CHANGE - endif no error reading settings from settings file
} // ! missingParam
- //CMS.debug("TokenServlet:processDiversifyKey " +outputString);
- //String value="keySetData=%00" if the KeySetData=byte[0]=0;
String value = "";
String status = "0";
if (KeySetData != null && KeySetData.length > 1) {
- value = IRemoteRequest.RESPONSE_STATUS+"=0&" + IRemoteRequest.TKS_RESPONSE_KeySetData+"=" +
- com.netscape.cmsutil.util.Utils.SpecialEncode(KeySetData);
+ value = IRemoteRequest.RESPONSE_STATUS + "=0&" + IRemoteRequest.TKS_RESPONSE_KeySetData + "=" +
+ com.netscape.cmsutil.util.Utils.SpecialEncode(KeySetData);
CMS.debug("TokenServlet:process DiversifyKey.encode " + value);
- // AC: KDF SPEC CHANGE - check for settings file issue (flag)
- } else if (missingSetting_exception != null){
+ // AC: KDF SPEC CHANGE - check for settings file issue (flag)
+ } else if (missingSetting_exception != null) {
status = "6";
errorMsg = "Problem reading required configuration value.";
value = "status=" + status;
@@ -1266,11 +1834,11 @@ public class TokenServlet extends CMSServlet {
badParams = badParams.substring(0, badParams.length() - 1);
}
errorMsg = "Missing input parameters: " + badParams;
- value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
+ value = IRemoteRequest.RESPONSE_STATUS + "=" + status;
} else {
errorMsg = "Problem diversifying key data.";
status = "1";
- value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
+ value = IRemoteRequest.RESPONSE_STATUS + "=" + status;
}
resp.setContentLength(value.length());
@@ -1287,48 +1855,48 @@ public class TokenServlet extends CMSServlet {
if (status.equals("0")) {
- // AC: KDF SPEC CHANGE - Log both CUID and KDD
- // Also added TKSKeyset, OldKeyInfo_KeyVersion, NewKeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
- // Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
- String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
- log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
- ILogger.SUCCESS, // Outcome
- status, // status
- agentId, // AgentID
-
- // AC: BUGFIX: Record the actual parameters to DiversifyKey in the audit log.
- oldKeyNickName, // oldMasterKeyName
- newKeyNickName, // newMasterKeyName
-
- keySet, // TKSKeyset
- log_string_from_keyInfo(xkeyInfo), // OldKeyInfo_KeyVersion
- log_string_from_keyInfo(xnewkeyInfo), // NewKeyInfo_KeyVersion
- "0x" + Integer.toHexString((int)nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
- Boolean.toString(nistSP800_108KdfUseCuidAsKdd) // NistSP800_108KdfUseCuidAsKdd
- };
- auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, logParams);
+ // AC: KDF SPEC CHANGE - Log both CUID and KDD
+ // Also added TKSKeyset, OldKeyInfo_KeyVersion, NewKeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
+ // Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
+ String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.SUCCESS, // Outcome
+ status, // status
+ agentId, // AgentID
+
+ // AC: BUGFIX: Record the actual parameters to DiversifyKey in the audit log.
+ oldKeyNickName, // oldMasterKeyName
+ newKeyNickName, // newMasterKeyName
+
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(xkeyInfo), // OldKeyInfo_KeyVersion
+ log_string_from_keyInfo(xnewkeyInfo), // NewKeyInfo_KeyVersion
+ "0x" + Integer.toHexString(nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
+ Boolean.toString(nistSP800_108KdfUseCuidAsKdd) // NistSP800_108KdfUseCuidAsKdd
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, logParams);
} else {
- // AC: KDF SPEC CHANGE - Log both CUID and KDD
- // Also added TKSKeyset, OldKeyInfo_KeyVersion, NewKeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
- // Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
- String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
- log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
- ILogger.FAILURE, // Outcome
- status, // status
- agentId, // AgentID
-
- // AC: BUGFIX: Record the actual parameters to DiversifyKey in the audit log.
- oldKeyNickName, // oldMasterKeyName
- newKeyNickName, // newMasterKeyName
-
- keySet, // TKSKeyset
- log_string_from_keyInfo(xkeyInfo), // OldKeyInfo_KeyVersion
- log_string_from_keyInfo(xnewkeyInfo), // NewKeyInfo_KeyVersion
- "0x" + Integer.toHexString((int)nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
- Boolean.toString(nistSP800_108KdfUseCuidAsKdd), // NistSP800_108KdfUseCuidAsKdd
- errorMsg // Error
- };
- auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE, logParams);
+ // AC: KDF SPEC CHANGE - Log both CUID and KDD
+ // Also added TKSKeyset, OldKeyInfo_KeyVersion, NewKeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
+ // Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
+ String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.FAILURE, // Outcome
+ status, // status
+ agentId, // AgentID
+
+ // AC: BUGFIX: Record the actual parameters to DiversifyKey in the audit log.
+ oldKeyNickName, // oldMasterKeyName
+ newKeyNickName, // newMasterKeyName
+
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(xkeyInfo), // OldKeyInfo_KeyVersion
+ log_string_from_keyInfo(xnewkeyInfo), // NewKeyInfo_KeyVersion
+ "0x" + Integer.toHexString(nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
+ Boolean.toString(nistSP800_108KdfUseCuidAsKdd), // NistSP800_108KdfUseCuidAsKdd
+ errorMsg // Error
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE, logParams);
}
audit(auditMessage);
@@ -1336,10 +1904,10 @@ public class TokenServlet extends CMSServlet {
private void processEncryptData(HttpServletRequest req,
HttpServletResponse resp) throws EBaseException {
- byte[] keyInfo, xCUID, encryptedData, xkeyInfo, xKDD; // AC: KDF SPEC CHANGE: removed duplicative 'CUID' variable and added xKDD
+ byte[] keyInfo, xCUID, encryptedData, xkeyInfo, xKDD; // AC: KDF SPEC CHANGE: removed duplicative 'CUID' variable and added xKDD
// AC: KDF SPEC CHANGE - new config file values (needed for symkey)
- byte nistSP800_108KdfOnKeyVersion = (byte)0xff;
+ byte nistSP800_108KdfOnKeyVersion = (byte) 0xff;
boolean nistSP800_108KdfUseCuidAsKdd = false;
// AC: KDF SPEC CHANGE - flag for if there is an error reading our new setting
@@ -1391,13 +1959,12 @@ public class TokenServlet extends CMSServlet {
// AC: KDF SPEC CHANGE: Need to log both KDD and CUID
String auditMessage = CMS.getLogMessage(
- LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST,
- rCUID,
- rKDD, // AC: KDF SPEC CHANGE - Log both CUID and KDD.
- ILogger.SUCCESS,
- agentId,
- s_isRandom);
-
+ LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST,
+ rCUID,
+ rKDD, // AC: KDF SPEC CHANGE - Log both CUID and KDD.
+ ILogger.SUCCESS,
+ agentId,
+ s_isRandom);
audit(auditMessage);
if (isRandom) {
@@ -1441,9 +2008,9 @@ public class TokenServlet extends CMSServlet {
}
// AC: KDF SPEC CHANGE
- xCUID = null; // avoid errors about non-initialization
- xKDD = null; // avoid errors about non-initialization
- xkeyInfo = null; // avoid errors about non-initialization
+ xCUID = null; // avoid errors about non-initialization
+ xKDD = null; // avoid errors about non-initialization
+ xkeyInfo = null; // avoid errors about non-initialization
if (!missingParam) {
xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID);
@@ -1478,28 +2045,29 @@ public class TokenServlet extends CMSServlet {
if (!missingParam) {
// AC: KDF SPEC CHANGE - read new config file values (needed for symkey
- try{
+ try {
nistSP800_108KdfOnKeyVersion = TokenServlet.read_setting_nistSP800_108KdfOnKeyVersion(keySet);
nistSP800_108KdfUseCuidAsKdd = TokenServlet.read_setting_nistSP800_108KdfUseCuidAsKdd(keySet);
// log settings read in to debug log along with xkeyInfo
CMS.debug("TokenServlet: processEncryptData(): xkeyInfo[0] = 0x"
- + Integer.toHexString((int)(xkeyInfo[0]) & 0x0000000FF)
- + ", xkeyInfo[1] = 0x"
- + Integer.toHexString((int)(xkeyInfo[1]) & 0x0000000FF)
- );
+ + Integer.toHexString((xkeyInfo[0]) & 0x0000000FF)
+ + ", xkeyInfo[1] = 0x"
+ + Integer.toHexString((xkeyInfo[1]) & 0x0000000FF)
+ );
CMS.debug("TokenServlet: processEncryptData(): Nist SP800-108 KDF will be used for key versions >= 0x"
- + Integer.toHexString((int)(nistSP800_108KdfOnKeyVersion) & 0x0000000FF)
- );
- if (nistSP800_108KdfUseCuidAsKdd == true){
+ + Integer.toHexString((nistSP800_108KdfOnKeyVersion) & 0x0000000FF)
+ );
+ if (nistSP800_108KdfUseCuidAsKdd == true) {
CMS.debug("TokenServlet: processEncryptData(): Nist SP800-108 KDF (if used) will use CUID instead of KDD.");
- }else{
+ } else {
CMS.debug("TokenServlet: processEncryptData(): Nist SP800-108 KDF (if used) will use KDD.");
}
- // conform to the set-an-error-flag mentality
- }catch(Exception e){
+ // conform to the set-an-error-flag mentality
+ } catch (Exception e) {
missingSetting_exception = e;
- CMS.debug("TokenServlet: processEncryptData(): Exception reading Nist SP800-108 KDF config values: " + e.toString());
+ CMS.debug("TokenServlet: processEncryptData(): Exception reading Nist SP800-108 KDF config values: "
+ + e.toString());
}
if (!isRandom)
@@ -1519,29 +2087,27 @@ public class TokenServlet extends CMSServlet {
byte kekKeyArray[] =
com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key"));
- // AC: KDF SPEC CHANGE - check for error reading settings
- if (missingSetting_exception == null){
-
- encryptedData = SessionKey.EncryptData(
- selectedToken,keyNickName,data,keyInfo,
- nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
- nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
- xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
- xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
- kekKeyArray, useSoftToken_s, keySet);
+ // AC: KDF SPEC CHANGE - check for error reading settings
+ if (missingSetting_exception == null) {
- // AC: KDF SPEC CHANGE - Log both CUID and KDD
+ encryptedData = SessionKey.EncryptData(
+ selectedToken, keyNickName, data, keyInfo,
+ nistSP800_108KdfOnKeyVersion, // AC: KDF SPEC CHANGE - pass in configuration file value
+ nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value
+ xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID'
+ xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use
+ kekKeyArray, useSoftToken_s, keySet);
+ // AC: KDF SPEC CHANGE - Log both CUID and KDD
- CMS.getLogger().log(ILogger.EV_AUDIT,
- ILogger.S_TKS,
- ILogger.LL_INFO,"process EncryptData for CUID="+
- trim(pp.toHexString(xCUID)) +
- ", KDD=" +
- trim(pp.toHexString(xKDD)));
-
- } // AC: KDF SPEC CHANGE - endif no error reading settings from settings file
+ CMS.getLogger().log(ILogger.EV_AUDIT,
+ ILogger.S_TKS,
+ ILogger.LL_INFO, "process EncryptData for CUID=" +
+ trim(pp.toHexString(xCUID)) +
+ ", KDD=" +
+ trim(pp.toHexString(xKDD)));
+ } // AC: KDF SPEC CHANGE - endif no error reading settings from settings file
} // !missingParam
@@ -1551,13 +2117,13 @@ public class TokenServlet extends CMSServlet {
String status = "0";
if (encryptedData != null && encryptedData.length > 0) {
// sending both the pre-encrypted and encrypted data back
- value = IRemoteRequest.RESPONSE_STATUS+"=0&"
- + IRemoteRequest.TOKEN_DATA+"=" +
- com.netscape.cmsutil.util.Utils.SpecialEncode(data) +
- "&"+IRemoteRequest.TKS_RESPONSE_EncryptedData+"=" +
- com.netscape.cmsutil.util.Utils.SpecialEncode(encryptedData);
- // AC: KDF SPEC CHANGE - check for settings file issue (flag)
- } else if (missingSetting_exception != null){
+ value = IRemoteRequest.RESPONSE_STATUS + "=0&"
+ + IRemoteRequest.TOKEN_DATA + "=" +
+ com.netscape.cmsutil.util.Utils.SpecialEncode(data) +
+ "&" + IRemoteRequest.TKS_RESPONSE_EncryptedData + "=" +
+ com.netscape.cmsutil.util.Utils.SpecialEncode(encryptedData);
+ // AC: KDF SPEC CHANGE - check for settings file issue (flag)
+ } else if (missingSetting_exception != null) {
status = "6";
errorMsg = "Problem reading required configuration value.";
value = "status=" + status;
@@ -1567,11 +2133,11 @@ public class TokenServlet extends CMSServlet {
}
errorMsg = "Missing input parameters: " + badParams;
status = "3";
- value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
+ value = IRemoteRequest.RESPONSE_STATUS + "=" + status;
} else {
errorMsg = "Problem encrypting data.";
status = "1";
- value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
+ value = IRemoteRequest.RESPONSE_STATUS + "=" + status;
}
CMS.debug("TokenServlet:process EncryptData.encode " + value);
@@ -1589,42 +2155,42 @@ public class TokenServlet extends CMSServlet {
}
if (status.equals("0")) {
- // AC: KDF SPEC CHANGE - Log both CUID and KDD
- // Also added TKSKeyset, KeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
- // Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
- String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
- log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
- ILogger.SUCCESS, // Outcome
- status, // status
- agentId, // AgentID
- s_isRandom, // isRandom
- selectedToken, // SelectedToken
- keyNickName, // KeyNickName
- keySet, // TKSKeyset
- log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
- "0x" + Integer.toHexString((int)nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
- Boolean.toString(nistSP800_108KdfUseCuidAsKdd) // NistSP800_108KdfUseCuidAsKdd
- };
- auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS, logParams);
+ // AC: KDF SPEC CHANGE - Log both CUID and KDD
+ // Also added TKSKeyset, KeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
+ // Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
+ String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.SUCCESS, // Outcome
+ status, // status
+ agentId, // AgentID
+ s_isRandom, // isRandom
+ selectedToken, // SelectedToken
+ keyNickName, // KeyNickName
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
+ "0x" + Integer.toHexString(nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
+ Boolean.toString(nistSP800_108KdfUseCuidAsKdd) // NistSP800_108KdfUseCuidAsKdd
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS, logParams);
} else {
- // AC: KDF SPEC CHANGE - Log both CUID and KDD
- // Also added TKSKeyset, KeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
- // Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
- String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
- log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
- ILogger.FAILURE, // Outcome
- status, // status
- agentId, // AgentID
- s_isRandom, // isRandom
- selectedToken, // SelectedToken
- keyNickName, // KeyNickName
- keySet, // TKSKeyset
- log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
- "0x" + Integer.toHexString((int)nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
- Boolean.toString(nistSP800_108KdfUseCuidAsKdd), // NistSP800_108KdfUseCuidAsKdd
- errorMsg // Error
- };
- auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE, logParams);
+ // AC: KDF SPEC CHANGE - Log both CUID and KDD
+ // Also added TKSKeyset, KeyInfo_KeyVersion, NistSP800_108KdfOnKeyVersion, NistSP800_108KdfUseCuidAsKdd
+ // Finally, log CUID and KDD in ASCII-HEX format, as long as special-decoded version is available.
+ String[] logParams = { log_string_from_specialDecoded_byte_array(xCUID), // CUID_decoded
+ log_string_from_specialDecoded_byte_array(xKDD), // KDD_decoded
+ ILogger.FAILURE, // Outcome
+ status, // status
+ agentId, // AgentID
+ s_isRandom, // isRandom
+ selectedToken, // SelectedToken
+ keyNickName, // KeyNickName
+ keySet, // TKSKeyset
+ log_string_from_keyInfo(xkeyInfo), // KeyInfo_KeyVersion
+ "0x" + Integer.toHexString(nistSP800_108KdfOnKeyVersion & 0x000000FF), // NistSP800_108KdfOnKeyVersion
+ Boolean.toString(nistSP800_108KdfUseCuidAsKdd), // NistSP800_108KdfUseCuidAsKdd
+ errorMsg // Error
+ };
+ auditMessage = CMS.getLogMessage(LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE, logParams);
}
audit(auditMessage);
@@ -1687,9 +2253,9 @@ public class TokenServlet extends CMSServlet {
CMS.debug("TokenServlet::processComputeRandomData data size requested: " + dataSize);
String auditMessage = CMS.getLogMessage(
- LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST,
- ILogger.SUCCESS,
- agentId);
+ LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST,
+ ILogger.SUCCESS,
+ agentId);
audit(auditMessage);
@@ -1727,9 +2293,9 @@ public class TokenServlet extends CMSServlet {
resp.setContentType("text/html");
String value = "";
- value = IRemoteRequest.RESPONSE_STATUS+"=" + status;
+ value = IRemoteRequest.RESPONSE_STATUS + "=" + status;
if (status.equals("0")) {
- value = value + "&"+IRemoteRequest.TKS_RESPONSE_RandomData+"=" + randomDataOut;
+ value = value + "&" + IRemoteRequest.TKS_RESPONSE_RandomData + "=" + randomDataOut;
}
try {
@@ -1746,17 +2312,17 @@ public class TokenServlet extends CMSServlet {
if (status.equals("0")) {
auditMessage = CMS.getLogMessage(
- LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,
- ILogger.SUCCESS,
- status,
- agentId);
+ LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,
+ ILogger.SUCCESS,
+ status,
+ agentId);
} else {
auditMessage = CMS.getLogMessage(
- LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,
- ILogger.FAILURE,
- status,
- agentId,
- errorMsg);
+ LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,
+ ILogger.FAILURE,
+ status,
+ agentId,
+ errorMsg);
}
audit(auditMessage);
@@ -1771,7 +2337,7 @@ public class TokenServlet extends CMSServlet {
try {
authzToken = authorize(mAclMethod, authToken,
- mAuthzResourceName, "execute");
+ mAuthzResourceName, "execute");
} catch (Exception e) {
}
@@ -1796,6 +2362,10 @@ public class TokenServlet extends CMSServlet {
}
String temp = req.getParameter(IRemoteRequest.TOKEN_CARD_CHALLENGE);
+ String protocol = req.getParameter(IRemoteRequest.CHANNEL_PROTOCOL);
+ String derivationConstant = req.getParameter(IRemoteRequest.DERIVATION_CONSTANT);
+ CMS.debug("Protocol: " + protocol + " temp: " + temp);
+
setDefaultSlotAndKeyName(req);
if (temp != null) {
processComputeSessionKey(req, resp);
@@ -1805,6 +2375,12 @@ public class TokenServlet extends CMSServlet {
processDiversifyKey(req, resp);
} else if (req.getParameter(IRemoteRequest.TOKEN_DATA_NUM_BYTES) != null) {
processComputeRandomData(req, resp);
+ } else if (protocol != null && protocol.contains("2") && (derivationConstant != null)) {
+ //SCP02 compute one session key.
+ processComputeSessionKeySCP02(req, resp);
+ } else {
+ throw new EBaseException("Process: Can't decide upon function to call!");
+
}
}
@@ -1818,4 +2394,54 @@ public class TokenServlet extends CMSServlet {
throws ServletException, IOException {
super.service(req, resp);
}
+
+ private PK11SymKey getSharedSecretKey() throws EBaseException, NotInitializedException {
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String sharedSecretName = null;
+ try {
+
+ sharedSecretName = getSharedSecretName(configStore);
+
+ } catch (EBaseException e) {
+ throw new EBaseException("TokenServlet.getSharedSecetKey: Internal error finding config value: "
+ + e);
+
+ }
+
+ CMS.debug("TokenServlet.getSharedSecretTransportKey: calculated key name: " + sharedSecretName);
+
+ String symmKeys = null;
+ boolean keyPresent = false;
+ try {
+ symmKeys = SessionKey.ListSymmetricKeys("internal");
+ CMS.debug("TokenServlet.getSharedSecretTransportKey: symmKeys List: " + symmKeys);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ CMS.debug(e);
+ }
+
+ for (String keyName : symmKeys.split(",")) {
+ if (sharedSecretName.equals(keyName)) {
+ CMS.debug("TokenServlet.getSharedSecret: shared secret key found!");
+ keyPresent = true;
+ break;
+ }
+
+ }
+
+ if (!keyPresent) {
+ throw new EBaseException("TokenServlet.getSharedSecret: Can't find shared secret!");
+ }
+
+ // We know for now that shared secret is on this token
+ String tokenName = "Internal Key Storage Token";
+ PK11SymKey sharedSecret = SessionKey.GetSymKeyByName(tokenName, sharedSecretName);
+
+ CMS.debug("TokenServlet.getSharedSecret: SymKey returns: " + sharedSecret);
+
+ return sharedSecret;
+
+ }
+
}
diff --git a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
index a383a4b0f..ebaf12636 100644
--- a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
+++ b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java
@@ -34,6 +34,9 @@ public interface IRemoteRequest {
public static final String RESPONSE_STATUS_XML = "Status";
// TKS request params
+ public static final String CHANNEL_PROTOCOL = "protocol";
+ public static final String SEQUENCE_COUNTER = "sequenceCounter";
+ public static final String DERIVATION_CONSTANT = "derivationConstant";
public static final String SERVER_SIDE_KEYGEN = "serversideKeygen";
public static final String TOKEN_CARD_CHALLENGE = "card_challenge";
public static final String TOKEN_HOST_CHALLENGE = "host_challenge";
@@ -43,6 +46,7 @@ public interface IRemoteRequest {
public static final String TOKEN_DATA_NUM_BYTES = "dataNumBytes";
public static final String TOKEN_NEW_KEYINFO = "newKeyInfo";
public static final String TOKEN_DATA = "data";
+ public static final String WRAPPED_DEK_SESSION_KEY = "wrappedDekKey";
// TKS response params
/* computeSessionKey responses */
diff --git a/base/symkey/src/com/netscape/symkey/Buffer.cpp b/base/symkey/src/com/netscape/symkey/Buffer.cpp
index 5c687c5f5..6241534a5 100644
--- a/base/symkey/src/com/netscape/symkey/Buffer.cpp
+++ b/base/symkey/src/com/netscape/symkey/Buffer.cpp
@@ -171,10 +171,10 @@ Buffer::dump() const
unsigned int i;
for( i=0; i < len; ++i ) {
- printf("%02x ", buf[i]);
- if( i % 16 == 15 ) printf("\n");
+ PR_fprintf(PR_STDOUT,"%02x ", buf[i]);
+ if( i % 16 == 15 ) PR_fprintf(PR_STDOUT,"\n");
}
- printf("\n");
+ PR_fprintf(PR_STDOUT,"\n");
}
static const char hextbl[] = {
diff --git a/base/symkey/src/com/netscape/symkey/EncryptData.cpp b/base/symkey/src/com/netscape/symkey/EncryptData.cpp
index 3963b5026..cebc0bb25 100644
--- a/base/symkey/src/com/netscape/symkey/EncryptData.cpp
+++ b/base/symkey/src/com/netscape/symkey/EncryptData.cpp
@@ -219,7 +219,6 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr
if (masterKey != NULL)
{
-
// ---------------------------------
// AC KDF SPEC CHANGE: Determine which KDF to use.
//
@@ -279,11 +278,9 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr
GetDiversificationData(kddValue,kekData,kek);
// AC: Derives the Kek key for the token.
- kekKey = ComputeCardKeyOnToken(masterKey,kekData);
+ kekKey = ComputeCardKeyOnToken(masterKey,kekData,1);
} // endif use original KDF
- // ---------------------------------
-
if (kekKey != NULL)
{
diff --git a/base/symkey/src/com/netscape/symkey/SessionKey.cpp b/base/symkey/src/com/netscape/symkey/SessionKey.cpp
index 2c146730f..610928099 100644
--- a/base/symkey/src/com/netscape/symkey/SessionKey.cpp
+++ b/base/symkey/src/com/netscape/symkey/SessionKey.cpp
@@ -349,6 +349,101 @@ JSS_PK11_getSymKeyPtr(JNIEnv *env, jobject symKeyObject, PK11SymKey **ptr)
SYM_KEY_PROXY_SIG, (void**)ptr);
}
#endif //STEAL_JSS
+
+
+/* ToDo: fully support nistSP800 in next ticket
+*/
+PK11SymKey *DeriveKeySCP02(PK11SymKey *cardKey, const Buffer& sequenceCounter, const Buffer& derivationConstant)
+{
+
+ PK11SymKey *key = NULL;
+ PK11SymKey *master = NULL;
+ unsigned char message[KEYLENGTH] = {0};
+ unsigned char derivationData[DES3_LENGTH] = {0};
+
+ PRBool invalid_mechanism = PR_TRUE;
+ SECStatus s = SECFailure;
+ int len = 0;
+ int i = 0;
+
+ SECItem *secParam = NULL;
+
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ PK11Context *context = NULL;
+ SECItem param = { siBuffer, NULL, 0 };
+
+ unsigned char icv[EIGHT_BYTES] = { 0 };
+
+ if( sequenceCounter == NULL || derivationConstant == NULL ||
+ sequenceCounter.size() != 2 || derivationConstant.size() != 2 ||
+ cardKey == NULL) {
+ PR_fprintf(PR_STDERR,"In DeriveKeySCP02! Error invalid input data!\n");
+ goto done;
+ }
+
+ PR_fprintf(PR_STDOUT,"In DeriveKeySCP02! \n");
+ PR_fprintf(PR_STDOUT,"In DeriveKeySCP02! seqCounter[0] : %d sequenceCounter [1] : %d \n", sequenceCounter[0], sequenceCounter[1]);
+ PR_fprintf(PR_STDOUT,"In DeriveKeySCP02! derivationConstant[0] : %x derivationConstant[1] : %x \n", derivationConstant[0], derivationConstant[1]);
+
+ master = cardKey;
+
+ message[0] = (unsigned char) derivationConstant[0];
+ message[1] = (unsigned char) derivationConstant[1];
+ message[2] = (unsigned char) sequenceCounter[0];
+ message[3] = (unsigned char) sequenceCounter[1];
+
+
+ //ToDo use the new NSS provided derive mechanisms for this operation
+ if(invalid_mechanism == PR_FALSE) {
+ // Use derive mechanisms
+ } else {
+
+ //Use encryption method
+ param.data = (unsigned char *) &icv;
+ param.len = 8;
+ secParam = PK11_ParamFromIV(CKM_DES3_CBC_PAD, &param);
+ context = PK11_CreateContextBySymKey(CKM_DES3_CBC_PAD, CKA_ENCRYPT, master, secParam);
+ if(context == NULL) {
+ goto done;
+ }
+ s = PK11_CipherOp(context,&derivationData[0] , &len, EIGHT_BYTES, &message[0], EIGHT_BYTES);
+
+ if (s != SECSuccess) { goto done; }
+
+ s = PK11_CipherOp(context, &derivationData[EIGHT_BYTES], &len, EIGHT_BYTES, &message[EIGHT_BYTES], EIGHT_BYTES);
+ if (s != SECSuccess) { goto done; }
+
+ for(i = 0;i < EIGHT_BYTES ;i++)
+ {
+ derivationData[i+KEYLENGTH] = derivationData[i];
+ }
+
+ key = CreateUnWrappedSymKeyOnToken( slot, master, &derivationData[0] , DES3_LENGTH, PR_FALSE );
+
+ PR_fprintf(PR_STDOUT,"In DeriveKeySCP02! calculated key: %p \n", key);
+ }
+
+ done:
+
+ memset(derivationData, 0, sizeof derivationData);
+ if ( context != NULL) {
+ PK11_DestroyContext(context, PR_TRUE);
+ context = NULL;
+ }
+
+ if (slot) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+
+ if (secParam) {
+ SECITEM_FreeItem(secParam, PR_TRUE);
+ secParam = NULL;
+ }
+
+ return key;
+}
+
// Function takes wither a symkey OR a keybuffer (for the default keyset case)
// To derive a new key.
PK11SymKey *DeriveKey(PK11SymKey *cardKey, const Buffer& hostChallenge, const Buffer& cardChallenge)
@@ -567,6 +662,369 @@ finish:
}
+//ToDo: Fix this to conform the nistSP800
+//=================================================================================
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
+ * Class: com_netscape_cms_servlet_tks_RASessionKey
+ * Method: ComputeSessionKeySCP02
+ * Signature: ([B[B[B[B)[B
+ */
+ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeSessionKeySCP02
+ (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring, jstring);
+#ifdef __cplusplus
+}
+#endif
+#define KEYLENGTH 16
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeSessionKeySCP02(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray keyInfo, jbyteArray CUID, jbyteArray devKeyArray, jbyteArray sequenceCounter, jbyteArray derivationConstant, jstring useSoftToken_s, jstring keySet, jstring sharedSecretKeyName)
+{
+ /* hardcode permanent dev key */
+ jbyte *dev_key = NULL;
+ if (devKeyArray != NULL) {
+ dev_key = (jbyte*)(env)->GetByteArrayElements(devKeyArray, NULL);
+ } else {
+ return NULL;
+ }
+
+ SECItem wrappedKeyItem = { siBuffer, NULL , 0};
+ SECItem noParams = { siBuffer, NULL, 0 };
+ SECStatus wrapStatus = SECFailure;
+
+
+ char *keyNameChars=NULL;
+ char *tokenNameChars=NULL;
+ PK11SlotInfo *slot = NULL;
+ PK11SlotInfo *internal = PK11_GetInternalKeySlot();
+
+ PK11SymKey *symkey = NULL;
+ PK11SymKey *transportKey = NULL;
+ PK11SymKey *masterKey = NULL;
+
+ PK11SymKey *devSymKey = NULL;
+ PK11SymKey *symkey16 = NULL;
+ PK11SymKey *devKey = NULL;
+
+
+ BYTE devData[KEYLENGTH];
+ char keyname[KEYNAMELENGTH];
+
+ const char *devKeyName = NULL;
+
+ const char *macName = "mac";
+ const char *encName = "enc";
+ const char *kekName = "kek";
+
+ keyType kType = mac;
+
+ /* Derive vars */
+
+ CK_ULONG bitPosition = 0;
+ SECItem paramsItem = { siBuffer, NULL, 0 };
+
+ /* Java object return vars */
+
+ jbyteArray handleBA=NULL;
+ jbyte *handleBytes=NULL;
+
+ jbyte * cuidValue = NULL;
+
+ jbyte *sc = NULL;
+ int sc_len = 0;
+
+ int dc_len = 0;
+ jbyte *dc = NULL;
+
+ jbyte * keyVersion = NULL;
+ int keyVersion_len = 0;
+
+ Buffer devBuff( ( BYTE *) dev_key , KEYLENGTH );
+
+ char *keySetStringChars = NULL;
+ if( keySet != NULL ) {
+ keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL);
+ }
+
+ char *keySetString = keySetStringChars;
+
+ if ( keySetString == NULL ) {
+ keySetString = (char *) DEFKEYSET_NAME;
+ }
+
+ char *sharedSecretKeyNameChars = NULL;
+
+ if( sharedSecretKeyName != NULL ) {
+ sharedSecretKeyNameChars = (char *) (env)->GetStringUTFChars( sharedSecretKeyName, NULL);
+ }
+
+ char *sharedSecretKeyNameString = sharedSecretKeyNameChars;
+
+ if ( sharedSecretKeyNameString == NULL ) {
+ sharedSecretKeyNameString = (char *) TRANSPORT_KEY_NAME;
+ }
+
+ GetSharedSecretKeyName(sharedSecretKeyNameString);
+
+ if( sequenceCounter != NULL) {
+ sc = (jbyte*)(env)->GetByteArrayElements( sequenceCounter, NULL);
+ sc_len = (env)->GetArrayLength(sequenceCounter);
+ }
+
+ if( sc == NULL || sc_len != 2) {
+ goto done;
+ }
+
+ if( derivationConstant != NULL) {
+ dc = (jbyte*)(env)->GetByteArrayElements( derivationConstant, NULL);
+ dc_len = (env)->GetArrayLength( derivationConstant);
+ }
+
+ if( dc == NULL || dc_len != 2) {
+ goto done;
+ }
+
+ if( keyInfo != NULL) {
+ keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL);
+
+ if( keyVersion) {
+ keyVersion_len = (env)->GetArrayLength(keyInfo);
+ }
+ }
+
+ if( !keyVersion || (keyVersion_len < 2) ){
+ goto done;
+ }
+
+ if ( CUID != NULL ) {
+ cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL);
+ }
+
+ if( cuidValue == NULL) {
+ goto done;
+ }
+
+ if(tokenName)
+ {
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ slot = ReturnSlot(tokenNameChars);
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ }
+
+ if(keyName)
+ {
+ keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL);
+ strncpy(keyname,keyNameChars,KEYNAMELENGTH);
+ (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars);
+ }else
+ GetKeyName(keyVersion,keyname);
+
+ //Get key type from derivation constant
+ switch((unsigned char) dc[1]) {
+ case 0x1 :
+ kType = mac;
+ devKeyName = macName;
+ break;
+
+ case 0x82:
+ kType = enc;
+ devKeyName = encName;
+ break;
+
+ case 0x81:
+ kType = kek;
+ devKeyName = kekName;
+ break;
+
+ default:
+ kType = mac;
+ devKeyName = macName;
+ break;
+ }
+
+ GetDiversificationData(cuidValue,devData,kType);
+
+ PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKeySCP02! keyName %s keyVersion[0] %d keyVersion[1] %d \n",keyname,(int) keyVersion[0],(int) keyVersion[1]);
+
+ if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 ) ||
+ (keyVersion[0] == -1 && keyVersion[1] == 0x1))
+
+ {
+ /* default manufacturers key */
+
+ devSymKey = ReturnDeveloperSymKey(slot, (char *) devKeyName , keySetString, devBuff);
+
+ if( devSymKey == NULL ) {
+ goto done;
+ }
+
+ PR_fprintf(PR_STDOUT,"SessionKey.ComputeSessionKeySCP02! sc[0] : %d sc[1] : %d \n", sc[0], sc[1]);
+ symkey = DeriveKeySCP02( //Util::DeriveKey(
+ devSymKey, Buffer((BYTE*)sc, sc_len), Buffer((BYTE*)dc, dc_len));
+
+ if(symkey == NULL)
+ {
+ goto done;
+ }
+
+ //In the enc key case create the auth as well, we may need it later.
+
+ if(kType == enc) {
+
+ PK11SymKey *authKey = NULL;
+
+ authKey = ReturnDeveloperSymKey(slot, (char *) "auth" , keySetString, devBuff);
+
+ if(authKey == NULL)
+ {
+ goto done;
+ }
+
+ PK11_FreeSymKey(authKey);
+ authKey = NULL;
+
+ }
+
+ }else
+ {
+ PR_fprintf(PR_STDOUT,"SessionKey.ComputeSessionKeySCP02! Attempting with master key. \n");
+ masterKey = ReturnSymKey( slot,keyname);
+ if(masterKey == NULL)
+ {
+ goto done;
+ }
+
+ devKey =ComputeCardKeyOnToken(masterKey,devData,2);
+ if(devKey == NULL)
+ {
+ goto done;
+ }
+
+ symkey = DeriveKeySCP02(devKey, Buffer((BYTE*)sc, sc_len), Buffer((BYTE*)dc, dc_len));
+
+ if(symkey == NULL)
+ {
+ goto done;
+ }
+ }
+ //Now wrap the key for the trip back to TPS with shared secret transport key
+
+ symkey16 = NULL;
+ transportKey = ReturnSymKey( internal, GetSharedSecretKeyName(NULL));
+ if ( transportKey == NULL ) {
+ PR_fprintf(PR_STDERR, "Can't find shared secret transport key! \n");
+ goto done;
+ }
+
+ handleBA = (env)->NewByteArray( KEYLENGTH);
+ handleBytes = (env)->GetByteArrayElements(handleBA, NULL);
+
+ paramsItem.data = (CK_BYTE *) &bitPosition;
+ paramsItem.len = sizeof bitPosition;
+
+ symkey16 = PK11_Derive(symkey, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT,
+ CKA_DERIVE, 16);
+ if ( !symkey16 ) {
+ PR_fprintf(PR_STDERR,"Can't derive 16 byte key from 24 byte symkey! \n");
+ goto done;
+ }
+
+ wrappedKeyItem.data = (unsigned char *) handleBytes;
+ wrappedKeyItem.len = KEYLENGTH;
+ wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, transportKey, symkey16, &wrappedKeyItem);
+
+ if(wrapStatus == SECFailure )
+ {
+ PR_fprintf(PR_STDERR, "Can't wrap session key! Error: %d \n", PR_GetError());
+ }
+
+done:
+
+ if( slot) {
+ PK11_FreeSlot(slot);
+ slot = NULL;
+ }
+
+ if( internal ) {
+ PK11_FreeSlot(internal);
+ internal = NULL;
+ }
+
+ if ( symkey ) {
+ PK11_FreeSymKey( symkey);
+ symkey = NULL;
+ }
+
+ if ( transportKey ) {
+ PK11_FreeSymKey( transportKey );
+ transportKey = NULL;
+ }
+
+ if ( symkey16 ) {
+ PK11_FreeSymKey( symkey16 );
+ symkey16 = NULL;
+ }
+
+ if( masterKey ) {
+ PK11_FreeSymKey( masterKey);
+ masterKey = NULL;
+ }
+
+ if( devKey ) {
+ PK11_FreeSymKey( devKey);
+ devKey = NULL;
+ }
+
+ if( devSymKey ) {
+ PK11_FreeSymKey( devSymKey );
+ devSymKey = NULL;
+ }
+
+ if( keySetStringChars ) {
+ (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars);
+ keySetStringChars = NULL;
+ }
+
+ if( sharedSecretKeyNameChars ) {
+ (env)->ReleaseStringUTFChars(sharedSecretKeyName, (const char *)sharedSecretKeyNameChars);
+ sharedSecretKeyNameChars = NULL;
+ }
+
+ if ( handleBytes != NULL) {
+ (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0);
+ }
+
+ if ( sc != NULL) {
+ (env)->ReleaseByteArrayElements(sequenceCounter, sc, JNI_ABORT);
+ }
+
+ if ( dc != NULL) {
+ (env)->ReleaseByteArrayElements(derivationConstant, dc, JNI_ABORT);
+ }
+
+ if( keyVersion != NULL) {
+ (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT);
+ }
+
+ if ( cuidValue != NULL) {
+ (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT);
+ }
+
+ if( dev_key != NULL) {
+ (env)->ReleaseByteArrayElements(devKeyArray, dev_key, JNI_ABORT);
+ }
+
+ if (wrapStatus != SECFailure ){
+ return handleBA;
+ }else{
+ return NULL;
+ }
+
+}
+
+
+
//=================================================================================
#ifdef __cplusplus
extern "C"
@@ -595,7 +1053,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
return NULL;
}
- char input[KEYLENGTH];
+ unsigned char input[KEYLENGTH] = {0};
int i = 0;
SECItem wrappedKeyItem = { siBuffer, NULL , 0};
@@ -762,7 +1220,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
}else
GetKeyName(keyVersion,keyname);
- PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKey! \n");
+ PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKey! keyName %s keyVersion[0] %d keyVersion[1] %d \n",keyname,(int) keyVersion[0],(int) keyVersion[1]);
if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 && strcmp( keyname, "#01#01") == 0) ||
(keyVersion[0] == -1 && strstr(keyname, "#FF")))
@@ -781,13 +1239,13 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
}else
{
+ PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKey! Upgraded keyset mode. \n");
masterKey = ReturnSymKey( slot,keyname);
if(masterKey == NULL)
{
goto done;
}
-
// ---------------------------------
// AC KDF SPEC CHANGE: Determine which KDF to use.
//
@@ -847,17 +1305,12 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
GetDiversificationData(kddValue,macData,mac);//keytype is mac
// AC: Derives the mac key for the token.
- macKey =ComputeCardKeyOnToken(masterKey,macData);
+ macKey =ComputeCardKeyOnToken(masterKey,macData,1);
} // endif use original KDF
// ---------------------------------
- if(macKey == NULL)
- {
- goto done;
- }
-
// AC: This computes the GP session key using the card-specific MAC key we previously derived.
symkey = DeriveKey(macKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len));
@@ -1030,7 +1483,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
return NULL;
}
- char input[KEYLENGTH];
+ unsigned char input[KEYLENGTH] = {0};
int i = 0;
SECItem wrappedKeyItem = { siBuffer, NULL , 0};
@@ -1205,7 +1658,6 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
goto done;
}
-
// ---------------------------------
// AC KDF SPEC CHANGE: Determine which KDF to use.
//
@@ -1265,12 +1717,11 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
GetDiversificationData(kddValue,encData,enc);
// AC: Derives the enc key for the token.
- encKey =ComputeCardKeyOnToken(masterKey,encData);
+ encKey =ComputeCardKeyOnToken(masterKey,encData,1);
} // endif use original KDF
// ---------------------------------
-
if(encKey == NULL) {
goto done;
}
@@ -1446,7 +1897,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute
keySetString = (char *) DEFKEYSET_NAME;
}
- char input[KEYLENGTH];
+ unsigned char input[KEYLENGTH] = {0};
int i;
jobject keyObj = NULL;
@@ -1575,7 +2026,6 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute
goto done;
}
-
// ---------------------------------
// AC KDF SPEC CHANGE: Determine which KDF to use.
//
@@ -1635,12 +2085,11 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute
GetDiversificationData(kddValue,kekData,kek);//keytype is kek
// AC: Derives the mac key for the token.
- kekKey =ComputeCardKeyOnToken(masterKey,kekData);
+ kekKey =ComputeCardKeyOnToken(masterKey,kekData,1);
} // endif use original KDF
// ---------------------------------
-
}
if(kekKey == NULL) {
@@ -2049,7 +2498,6 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
goto done;
}
-
// ---------------------------------
// AC KDF SPEC CHANGE: Determine which KDF to use.
//
@@ -2109,12 +2557,11 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp
GetDiversificationData(kddValue,authData,enc);
// AC: Derives the mac key for the token.
- authKey = ComputeCardKeyOnToken(masterKey,authData);
+ authKey = ComputeCardKeyOnToken(masterKey,authData,1);
} // endif use original KDF
// ---------------------------------
-
if (authKey == NULL)
{
goto done;
@@ -2297,14 +2744,24 @@ Java_com_netscape_symkey_SessionKey_ECBencrypt
goto finish;
}
+ PR_fprintf(PR_STDOUT,"In SessionKey: ECBencrypt! 16 byte key derived.... \n");
+
//Wrap the new 16 bit key with the input symkey.
wrappedKeyItem.data = (unsigned char *) handleBytes;
wrappedKeyItem.len = dlen;
+
+ PR_fprintf(PR_STDOUT,"In SessionKey: ECBencrypt! About to wrap des key with sym key.\n");
wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, symkey, newdeskey, &wrappedKeyItem);
if( wrapStatus == SECSuccess) {
PR_fprintf(PR_STDERR, "ECBencrypt wrapStatus %d wrappedKeySize %d \n", wrapStatus, wrappedKeyItem.len);
+
+ PR_fprintf(PR_STDOUT," ECBencrypt wrapped data: \n");
+ Buffer wrappedDataBuf(wrappedKeyItem.data,wrappedKeyItem.len);
+ wrappedDataBuf.dump();
+
+
} else {
PR_fprintf(PR_STDERR, "ECBecrypt wrap failed! Error %d \n", PR_GetError());
}
@@ -2328,6 +2785,105 @@ extern "C"
{
#endif
/*
+ * Class: com_netscape_cms_servlet_tks_DeriveDESKeyFrom3DesKey
+ * Method: DeriveDESKeyFrom3DesKey
+ * Signature: ([B[B[B[B)[B
+ */
+ JNIEXPORT jobject JNICALL
+ Java_com_netscape_symkey_SessionKey_DeriveDESKeyFrom3DesKey
+ (JNIEnv*, jclass,jstring ,jobject,jlong);
+#ifdef __cplusplus
+}
+#endif
+extern "C" JNIEXPORT jobject JNICALL
+Java_com_netscape_symkey_SessionKey_DeriveDESKeyFrom3DesKey
+(JNIEnv* env, jclass this2, jstring tokenName, jobject des3Key,jlong alg)
+{
+ PK11SymKey * des3 = NULL;
+ PK11SymKey * des = NULL;
+ PK11SymKey * desFinal = NULL;
+ PRStatus r = PR_FAILURE;
+ CK_ULONG bitPosition = 0;
+ SECItem paramsItem = { siBuffer, NULL, 0 };
+ jobject keyObj = NULL;
+ char *tokenNameChars = NULL;
+ PK11SlotInfo *slot = NULL;
+
+ if( des3Key == NULL) {
+ goto loser;
+ }
+
+ if(alg != CKM_DES_CBC && alg != CKM_DES_ECB) {
+ PR_fprintf(PR_STDOUT,"SessionKey.DeriveDESKeyFrom3DesKey invalid alg!.. \n");
+ goto loser;
+ }
+
+ if (tokenName)
+ {
+ tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL);
+ if ( tokenNameChars && !strcmp(tokenNameChars, "internal")) {
+ slot = PK11_GetInternalSlot();
+ } else {
+ slot = ReturnSlot(tokenNameChars);
+ }
+
+ (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars);
+ } else {
+ slot = PK11_GetInternalKeySlot();
+ }
+
+ if(slot == NULL) {
+ goto loser;
+ }
+
+ r = JSS_PK11_getSymKeyPtr(env, des3Key, &des3);
+
+ if (r != PR_SUCCESS) {
+ PR_fprintf(PR_STDOUT,"SessionKey: DeriveDESKeyFrom3DesKey Unable to get input session 3des sym key! \n");
+ goto loser;
+ }
+
+ /* Now create a DES key with the first 8 bytes of the input 3des key */
+
+ // Extract first eight bytes from generated key into another key.
+ bitPosition = 0;
+ paramsItem.data = (CK_BYTE *) &bitPosition;
+ paramsItem.len = sizeof bitPosition;
+
+
+ des = PK11_Derive(des3, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, alg , CKA_DERIVE, 8);
+ if (des == NULL ) {
+ goto loser;
+ }
+
+ //Make sure we move this to the orig token, in case it got moved by NSS
+ //during the derive phase.
+
+ desFinal = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, des);
+
+
+ /* wrap the sesssion in java object. */
+ keyObj = JSS_PK11_wrapSymKey(env, &desFinal, NULL);
+
+loser:
+
+ if ( slot != NULL ) {
+ PK11_FreeSlot( slot);
+ slot = NULL;
+ }
+
+ if ( des != NULL) {
+ PK11_FreeSymKey(des);
+ des = NULL;
+ }
+ return keyObj;
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*
* Class: com_netscape_cms_servlet_tks_UnwrapSessionKeyWithSharedSecret
* Method: UnwrapSessionKeyWithSharedSecret
* Signature: ([B[B[B[B)[B
@@ -2396,6 +2952,7 @@ Java_com_netscape_symkey_SessionKey_UnwrapSessionKeyWithSharedSecret
wrappedItem.data = (unsigned char *) sessionKeyBytes;
wrappedItem.len = sessionKeyLen;
+
sessionKey = PK11_UnwrapSymKey(sharedSecret,
CKM_DES3_ECB,SecParam, &wrappedItem,
CKM_DES3_ECB,
@@ -2437,6 +2994,12 @@ loser:
sessionKey = NULL;
}
+ if (SecParam) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ SecParam = NULL;
+ }
+
+
// Don't free finalKey ptr because wrapping routine takes that out of our hands.
return keyObj;
@@ -2467,7 +3030,6 @@ Java_com_netscape_symkey_SessionKey_GetSymKeyByName
char *tokenNameChars = NULL;
char *keyNameChars = NULL;
PK11SlotInfo *slot = NULL;
- CK_OBJECT_HANDLE keyhandle = 0;
PR_fprintf(PR_STDOUT,"In SessionKey GetSymKeyByName!\n");
diff --git a/base/symkey/src/com/netscape/symkey/SessionKey.java b/base/symkey/src/com/netscape/symkey/SessionKey.java
index d44cc5479..7a32de60c 100644
--- a/base/symkey/src/com/netscape/symkey/SessionKey.java
+++ b/base/symkey/src/com/netscape/symkey/SessionKey.java
@@ -74,6 +74,19 @@ public class SessionKey {
// external calls from RA
public static native byte[] ComputeKeyCheck(PK11SymKey desKey); /* byte data[] ); */
+ //SCP02/GP211 methods
+
+ public static native byte[] ComputeSessionKeySCP02(String tokenName,
+ String keyName,
+ byte[] keyInfo,
+ byte[] CUID,
+ byte[] devKeyArray,
+ byte[] sequenceCounter,
+ byte[] derivationConstant,
+ String useSoftToken,
+ String keySet,
+ String sharedSecretKeyName);
+
public static native byte[] ComputeSessionKey(String tokenName,
String keyName,
byte[] card_challenge,
@@ -173,7 +186,7 @@ public class SessionKey {
byte[] CUIDValue,
byte[] KDD, // AC: KDF SPEC CHANGE
byte[] kekKeyArray,
- String useSoftToken, String keySet);
+ String useSoftToken, String keySet,byte protocol);
// internal calls from config TKS keys tab
public static native String GenMasterKey(String token,
@@ -197,4 +210,6 @@ public class SessionKey {
// with functionality only available now in NSS. This is all to preserve exact functional parity with the current TKS.
public static native PK11SymKey UnwrapSessionKeyWithSharedSecret(String tokenName, PK11SymKey sharedSecret,
byte[] sessionKeyArray);
+
+ public static native PK11SymKey DeriveDESKeyFrom3DesKey(String tokenName, PK11SymKey key3Des,long alg);
}
diff --git a/base/symkey/src/com/netscape/symkey/SymKey.cpp b/base/symkey/src/com/netscape/symkey/SymKey.cpp
index 6e206db54..8890ac3b5 100644
--- a/base/symkey/src/com/netscape/symkey/SymKey.cpp
+++ b/base/symkey/src/com/netscape/symkey/SymKey.cpp
@@ -91,6 +91,8 @@ char masterKeyNickName[KEYNAMELENGTH];
char masterNewKeyNickName[KEYNAMELENGTH];
char sharedSecretSymKeyName[KEYNAMELENGTH] = { 0 };
+static int checkForDeveloperKeySet(char * keyInfo);
+
//=================================================================================
#ifdef __cplusplus
extern "C"
@@ -509,10 +511,10 @@ static secuPWData pwdata = { secuPWData::PW_NONE, 0 };
* Internal token is required when we are doing key diversification
* where raw key material needs to be accessed
*/
-PK11SymKey *ComputeCardKeyOnSoftToken(PK11SymKey *masterKey, unsigned char *data)
+PK11SymKey *ComputeCardKeyOnSoftToken(PK11SymKey *masterKey, unsigned char *data, int protocol)
{
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
- PK11SymKey *key = ComputeCardKey(masterKey, data, slot);
+ PK11SymKey *key = ComputeCardKey(masterKey, data, slot,protocol);
if( slot != NULL) {
PK11_FreeSlot(slot);
slot = NULL;
@@ -521,7 +523,7 @@ PK11SymKey *ComputeCardKeyOnSoftToken(PK11SymKey *masterKey, unsigned char *data
return key;
}
-PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot)
+PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot,int protocol)
{
PK11SymKey *key = NULL;
PK11Context *context = NULL;
@@ -533,9 +535,12 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI
static SECItem noParams = { siBuffer, NULL, 0 };
unsigned char *in = data;
PK11SymKey *tmpkey = NULL;
+ unsigned char icv[EIGHT_BYTES] = { 0 };
unsigned char wrappedkey[DES3_LENGTH];
SECItem wrappeditem = { siBuffer, NULL, 0 };
+ PR_fprintf(PR_STDOUT,"ComputeCardKey: protocol %d.\n",protocol);
+
keyData = (unsigned char*)malloc(keysize);
for (i = 0;i < keysize; i++)
@@ -550,7 +555,7 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI
context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT,
masterKey,
- &noParams);
+ &noParams);
if (context == NULL) {
PR_fprintf(PR_STDERR,"ComputeCardKey: failed to create context.\n");
@@ -591,7 +596,7 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI
PR_fprintf(PR_STDERR,"ComputeCardKey: failed to keygen. \n");
goto done;
}
-
+
context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT,
tmpkey,
&noParams);
@@ -635,10 +640,10 @@ done:
return key;
}
-PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data)
+PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data, int protocol)
{
PK11SlotInfo *slot = PK11_GetSlotFromKey(masterKey);
- PK11SymKey *key = ComputeCardKey(masterKey, data, slot);
+ PK11SymKey *key = ComputeCardKey(masterKey, data, slot,protocol);
if( slot) {
PK11_FreeSlot(slot);
@@ -787,13 +792,14 @@ PRStatus ComputeKeyCheckWithSymKey(PK11SymKey * newKey, Buffer& output)
}
// Create key set data with the help of either a provided old_keyk_ke2_sym key or key buffer (for the Default keyset case).
-PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek_key2, PK11SymKey *old_kek_key2_sym, PK11SymKey *new_auth_key, PK11SymKey *new_mac_key, PK11SymKey *new_kek_key, Buffer &output)
+PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek_key2, PK11SymKey *old_kek_key2_sym, PK11SymKey *new_auth_key, PK11SymKey *new_mac_key, PK11SymKey *new_kek_key,int protocol, Buffer &output)
{
PRStatus rv = PR_FAILURE;
static SECItem noParams = { siBuffer, NULL, 0 };
PK11SymKey *transportKey = NULL;
PK11SymKey *wrappingKey = NULL;
BYTE masterKeyData[DES3_LENGTH];
+ BYTE alg = 0x81;
/* Wrapping vars */
SECItem wrappedKeyItem = { siBuffer, NULL , 0 };
@@ -819,34 +825,69 @@ PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek
Buffer kc_kek_key(3);
Buffer result;
- PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys!\n");
+ //Buffer *dumpBuffer = NULL;
+ //int showDerivedKeys = 0;
+
+ PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys! Protocol: %d \n",protocol);
if ( new_auth_key == NULL || new_mac_key == NULL || new_kek_key == NULL) {
return rv;
}
slot = PK11_GetSlotFromKey(new_auth_key);
- if ( old_kek_key2_sym == NULL ) { /* perm key mode */
- /* Find transport key, shared secret */
- transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL));
- if ( transportKey == NULL ) {
- goto done;
+
+ if(protocol == 1) {
+ if ( old_kek_key2_sym == NULL ) { /* perm key mode */
+ /* Find transport key, shared secret */
+ transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL));
+ if ( transportKey == NULL ) {
+ goto done;
+ }
+
+ /* convert 16-byte to 24-byte triple-DES key */
+ memcpy(masterKeyData, old_kek_key2, KEYLENGTH);
+ memcpy(masterKeyData+16, old_kek_key2, EIGHT_BYTES);
+
+ wrappingKey = CreateUnWrappedSymKeyOnToken( slot, transportKey, masterKeyData, sizeof(masterKeyData), PR_FALSE);
+
+ } else { /* card key mode */
+ PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys: SCP01 card key mode.\n");
+ wrappingKey = old_kek_key2_sym;
}
- /* convert 16-byte to 24-byte triple-DES key */
- memcpy(masterKeyData, old_kek_key2, KEYLENGTH);
- memcpy(masterKeyData+16, old_kek_key2, EIGHT_BYTES);
+ } else if(protocol == 2) {
- wrappingKey = CreateUnWrappedSymKeyOnToken( slot, transportKey, masterKeyData, sizeof(masterKeyData), PR_FALSE);
+ PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys: Using dekKey from SCP02 for wrapping key.\n");
- } else { /* card key mode */
- wrappingKey = old_kek_key2_sym;
- }
+
+ // Use the unwapped SCP02 DEK sym key pointer.
+ wrappingKey = old_kek_key2_sym;
+
+ } else {
+ PR_fprintf(PR_STDERR,"Invalid protocol %d . \n",protocol);
+ goto done;
+
+ }
//Now derive 16 byte versions of the provided symkeys
authKey16 = PK11_Derive(new_auth_key, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT,
CKA_DERIVE, 16);
+ /*
+
+ if(showDerivedKeys == 1) {
+ SECItem *keyData = NULL;
+ PK11_ExtractKeyValue( authKey16 );
+ keyData = PK11_GetKeyData(authKey16);
+ dumpBuffer = new Buffer(keyData->data,keyData->len );
+ PR_fprintf(PR_STDERR,"Debug authKey16 data: \n");
+ dumpBuffer->dump();
+ delete dumpBuffer;
+ dumpBuffer = NULL;
+ }
+
+ */
+
if ( authKey16 == NULL ) {
PR_fprintf(PR_STDERR,"Error deriving authKey16. Error %d \n", PR_GetError());
goto done;
@@ -860,13 +901,28 @@ PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek
goto done;
}
- macKey16 = PK11_Derive(new_mac_key, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT, CKA_DERIVE, 16);
+ macKey16 = PK11_Derive(new_mac_key, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, CKA_ENCRYPT, CKA_DERIVE, 16);
if ( macKey16 == NULL ) {
PR_fprintf(PR_STDERR,"Error deriving macKey16. Error %d \n", PR_GetError());
goto done;
}
+ /*
+
+ if(showDerivedKeys == 1) {
+ SECItem *keyData = NULL;
+ PK11_ExtractKeyValue( macKey16 );
+ keyData = PK11_GetKeyData(macKey16);
+ dumpBuffer = new Buffer(keyData->data,keyData->len );
+ PR_fprintf(PR_STDERR,"Debug macKey16 data: \n");
+ dumpBuffer->dump();
+ delete dumpBuffer;
+ dumpBuffer = NULL;
+ }
+
+ */
+
wrappedKeyItem.data = (unsigned char *) encrypted_mac_key;
wrappedKeyItem.len = encrypted_mac_key.size();
wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, macKey16, &wrappedKeyItem);
@@ -883,6 +939,21 @@ PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek
PR_fprintf(PR_STDERR,"Error deriving kekKey16. Error %d \n", PR_GetError());
}
+ /*
+
+ if(showDerivedKeys == 1) {
+ SECItem *keyData = NULL;
+ PK11_ExtractKeyValue( kekKey16 );
+ keyData = PK11_GetKeyData(kekKey16);
+ dumpBuffer = new Buffer(keyData->data,keyData->len );
+ PR_fprintf(PR_STDERR,"Debug kekKey16 data: \n");
+ dumpBuffer->dump();
+ delete dumpBuffer;
+ dumpBuffer = NULL;
+ }
+
+ */
+
wrappedKeyItem.data = (unsigned char *) encrypted_kek_key;
wrappedKeyItem.len = encrypted_mac_key.size();
wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, kekKey16, &wrappedKeyItem);
@@ -897,18 +968,22 @@ PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek
ComputeKeyCheckWithSymKey(new_kek_key, kc_kek_key);
+ if(protocol == 2) {
+ alg = 0x80;
+ } //default at top is 0x81
+
result = newMasterVer +
- Buffer(1, (BYTE)0x81) +
+ Buffer(1, (BYTE)alg) +
Buffer(1, (BYTE)0x10) +
encrypted_auth_key +
Buffer(1, (BYTE)0x03) +
kc_auth_key +
- Buffer(1, (BYTE)0x81) +
+ Buffer(1, (BYTE)alg) +
Buffer(1, (BYTE)0x10) +
encrypted_mac_key +
Buffer(1, (BYTE)0x03) +
kc_mac_key +
- Buffer(1, (BYTE)0x81) +
+ Buffer(1, (BYTE)alg) +
Buffer(1, (BYTE)0x10) +
encrypted_kek_key +
Buffer(1, (BYTE)0x03) +
@@ -1042,13 +1117,13 @@ void getFullName(char * fullMasterKeyName, char * masterKeyNameChars )
// AC: KDF SPEC CHANGE: function signature change - added jstring oldKeyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, and jbyteArray KDD
// AC: BUGFIX for key versions higher than 09: We need to specialDecode keyInfo parameters before sending them into symkey! This means the parameters must be jbyteArray's
// -- Changed parameter "jstring keyInfo" to "jbyteArray newKeyInfo"
-extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey
-(JNIEnv *, jclass, jstring, jstring, jstring, jstring, jbyteArray, jbyteArray, jbyte, jboolean, jbyteArray, jbyteArray, jbyteArray, jstring, jstring);
+//extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey
+//(JNIEnv *, jclass, jstring, jstring, jstring, jstring, jbyteArray, jbyteArray, jbyte, jboolean, jbyteArray, jbyteArray, jbyteArray, jstring, jstring);
// AC: KDF SPEC CHANGE: function signature change - added jstring oldKeyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, and jbyteArray KDD
// AC: BUGFIX for key versions higher than 09: We need to specialDecode keyInfo parameters before sending them into symkey! This means the parameters must be jbyteArray's
// -- Changed parameter "jstring keyInfo" to "jbyteArray newKeyInfo"
-extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey( JNIEnv * env, jclass this2, jstring tokenName,jstring newTokenName, jstring oldMasterKeyName, jstring newMasterKeyName, jbyteArray oldKeyInfo, jbyteArray newKeyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, jbyteArray CUIDValue, jbyteArray KDD, jbyteArray kekKeyArray, jstring useSoftToken_s, jstring keySet)
+extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey( JNIEnv * env, jclass this2, jstring tokenName,jstring newTokenName, jstring oldMasterKeyName, jstring newMasterKeyName, jbyteArray oldKeyInfo, jbyteArray newKeyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, jbyteArray CUIDValue, jbyteArray KDD, jbyteArray kekKeyArray, jstring useSoftToken_s, jstring keySet,jbyte protocol)
{
PK11SymKey *encKey = NULL;
PK11SymKey *macKey = NULL;
@@ -1069,6 +1144,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive
PK11SymKey* old_mac_sym_key = NULL;
PK11SymKey* old_enc_sym_key = NULL;
PK11SymKey* old_kek_sym_key = NULL;
+ BYTE scp02DekKeyData[DES3_LENGTH];
char *keySetStringChars = NULL;
if ( keySet != NULL ) {
@@ -1106,10 +1182,10 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive
Buffer output;
PK11SlotInfo *newSlot =NULL;
char * newTokenNameChars = NULL;
- char *keyInfoChars = NULL;
+ //char *keyInfoChars = NULL;
// AC: KDF SPEC CHANGE: Need to retrieve old key info from JNI.
- char* oldKeyInfoChars = NULL;
+ //char* oldKeyInfoChars = NULL;
// AC: KDF SPEC CHANGE: Convert new setting value to BYTE (unsigned).
BYTE nistSP800_108KdfOnKeyVersion_byte = static_cast<BYTE>(nistSP800_108KdfOnKeyVersion);
@@ -1125,6 +1201,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive
PK11SymKey * masterKey = NULL;
PK11SymKey * oldMasterKey = NULL;
+ PK11SymKey * transportKey = NULL;
BYTE KDCenc[KEYLENGTH];
BYTE KDCmac[KEYLENGTH];
@@ -1170,7 +1247,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive
goto done;
}
- PR_fprintf(PR_STDOUT,"In SessionKey.DiversifyKey! \n");
+ PR_fprintf(PR_STDOUT,"In SessionKey.DiversifyKey! Protocol: %d \n", protocol);
// AC: KDF SPEC CHANGE:
// Changed from "cuidValue" to "kddValue".
@@ -1274,106 +1351,106 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive
if(newSlot == NULL) {
newSlot = slot;
}
- if(strcmp( oldMasterKeyNameChars, "#01#01") == 0 || strcmp( oldMasterKeyNameChars, "#FF#01") == 0)
- {
- old_kek_key_buff = Buffer((BYTE*)old_kek_key, KEYLENGTH);
+ if(protocol == 1) {
+ if( checkForDeveloperKeySet(oldMasterKeyNameChars ))
+ {
+ old_kek_key_buff = Buffer((BYTE*)old_kek_key, KEYLENGTH);
+ }
+ else
+ {
+ oldMasterKey = ReturnSymKey(slot,fullMasterKeyName);
- // AC: BUGFIX: Remove garbage code.
- // I believe that this code is a no-op as long as the system is working correctly
- // (with the developer keyset data populated in the config file & copied to HSM).
- //
- // Notes:
- // "old_kek_key_buff" appears to only be used if unable to read/load the developer keys into HSM.
- // "old_kek_key_buff" is populated with incorrect data (not appropriate key-length)
- // "output" is overwritten when "CreateKeySetDataWithSymKeys" is called
- //
- // As a result, only when there is some failure (i.e. we execute a "goto" and skip assignment
- // to "output") do we return a keyset data that is 16 bytes in length (the default KEK).
- // This is unlikely to work and even if it does, is a horrible idea as the caller has no way
- // of knowing that we've now essentially inserted a "backdoor" on the token. So, instead of
- // this, we treat #00#00 just like any other "normal" case.
- //
- //}else if(strcmp( oldMasterKeyNameChars, "#00#00") == 0)
- //{
- // /* print Debug message - do not create real keysetdata */
- // old_kek_key_buff = Buffer((BYTE*)"#00#00", 6);
- // output = Buffer((BYTE*)old_kek_key, KEYLENGTH);
+ // AC: BUGFIX: Check for nonexistent master key instead of (potentially) crashing.
+ if (oldMasterKey == NULL){
+ goto done;
+ }
- }
- else
- {
- oldMasterKey = ReturnSymKey(slot,fullMasterKeyName);
+ // ---------------------------------
+ // AC KDF SPEC CHANGE: Determine which KDF to use.
+ //
+ // if old key version meets setting value, use NIST SP800-108 KDF for deriving old keys
+ if (NistSP800_108KDF::useNistSP800_108KDF(nistSP800_108KdfOnKeyVersion_byte, oldKeyVersion) == true){
+
+ PR_fprintf(PR_STDOUT,"DiversifyKey old key NistSP800_108KDF code: Using NIST SP800-108 KDF for old keyset.\n");
+
+ // react to "UseCUIDAsKDD" setting value
+ jbyte* context_jbyte = NULL;
+ jsize context_len_jsize = 0;
+ if (nistSP800_108KdfUseCuidAsKdd == JNI_TRUE){
+ context_jbyte = cuidValue;
+ context_len_jsize = cuidValue_len;
+ }else{
+ context_jbyte = kddValue;
+ context_len_jsize = kddValue_len;
+ }
+ // Converting this way is safe since jbyte is guaranteed to be 8 bits
+ // Of course, this assumes that "char" is 8 bits (not guaranteed, but typical),
+ // but it looks like this assumption is also made in GetDiversificationData
+ const BYTE* const context = reinterpret_cast<const BYTE*>(context_jbyte);
- // AC: BUGFIX: Check for nonexistent master key instead of (potentially) crashing.
- if (oldMasterKey == NULL){
- goto done;
- }
+ // Convert jsize to size_t
+ const size_t context_len = static_cast<size_t>(context_len_jsize);
+ if (context_len > 0x000000FF){ // sanity check (CUID should never be larger than 255 bytes)
+ PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Error; context_len larger than 255 bytes.\n");
+ goto done;
+ }
+ // call NIST SP800-108 KDF routine
+ try{
+ NistSP800_108KDF::ComputeCardKeys(oldMasterKey, context, context_len, &old_enc_sym_key, &old_mac_sym_key, &old_kek_sym_key);
+ }catch(std::runtime_error& ex){
+ PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Exception invoking NistSP800_108KDF::ComputeCardKeys: ");
+ PR_fprintf(PR_STDERR, "%s\n", ex.what() == NULL ? "null" : ex.what());
+ goto done;
+ }catch(...){
+ PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Unknown exception invoking NistSP800_108KDF::ComputeCardKeys.\n");
+ goto done;
+ }
- // ---------------------------------
- // AC KDF SPEC CHANGE: Determine which KDF to use.
- //
- // if old key version meets setting value, use NIST SP800-108 KDF for deriving old keys
- if (NistSP800_108KDF::useNistSP800_108KDF(nistSP800_108KdfOnKeyVersion_byte, oldKeyVersion) == true){
+ // if not a key version where we use the NIST SP800-108 KDF, use the original KDF
+ }else{
- PR_fprintf(PR_STDOUT,"DiversifyKey old key NistSP800_108KDF code: Using NIST SP800-108 KDF for old keyset.\n");
+ PR_fprintf(PR_STDOUT,"DiversifyKey old key NistSP800_108KDF code: Using original KDF for old keyset.\n");
- // react to "UseCUIDAsKDD" setting value
- jbyte* context_jbyte = NULL;
- jsize context_len_jsize = 0;
- if (nistSP800_108KdfUseCuidAsKdd == JNI_TRUE){
- context_jbyte = cuidValue;
- context_len_jsize = cuidValue_len;
- }else{
- context_jbyte = kddValue;
- context_len_jsize = kddValue_len;
- }
+ // AC: Derives the kek key for the token.
+ old_kek_sym_key = ComputeCardKeyOnToken(oldMasterKey,KDCkek,1);
- // Converting this way is safe since jbyte is guaranteed to be 8 bits
- // Of course, this assumes that "char" is 8 bits (not guaranteed, but typical),
- // but it looks like this assumption is also made in GetDiversificationData
- const BYTE* const context = reinterpret_cast<const BYTE*>(context_jbyte);
+ } // endif use original KDF
+ }
- // Convert jsize to size_t
- const size_t context_len = static_cast<size_t>(context_len_jsize);
- if (context_len > 0x000000FF){ // sanity check (CUID should never be larger than 255 bytes)
- PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Error; context_len larger than 255 bytes.\n");
- goto done;
- }
+ } else if(protocol == 2) {
- // call NIST SP800-108 KDF routine
- try{
- NistSP800_108KDF::ComputeCardKeys(oldMasterKey, context, context_len, &old_enc_sym_key, &old_mac_sym_key, &old_kek_sym_key);
- }catch(std::runtime_error& ex){
- PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Exception invoking NistSP800_108KDF::ComputeCardKeys: ");
- PR_fprintf(PR_STDERR, "%s\n", ex.what() == NULL ? "null" : ex.what());
- goto done;
- }catch(...){
- PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Unknown exception invoking NistSP800_108KDF::ComputeCardKeys.\n");
- goto done;
- }
+ Buffer dek_key_buf = Buffer((BYTE*)old_kek_key, 16);
- // if not a key version where we use the NIST SP800-108 KDF, use the original KDF
- }else{
+ PR_fprintf(PR_STDOUT,"DiversifyKey: protocol is 2 import wrapped dek key. \n");
+ dek_key_buf.dump();
+ transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL));
- PR_fprintf(PR_STDOUT,"DiversifyKey old key NistSP800_108KDF code: Using original KDF for old keyset.\n");
+ if(transportKey == NULL)
+ goto done;
- // AC: Derives the kek key for the token.
- old_kek_sym_key = ComputeCardKeyOnToken(oldMasterKey,KDCkek);
+ /* convert 16-byte to 24-byte triple-DES key */
+ memcpy(scp02DekKeyData, old_kek_key, 16);
- } // endif use original KDF
- // ---------------------------------
+ old_kek_sym_key = UnwrapWrappedSymKeyOnToken( slot, transportKey,DES2_LENGTH, scp02DekKeyData, PR_FALSE);
+ if(old_kek_sym_key == NULL) {
+ PR_fprintf(PR_STDERR,"DiversifyKey: Can't unwrap dek key for protocol 2! \n");
+ goto done;
+ }
+ } else {
+ PR_fprintf(PR_STDERR,"DiversifyKey: invalid protocol! \n");
+ goto done;
+ }
// AC KDF SPEC CHANGE: Moved this code down so we don't skip it during "goto done".
//if (oldMasterKey) {
// PK11_FreeSymKey( oldMasterKey );
// oldMasterKey = NULL;
//}
- }
// AC KDF SPEC CHANGE: Moved this code down so we don't skip it during "goto done".
//if(oldMasterKeyNameChars) {
@@ -1406,7 +1483,6 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive
} else {
PR_fprintf(PR_STDOUT,"DiversifyKey: Compute card key on token case ! \n");
-
// ---------------------------------
// AC KDF SPEC CHANGE: Determine which KDF to use.
//
@@ -1457,14 +1533,13 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive
// AC: Derives the kek key for the token.
/* compute card key */
- encKey = ComputeCardKeyOnSoftToken(masterKey, KDCenc);
- macKey = ComputeCardKeyOnSoftToken(masterKey, KDCmac);
- kekKey = ComputeCardKeyOnSoftToken(masterKey, KDCkek);
+ encKey = ComputeCardKeyOnSoftToken(masterKey, KDCenc,protocol);
+ macKey = ComputeCardKeyOnSoftToken(masterKey, KDCmac,protocol);
+ kekKey = ComputeCardKeyOnSoftToken(masterKey, KDCkek,protocol);
} // endif use original KDF
// ---------------------------------
-
/* Fixes Bugscape Bug #55855: TKS crashes if specified key
* is not present -- for each portion of the key, check if
* the PK11SymKey is NULL before sending it to PK11_GetKeyData()!
@@ -1487,19 +1562,23 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive
}
if (old_kek_sym_key != NULL) {
+
CreateKeySetDataWithSymKeys(newMasterKeyBuffer, Buffer(),
old_kek_sym_key,
encKey,
macKey,
kekKey,
+ protocol,
output); }
else {
old_kek_sym_key = ReturnDeveloperSymKey(slot, (char *) "kek", keySetString, old_kek_key_buff);
+
CreateKeySetDataWithSymKeys(newMasterKeyBuffer, Buffer(),
old_kek_sym_key,
encKey,
macKey,
kekKey,
+ protocol,
output);
}
@@ -1638,13 +1717,14 @@ PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWra
PK11Context * EncContext = NULL;
SECItem unWrappedKeyItem = { siBuffer, NULL, 0};
PK11SymKey *unwrapper = NULL;
+ PK11SymKey *unwrapped24Key = NULL;
PR_fprintf( PR_STDOUT,
"Creating UnWrappedSymKey on token. \n");
if ( (slot == NULL) || (unWrappingKey == NULL) ||
(keyToBeUnWrapped == NULL) ||
- (sizeOfKeyToBeUnWrapped != DES3_LENGTH)
+ ((sizeOfKeyToBeUnWrapped != DES3_LENGTH) && (sizeOfKeyToBeUnWrapped != DES2_LENGTH))
) {
return NULL;
}
@@ -1675,7 +1755,11 @@ PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWra
goto done;
}
- if ( final_len != DES3_LENGTH ) {
+ PR_fprintf( PR_STDOUT,
+ "Creating UnWrappedSymKey on token. final len %d \n", final_len);
+
+
+ if ( final_len != DES3_LENGTH && final_len != DES2_LENGTH) {
goto done;
}
@@ -1689,6 +1773,22 @@ PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWra
CKM_DES3_ECB,
CKA_UNWRAP,
sizeOfKeyToBeUnWrapped, 0, isPerm );
+
+ if(sizeOfKeyToBeUnWrapped == DES2_LENGTH) {
+ unwrapped24Key = CreateDesKey24Byte(slot, unWrappedSymKey);
+ if(unwrapped24Key == NULL) {
+ PR_fprintf( PR_STDERR,
+ "UnwrapWrappedSymKeyOnToken . Unable to unwrap 24 byte key onto token!. \n");
+
+ }
+ }
+
+
+ if(unwrapped24Key != NULL) {
+ PK11_FreeSymKey( unWrappedSymKey);
+ unWrappedSymKey = unwrapped24Key;
+ }
+
done:
@@ -1710,7 +1810,7 @@ done:
if( unwrapKeySlot != NULL) {
PK11_FreeSlot( unwrapKeySlot);
unwrapKeySlot = NULL;
- }
+ }
PR_fprintf( PR_STDOUT,
"UnWrappedSymKey on token result: %p \n",unWrappedSymKey);
@@ -1735,6 +1835,8 @@ PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySe
snprintf(devKeyName,maxKeyNameSize,"%s-%sKey", keySet, keyType);
+ PR_fprintf(PR_STDOUT,"ReturnDeveloperSymKey! trying to find key %s. \n",devKeyName);
+
devSymKey = ReturnSymKey( slot, devKeyName );
// Try to create the key once and leave it there.
@@ -1767,7 +1869,10 @@ PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySe
PR_fprintf(PR_STDERR, "Can't set the nickname of just written devKey! \n");
}
}
+ } else {
+ PR_fprintf(PR_STDOUT,"ReturnDeveloperSymKey! input key size %d. \n",inputKey.size());
}
+
}
done:
@@ -1806,3 +1911,114 @@ JNICALL Java_com_netscape_symkey_SessionKey_SetDefaultPrefix(JNIEnv * env, jclas
return;
}
+
+int checkForDeveloperKeySet(char * keyInfo)
+{
+
+ if(keyInfo == NULL)
+ return 1;
+
+ //SCP01 or SCP02
+ if(strcmp( keyInfo, "#01#01") == 0 || strcmp( keyInfo, "#FF#01") == 0)
+ return 1;
+
+ //SCP02
+ if(strcmp( keyInfo, "#01#02") == 0 || strcmp( keyInfo, "#FF#02") == 0)
+ return 1;
+
+ return 0;
+}
+
+// Unwrap previously wrapped sym key. Assume the final output is 24 bytes DES3, this function assumes the key is wrapped already.
+
+PK11SymKey *UnwrapWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey,int sizeOfWrappedKey, unsigned char * wrappedKeyData, PRBool isPerm) {
+
+ PK11SymKey * unWrappedSymKey = NULL;
+ int final_len = DES3_LENGTH;
+ SECItem unWrappedKeyItem = { siBuffer, NULL, 0};
+ PK11SymKey *unwrapper = NULL;
+ PK11SymKey *unwrapped24Key = NULL;
+
+
+ PR_fprintf( PR_STDOUT,
+ "Creating UnWrappedSymKey on token. UnwrapWrappedSymKeyOnToken. \n");
+
+ if ( (slot == NULL) || (unWrappingKey == NULL) || (wrappedKeyData == NULL))
+ {
+ return NULL;
+ }
+
+ if(sizeOfWrappedKey == DES2_LENGTH) {
+ PR_fprintf( PR_STDOUT,
+ "UnwrapWrappedSymKeyOnToken . Given 16 byte encrypted key will have to derive a 24 byte on later. \n");
+ }
+
+ PK11SlotInfo *unwrapKeySlot = PK11_GetSlotFromKey( unWrappingKey );
+
+ if ( unwrapKeySlot != slot ) {
+ unwrapper = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, unWrappingKey);
+ }
+
+ SECItem *SecParam = PK11_ParamFromIV(CKM_DES3_ECB, NULL);
+ if ( SecParam == NULL) {
+ goto done;
+ }
+
+ if ( final_len != DES3_LENGTH ) {
+ goto done;
+ }
+
+ unWrappedKeyItem.data = wrappedKeyData;
+ unWrappedKeyItem.len = sizeOfWrappedKey;
+
+ /* Now try to unwrap our key into the token */
+ unWrappedSymKey = PK11_UnwrapSymKeyWithFlagsPerm(unwrapper ? unwrapper : unWrappingKey,
+ CKM_DES3_ECB,SecParam, &unWrappedKeyItem,
+ CKM_DES3_ECB,
+ CKA_UNWRAP,
+ sizeOfWrappedKey, 0, isPerm );
+
+ if(unWrappedSymKey == NULL) {
+ PR_fprintf( PR_STDERR,
+ "UnwrapWrappedSymKeyOnToken . Unable to unwrap key onto token!. \n");
+ goto done;
+ }
+
+ if(sizeOfWrappedKey == DES2_LENGTH) {
+ unwrapped24Key = CreateDesKey24Byte(slot, unWrappedSymKey);
+ if(unwrapped24Key == NULL) {
+ PR_fprintf( PR_STDERR,
+ "UnwrapWrappedSymKeyOnToken . Unable to unwrap 24 byte key onto token!. \n");
+
+ }
+ }
+
+done:
+
+ if( SecParam != NULL ) {
+ SECITEM_FreeItem(SecParam, PR_TRUE);
+ SecParam = NULL;
+ }
+
+ if( unwrapper != NULL ) {
+ PK11_FreeSymKey( unwrapper );
+ unwrapper = NULL;
+ }
+
+ if( unwrapKeySlot != NULL) {
+ PK11_FreeSlot( unwrapKeySlot);
+ unwrapKeySlot = NULL;
+ }
+
+ if( unwrapped24Key != NULL) {
+ PK11_FreeSymKey( unWrappedSymKey);
+ unWrappedSymKey = unwrapped24Key;
+ }
+
+ PR_fprintf( PR_STDOUT,
+ "UnwrapWrappedSymKey on token result: %p \n",unWrappedSymKey);
+
+
+ return unWrappedSymKey;
+
+}
diff --git a/base/symkey/src/com/netscape/symkey/SymKey.h b/base/symkey/src/com/netscape/symkey/SymKey.h
index efe187075..4f1bbe7ef 100644
--- a/base/symkey/src/com/netscape/symkey/SymKey.h
+++ b/base/symkey/src/com/netscape/symkey/SymKey.h
@@ -41,13 +41,14 @@ extern char sharedSecretSymKeyName[KEYNAMELENGTH];
void GetDiversificationData(jbyte *cuidValue,BYTE *KDC,keyType keytype);
PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname);
void GetKeyName(jbyte *keyVersion,char *keyname);
-PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data);
+PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data,int protocol);
PRStatus EncryptData(const Buffer &kek_key, PK11SymKey *card_key, Buffer &input, Buffer &output);
PK11SlotInfo *ReturnSlot(char *tokenNameChars);
-PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot);
+PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot,int protocol);
PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey, BYTE *keyToBeUnWrapped, int sizeOfKeyToBeUnWrapped, PRBool isPerm);
PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySet, Buffer &inputKey);
PK11SymKey *CreateDesKey24Byte(PK11SlotInfo *slot, PK11SymKey *origKey);
+PK11SymKey *UnwrapWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey,int sizeOfWrappedKey, unsigned char * wrappedKeyData, PRBool isPerm);
char *GetSharedSecretKeyName(char *newKeyName);
diff --git a/base/tks/shared/conf/CS.cfg.in b/base/tks/shared/conf/CS.cfg.in
index 2f7606f44..feca14b5c 100644
--- a/base/tks/shared/conf/CS.cfg.in
+++ b/base/tks/shared/conf/CS.cfg.in
@@ -302,7 +302,7 @@ selftests.plugin.TKSKnownSessionKey.TksSubId=tks
selftests.plugin.TKSKnownSessionKey.cardChallenge=#bd#6d#19#85#6e#54#0f#cd
selftests.plugin.TKSKnownSessionKey.hostChallenge=#77#57#62#e4#5e#23#66#7d
selftests.plugin.TKSKnownSessionKey.keyName=#01#01
-selftests.plugin.TKSKnownSessionKey.nistSP800-108KdfOnKeyVersion=FF
+selftests.plugin.TKSKnownSessionKey.nistSP800-108KdfOnKeyVersion=99
selftests.plugin.TKSKnownSessionKey.nistSP800-108KdfUseCuidAsKdd=false
selftests.plugin.TKSKnownSessionKey.macKey=#40#41#42#43#44#45#46#47#48#49#4a#4b#4c#4d#4e#4f
selftests.plugin.TKSKnownSessionKey.sessionKey=#d1#be#b8#26#dc#56#20#25#8c#93#e7#de#f0#ab#4f#5b
diff --git a/base/tps/shared/conf/CS.cfg.in b/base/tps/shared/conf/CS.cfg.in
index e363ba3df..0ddb244d1 100644
--- a/base/tps/shared/conf/CS.cfg.in
+++ b/base/tps/shared/conf/CS.cfg.in
@@ -110,7 +110,7 @@ channel._013=# * channel.instanceSize=18000
channel._014=# * channel.appletMemorySize=5000
channel._015=#########################################
channel.encryption=true
-channel.blocksize=248
+channel.blocksize=242
channel.defKeyVersion=0
channel.defKeyIndex=0
cms.product.version=@APPLICATION_VERSION@
diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java b/base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java
new file mode 100644
index 000000000..e5f38e108
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/channel/PlatformAndSecChannelProtoInfo.java
@@ -0,0 +1,108 @@
+package org.dogtagpki.server.tps.channel;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+public class PlatformAndSecChannelProtoInfo {
+
+ private String platform ;
+ private byte protocol;
+ private TPSBuffer oidCardRecognitionData;
+ private TPSBuffer oidCardManagementTypeAndVer;
+ private TPSBuffer oidCardIdentificationScheme;
+ private TPSBuffer keysetInfoData;
+
+ private byte implementation;
+ public PlatformAndSecChannelProtoInfo(String platform, byte protocol, byte implementation) {
+ // TODO Auto-generated constructor stub
+ this.platform = platform;
+ this.protocol = protocol;
+ this.implementation = implementation;
+ }
+ public PlatformAndSecChannelProtoInfo() {
+ setPlatform(SecureChannel.GP201);
+ setProtocol(SecureChannel.SECURE_PROTO_01);
+ setImplementation((byte)0);
+ }
+ public String getPlatform() {
+ return platform;
+ }
+ public void setPlatform(String platform) {
+ this.platform = platform;
+ }
+ public byte getProtocol() {
+ return protocol;
+ }
+
+ public boolean isGP201() {
+ if(SecureChannel.GP201.equals(platform)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean isGP211() {
+ if(SecureChannel.GP211.equals(platform)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isSCP01() {
+ if(protocol == SecureChannel.SECURE_PROTO_01) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isSCP02() {
+ if(protocol == SecureChannel.SECURE_PROTO_02) {
+ return true;
+ }
+ return false;
+ }
+ public void setProtocol(byte protocol) {
+ this.protocol = protocol;
+ }
+ public void setOidCardRecognitionData(TPSBuffer oidCardRecognitionData) {
+ // TODO Auto-generated method stub
+ this.oidCardRecognitionData = oidCardRecognitionData;
+
+ }
+
+ public TPSBuffer getOidCardRecognitionData() {
+ return oidCardRecognitionData;
+ }
+ public void setOidCardManagementTypeAndVer(TPSBuffer oidCardManagementTypeAndVer) {
+ // TODO Auto-generated method stub
+ this.oidCardManagementTypeAndVer = oidCardManagementTypeAndVer;
+ }
+
+ public TPSBuffer getOidCardManagementTypeAndVer() {
+ return oidCardManagementTypeAndVer;
+ }
+ public void setOidCardIdentificationScheme(TPSBuffer oidCardIdentificationScheme) {
+ this.oidCardIdentificationScheme = oidCardIdentificationScheme;
+
+ }
+
+ public TPSBuffer getOidCardIdentificationScheme() {
+ return oidCardIdentificationScheme;
+ }
+
+ public void setImplementation(byte implementation) {
+ this.implementation = implementation;
+ }
+
+ public byte getImplementation() {
+ return implementation;
+ }
+ public TPSBuffer getKeysetInfoData() {
+ return keysetInfoData;
+ }
+ public void setKeysetInfoData(TPSBuffer keysetInfoData) {
+ this.keysetInfoData = keysetInfoData;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
index 7c3a01ba7..95cf26c2f 100644
--- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
+++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
@@ -19,21 +19,27 @@ package org.dogtagpki.server.tps.channel;
import java.io.IOException;
+import org.dogtagpki.server.tps.engine.TPSEngine;
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.DeleteFileGP211APDU;
import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU;
import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
+import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDUGP211;
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.InstallAppletAPDUGP211;
import org.dogtagpki.tps.apdu.InstallLoadAPDU;
+import org.dogtagpki.tps.apdu.InstallLoadGP211APDU;
import org.dogtagpki.tps.apdu.LifecycleAPDU;
import org.dogtagpki.tps.apdu.LoadFileAPDU;
+import org.dogtagpki.tps.apdu.LoadFileAPDUGP211;
import org.dogtagpki.tps.apdu.PutKeyAPDU;
import org.dogtagpki.tps.apdu.ReadObjectAPDU;
import org.dogtagpki.tps.apdu.SetIssuerInfoAPDU;
@@ -55,10 +61,23 @@ public class SecureChannel {
// Have not written all code to use all of these as of yet.
- private TPSProcessor processor;
+ public TPSProcessor processor;
private PK11SymKey sessionKey;
+
+ //SCP01 or SCP02 key
private PK11SymKey encSessionKey;
+
+ //SCP02 session keys
+ private PK11SymKey cmacSessionKey;
+ //Used for security level we do not yet suport.
+ private PK11SymKey rmacSessionKey;
+ private PK11SymKey dekSessionKey;
+
+ private TPSBuffer dekSessionKeyWrapped;
+
private TPSBuffer drmDesKey;
+
+ //SCP01 kek key
private TPSBuffer kekDesKey;
private TPSBuffer keyCheck;
private TPSBuffer keyDiversificationData;
@@ -68,7 +87,10 @@ public class SecureChannel {
private TPSBuffer hostCryptogram;
private TPSBuffer icv;
private TPSBuffer keyInfoData;
- private SecurityLevel secLevel;
+ private TPSBuffer sequenceCounter;
+ private ExternalAuthenticateAPDU.SecurityLevel secLevel;
+ private PlatformAndSecChannelProtoInfo platProtInfo;
+ private ExternalAuthenticateAPDUGP211.SecurityLevel secLevelGP211;
public enum TokenKeyType {
KEY_TYPE_ENCRYPTION,
@@ -76,9 +98,29 @@ public class SecureChannel {
KEY_TYPE_SIGNING_AND_ENCRYPTION
}
+ public final static byte GP211_SCP02_IMPL_15 = 0x15;
+ public final static String GP201 = "2.0.1";
+ public final static String GP211 = "2.1.1";
+
+ public final static byte SECURE_PROTO_01 = 1;
+ public final static byte SECURE_PROTO_02 = 2;
+ public final static byte SECURE_PROTO_03 = 3;
+
+ public final static byte[] GP211_GET_DATA_CARD_DATA = { 0x00, (byte) 0x66 };
+ public final static byte[] GP211_GET_DATA_KEY_INFO = { 0x00, (byte) 0xe0 };
+ public final static byte[] GP201_GET_DATA_CPLC_WHOLE_CPLC = { (byte) 0x9F, (byte) 0x7F };
+ public final static byte[] GP211_GET_DATA_CPLC_WHOLE_CPLC = { (byte) 0x9F, (byte) 0x7F };
+
+ public final static byte[] C_MACDerivationConstant = { 0x01, 0x01 };
+ public final static byte[] ENCDerivationConstant = { (byte) 0x01, (byte) 0x82 };
+ public final static byte[] DEKDerivationConstant = { 0x01, (byte) 0x81 };
+ public final static byte[] R_MACDerivationConstant = { 0x01, 0x02 };
+
+ //For SCP01
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)
+ TPSBuffer cardCryptogram, TPSBuffer hostChallenge, TPSBuffer hostCryptogram, TPSBuffer keyInfoData,
+ PlatformAndSecChannelProtoInfo platformInfo)
throws TPSException {
if (processor == null || sessionKey == null | encSessionKey == null || keyDiversificationData == null
@@ -88,6 +130,9 @@ public class SecureChannel {
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
}
+ CMS.debug("SecureChannel.SecureChannel: For SCP01. ");
+
+ this.platProtInfo = platformInfo;
this.processor = processor;
this.sessionKey = sessionKey;
this.encSessionKey = encSessionKey;
@@ -103,11 +148,105 @@ public class SecureChannel {
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) {
+ //For SCP02
+ public SecureChannel(TPSProcessor processor, PK11SymKey encSessionKey, PK11SymKey cmacSessionKey,
+ PK11SymKey rmacSessionKey, PK11SymKey dekSessionKey, TPSBuffer drmDesKey,
+ TPSBuffer kekDesKey, TPSBuffer keyCheck,
+ TPSBuffer keyDiversificationData,
+ TPSBuffer keyInfoData, TPSBuffer sequenceCounter, TPSBuffer hostChallenge, TPSBuffer cardChallenge,
+ TPSBuffer cardCryptogram, PlatformAndSecChannelProtoInfo platformInfo)
+ throws TPSException {
+
+ if (processor == null || encSessionKey == null | cmacSessionKey == null || rmacSessionKey == null
+ || dekSessionKey == null || keyDiversificationData == null || hostChallenge == null
+ || cardChallenge == null || cardCryptogram == null
+ || keyInfoData == null || platformInfo == null) {
+ throw new TPSException("SecureChannel.SecureChannel: Invalid data in constructor!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ this.sequenceCounter = sequenceCounter;
+ this.platProtInfo = platformInfo;
+ this.processor = processor;
+
+ this.encSessionKey = encSessionKey;
+ this.cmacSessionKey = cmacSessionKey;
+ this.setRmacSessionKey(rmacSessionKey);
+
+ this.keyDiversificationData = keyDiversificationData;
+
+ this.icv = new TPSBuffer(8);
+ this.keyInfoData = keyInfoData;
+ this.cardChallenge = cardChallenge;
+ this.cardCryptogram = cardCryptogram;
+ this.hostChallenge = hostChallenge;
+ this.drmDesKey = drmDesKey;
+ this.kekDesKey = kekDesKey;
+
+ //SCP02
+ this.secLevelGP211 = ExternalAuthenticateAPDUGP211.SecurityLevel.CDEC_CMAC;
+ this.keyCheck = keyCheck;
+
+ byte finalKeyIndex = gp211CalculateLatestKeySet(platformInfo.getKeysetInfoData());
+
+ CMS.debug("SecureChannel.SecureChannel: For SCP02: calculated latest key index: " + finalKeyIndex);
+
+ }
+
+ private byte gp211CalculateLatestKeySet(TPSBuffer keysetInfoData) throws TPSException {
+
+ if (keysetInfoData == null) {
+
+ throw new TPSException("SecureChannel.gp211calculateKeyInfoData invalid input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+ }
+
+ CMS.debug("SecureChannel.gp211calculateKeyInfoData: input keysetInfoData: " + keysetInfoData.toHexString());
+
+ int pos = 0;
+ byte next = keysetInfoData.at(pos++);
+
+ if (next != (byte) 0xE0) {
+ throw new TPSException("SecureChannel.gp211calculateKeyInfoData: malformed input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ next = keysetInfoData.at(pos++);
+
+ int numKeys = (next) / 6;
+
+ int remainder = (next) % 6;
+
+ if (remainder != 0) {
+ throw new TPSException("SecureChannel.gp211calculateKeyInfoData: malformed input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.gp211calculateKeyInfoData: number of keys: " + numKeys);
+
+ int numKeySets = numKeys / 3; //Three keys per set
+
+ CMS.debug("SecureChannel.gp211calculateKeyInfoData: number of keysets: " + numKeySets);
+
+ int offset = (numKeySets - 1) * 6 * 3 + 3;
+
+ CMS.debug("SecureChannel.gp211calculateKeyInfoData: offset " + offset);
+
+ offset += pos;
+
+ if (offset > keysetInfoData.size()) {
+ throw new TPSException("SecureChannel.gp211calculateKeyInfoData: malformed input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ byte finalKeyIndex = keysetInfoData.at(offset);
+
+ return finalKeyIndex;
+
}
public void appendPKCS11Attribute(TPSBuffer buffer, long type, TPSBuffer attribute) {
@@ -204,29 +343,77 @@ public class SecureChannel {
public void externalAuthenticate() throws TPSException, IOException {
- CMS.debug("SecureChannel.externalAuthenticate: entering.");
+ CMS.debug("SecureChannel.externalAuthenticate: entering. &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
- ExternalAuthenticateAPDU externalAuth = new ExternalAuthenticateAPDU(hostCryptogram,
- secLevel);
+ if (platProtInfo.isGP211() && platProtInfo.isSCP02()) {
+ CMS.debug("SecureChannel.externalAuthenticate: Attempting an External Authenticate for SCP02!");
- computeAPDUMac(externalAuth);
+ TPSBuffer calculatedCardCryptogram = computeCardCryptogramSCP02(encSessionKey);
- APDUResponse response = processor.handleAPDURequest(externalAuth);
+ if (false == cardCryptogram.equals(calculatedCardCryptogram)) {
+
+ CMS.debug("SecureChannel.eternalAuthenticate. Failed to match calculated to returned card cryptogram!. cardCryptogram: "
+ + cardCryptogram.toHexString()
+ + " calculatedCardCrytpogram: "
+ + calculatedCardCryptogram.toHexString());
+ throw new TPSException(
+ "SecureChannel.eternalAuthenticate. Failed to match calculated to returned card cryptogram!.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+ }
+
+ TPSBuffer calculatedHostCryptogram = computeHostCryptogramSCP02(encSessionKey);
+ this.hostCryptogram = calculatedHostCryptogram;
+
+ ExternalAuthenticateAPDUGP211 externalAuth = new ExternalAuthenticateAPDUGP211(hostCryptogram,
+ /* secLevel */secLevelGP211);
+
+ CMS.debug("SecureChannel.externalAuthenticate: about to call computeAPDUMacSCP02. &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
+ computeAPDUMacSCP02(externalAuth);
+
+ APDUResponse response = processor.handleAPDURequest(externalAuth);
+
+ if (!response.checkResult()) {
+ throw new TPSException(
+ "SecureChannel.eternalAuthenticate SCP02. Failed to external authenticate to token.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.externalAuthenticate: SCP02 external authenticate returns Success!!!");
+
+ } else { //SCP01
+
+ ExternalAuthenticateAPDU externalAuth = new ExternalAuthenticateAPDU(hostCryptogram,
+ /* secLevel */ExternalAuthenticateAPDU.SecurityLevel.SECURE_MSG_MAC_ENC);
+
+ CMS.debug("SecureChannel.externalAuthenticate: about to call computeAPDUMac. &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
+ computeAPDUMac(externalAuth);
+
+ APDUResponse response = processor.handleAPDURequest(externalAuth);
+
+ if (!response.checkResult()) {
+ throw new TPSException(
+ "SecureChannel.eternalAuthenticate SCP01. Failed to external authenticate to token.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
- 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.
+ // Handle SCP02 if required.
private void computeAPDU(APDU apdu) throws TPSException {
CMS.debug("SecureChannel.computeAPDU: entering..");
+ if (isSCP02()) {
+ computeAPDU_SCP02(apdu);
+ return;
+
+ }
+
if (apdu == null) {
throw new TPSException("SecureChannel.computeAPDU: bad input apdu!",
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
@@ -236,9 +423,9 @@ public class SecureChannel {
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());
+ CMS.debug("SecureChannel.computeAPDU: Before encryption data value: " + apdu.getData().toHexString());
+ apdu.secureMessage(encSessionKey, (byte) 1);
+ 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);
}
@@ -247,6 +434,79 @@ public class SecureChannel {
}
}
+ private void computeAPDU_SCP02(APDU apdu) throws TPSException {
+ CMS.debug("SecureChannel.computeAPDU_SCP02: entering..");
+
+ if (apdu == null) {
+ throw new TPSException("SecureChannel.computeAPDU_SCP02: bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ computeAPDUMacSCP02(apdu);
+
+ if (secLevelGP211 == ExternalAuthenticateAPDUGP211.SecurityLevel.CDEC_CMAC) {
+ try {
+ CMS.debug("SecureChannel.computeAPDU_SCP02: Before encryption data value: "
+ + apdu.getData().toHexString());
+ apdu.secureMessageSCP02(encSessionKey);
+ CMS.debug("SecureChannel.computeAPDU_SCP02: After encryption data value: "
+ + apdu.getData().toHexString());
+ } catch (EBaseException e) {
+ throw new TPSException("SecureChannel.computeAPDU_SCP02: Can't encrypt outgoing data! " + e);
+ }
+
+ CMS.debug("SecureChannel.computeAPDU_SCP02: Successfully encrypted apdu data.");
+ }
+
+ }
+
+ private void computeAPDUMacSCP02(APDU apdu) throws TPSException {
+
+ TPSBuffer newMac = null;
+ TPSBuffer data = null;
+ TPSBuffer singleDes = null;
+
+ if (apdu == null) {
+ throw new TPSException("SecureChannel.computeAPDUMacSCP02: bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ data = apdu.getDataToMAC();
+
+ CMS.debug("SecureChannel.computeAPDUMacSCP02: data To MAC: " + data.toHexString() + " incoming icv: "
+ + icv.toHexString());
+
+ try {
+
+ if (apdu.getType() != APDU.Type.APDU_EXTERNAL_AUTHENTICATE
+ && (secLevelGP211 == ExternalAuthenticateAPDUGP211.SecurityLevel.CMAC || secLevelGP211 == ExternalAuthenticateAPDUGP211.SecurityLevel.CDEC_CMAC)) {
+ CMS.debug("SecureChannel.computeAPDUMacSCP02: data To MAC, calcuating single des encyption before mac.");
+
+ singleDes = Util.computeEncEcbDes(cmacSessionKey, icv);
+ CMS.debug("SecureChannel.computeAPDUMacSCP02: data To MAC, calcuating single des encyption before mac. result: "
+ + singleDes.toHexString());
+
+ newMac = Util.computeMACdes3des(cmacSessionKey, data, singleDes);
+ } else {
+ CMS.debug("SecureChannel.computeAPDUMacSCP02: No ecnrypton of ICV.");
+ newMac = Util.computeMACdes3des(cmacSessionKey, data, icv);
+
+ }
+
+ } catch (EBaseException e) {
+ CMS.debug("SecureChannel.computeAPDUMacSCP02: Can't compute mac. " + e);
+ throw new TPSException("SecureChannel.compuatAPDUMacSCP02: Can't compute mac.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.computeAPDUMacSCP02: computed MAC: " + newMac.toHexString());
+
+ apdu.setMAC(newMac);
+
+ icv.set(newMac);
+
+ }
+
// This method computes MAC only.
private void computeAPDUMac(APDU apdu) throws TPSException {
TPSBuffer newMac = null;
@@ -282,25 +542,47 @@ public class SecureChannel {
throw new TPSException("SecureChannel.deleteFileX: no input aid!");
}
- DeleteFileAPDU deleteFile = new DeleteFileAPDU(aid);
+ if (isGP211()) {
+
+ CMS.debug("SecureChannel.deleteFileX: attempting gp211...");
+ DeleteFileGP211APDU deleteFile = new DeleteFileGP211APDU(aid);
+
+ computeAPDU(deleteFile);
+
+ processor.handleAPDURequest(deleteFile);
+ } else {
+
+ CMS.debug("SecureChannel.deleteFileX: attempting gp201...");
+ DeleteFileAPDU deleteFile = new DeleteFileAPDU(aid);
+
+ computeAPDU(deleteFile);
- computeAPDU(deleteFile);
+ processor.handleAPDURequest(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 ...");
+ CMS.debug("SecureChannel.installLoad: entering ... packageAID: " + packageAID.toHexString() + " sdAID: "
+ + sdAID.toHexString());
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);
+ TPSBuffer emptySDAID = new TPSBuffer();
+
+ if (isGP211()) {
+ TPSBuffer cardMgrGP211AIDBuff = new TPSBuffer(TPSEngine.CFG_DEF_CARDMGR_211_INSTANCE_AID);
+ installLoadGP211(packageAID, cardMgrGP211AIDBuff, fileLength);
+ return;
+ }
+
+ InstallLoadAPDU install = new InstallLoadAPDU(packageAID, emptySDAID, fileLength);
CMS.debug("SecureChannel.installLoad: Pre computed apdu: " + install.getEncoding().toHexString());
@@ -315,11 +597,34 @@ public class SecureChannel {
}
+ public void installLoadGP211(TPSBuffer packageAID, TPSBuffer sdAID, int fileLength) throws TPSException,
+ IOException {
+
+ CMS.debug("SecureChannel.installLoadGP211: entering ...");
+
+ if (packageAID == null || sdAID == null || fileLength <= 0) {
+ throw new TPSException("SecureChannel.insallLoadGP211 bad input parameters!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ InstallLoadGP211APDU install = new InstallLoadGP211APDU(packageAID, sdAID,
+ fileLength);
+
+ computeAPDU(install);
+
+ APDUResponse response = processor.handleAPDURequest(install);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.installLoadGP211. Failed to perform installLoadGP211 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...");
+ CMS.debug("SecureChannel.loadFile entering... blockSize: " + blockSize);
if (programFile == null || blockSize <= 0) {
throw new TPSException("ScureChannel.loadFile. Bad input data.", TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
@@ -407,11 +712,25 @@ public class SecureChannel {
TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
}
- LoadFileAPDU loadFile = new LoadFileAPDU(refControl, (byte) count, piece);
+ CMS.debug("SecureChannel.loadFileSegment: count: " + count + " piece: " + piece.toHexString());
+
+ APDUResponse response = null;
+
+ if (isGP211()) {
+ LoadFileAPDUGP211 loadFile = new LoadFileAPDUGP211(refControl, (byte) count, piece);
- computeAPDU(loadFile);
+ computeAPDU(loadFile);
- APDUResponse response = processor.handleAPDURequest(loadFile);
+ response = processor.handleAPDURequest(loadFile);
+ } else {
+ CMS.debug("SecureChannel.loadFileSegment: gp211.");
+ LoadFileAPDU loadFile = new LoadFileAPDU(refControl, (byte) count, piece);
+
+ computeAPDU(loadFile);
+
+ response = processor.handleAPDURequest(loadFile);
+
+ }
if (!response.checkResult()) {
throw new TPSException(
@@ -437,12 +756,25 @@ public class SecureChannel {
}
- InstallAppletAPDU install = new InstallAppletAPDU(netkeyPAIDBuff, netkeyAIDBuff, appPrivileges,
- channelInstanceSize, channelAppletMemSize);
+ APDUResponse response = null;
- computeAPDU(install);
+ if (isGP211()) {
+ InstallAppletAPDUGP211 install = new InstallAppletAPDUGP211(netkeyPAIDBuff, netkeyAIDBuff, appPrivileges,
+ channelInstanceSize, channelAppletMemSize);
- APDUResponse response = processor.handleAPDURequest(install);
+ computeAPDU(install);
+
+ response = processor.handleAPDURequest(install);
+ } else {
+
+ InstallAppletAPDU install = new InstallAppletAPDU(netkeyPAIDBuff, netkeyAIDBuff, appPrivileges,
+ channelInstanceSize, channelAppletMemSize);
+
+ computeAPDU(install);
+
+ response = processor.handleAPDURequest(install);
+
+ }
if (!response.checkResult()) {
throw new TPSException("SecureChannel.installApplett. Failed installApplet operation.",
@@ -972,7 +1304,8 @@ public class SecureChannel {
public void putKeys(byte curVersion, byte curIndex, TPSBuffer keySetData) throws TPSException, IOException {
- CMS.debug("SecureChannel.putKeys: entering..");
+ CMS.debug("SecureChannel.putKeys: entering.. curVersion: " + curVersion + " curIndex: " + curIndex
+ + " keySetData: " + keySetData);
if (keySetData == null) {
throw new TPSException("SecureChannel.putKeys: Invalid input data!", TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
@@ -980,14 +1313,27 @@ public class SecureChannel {
byte keyVersion = curVersion;
- if (curVersion == 0xff) {
- keyVersion = 0x0;
+ if (curVersion == (byte) 0xff) {
+ CMS.debug("Setting keyVersion to 1");
+ keyVersion = 0x1;
}
- PutKeyAPDU putKey = new PutKeyAPDU(keyVersion, (byte) (0x80 | curIndex), keySetData);
+ CMS.debug("keyVersion now set to: " + keyVersion);
+
+ PutKeyAPDU putKey = new PutKeyAPDU(keyVersion, (byte) 0x81, keySetData);
+ if (isSCP02()) {
+ TPSBuffer trailer = new TPSBuffer(1);
+ putKey.setTrailer(trailer);
+
+ }
computeAPDU(putKey);
+ int kill = 0;
+ if (kill == 1) {
+ throw new TPSException("putKeys end of progress.");
+ }
+
APDUResponse response = processor.handleAPDURequest(putKey);
if (!response.checkResult()) {
@@ -1017,11 +1363,12 @@ public class SecureChannel {
CMS.debug("SecureChannel.importKeyEnc entering...");
- if(data == null) {
- throw new TPSException("SecureChannel.importKeyEnc: Invalid input data!",TPSStatus.STATUS_ERROR_MAC_CERT_PDU);
+ 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);
+ ImportKeyEncAPDU importKeyEnc = new ImportKeyEncAPDU((byte) pe1, (byte) pe2, data);
computeAPDU(importKeyEnc);
@@ -1042,4 +1389,119 @@ public class SecureChannel {
this.kekDesKey = kekDesKey;
}
+ public TPSBuffer getSequenceCounter() {
+ return sequenceCounter;
+ }
+
+ public PlatformAndSecChannelProtoInfo getChannelPlatformAndProtocolInfo() {
+ return platProtInfo;
+ }
+
+ protected TPSBuffer computeCardCryptogramSCP02(PK11SymKey encSessionKey)
+ throws TPSException {
+
+ if (encSessionKey == null) {
+ throw new TPSException("TPSProcessor.computeCardCryptogramSCP02: invalide input data",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ TPSBuffer data = new TPSBuffer(hostChallenge);
+ data.add(sequenceCounter);
+ data.add(cardChallenge);
+
+ if (data.size() != 16) {
+ throw new TPSException("calculateCardCryptogramSCP02: card cyrptogram source data incorrect size.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ TPSBuffer cardCryptogram = null;
+ try {
+ cardCryptogram = Util.computeMAC(encSessionKey, data, icv);
+ } catch (EBaseException e) {
+ throw new TPSException("calculateCardCryptogramSCP02: card cyrptogram: Error calculating the MAC value",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSProcessor.calculateCardCrytogramSCP02: returning calculated card cryptogram; "
+ + cardCryptogram.toHexString());
+
+ return cardCryptogram;
+
+ }
+
+ protected TPSBuffer computeHostCryptogramSCP02(PK11SymKey encSessionKey)
+ throws TPSException {
+
+ if (encSessionKey == null) {
+ throw new TPSException("TPSProcessor.computeHostCryptogramSCP02: invalide input data",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ TPSBuffer hostCryptogramSCP02 = null;
+
+ TPSBuffer data = new TPSBuffer(sequenceCounter);
+ data.add(cardChallenge);
+ data.add(hostChallenge);
+
+ if (data.size() != 16) {
+ throw new TPSException("calculateHostCryptogramSCP02: host cyrptogram source data incorrect size.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ try {
+ hostCryptogramSCP02 = Util.computeMAC(encSessionKey, data, icv);
+ } catch (EBaseException e) {
+ throw new TPSException("calculateHostCryptogramSCP02: host cyrptogram: Error calculating the MAC value",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSProcessor.calculateHostCrytogramSCP02: returning calculated host cryptogram; "
+ + hostCryptogramSCP02.toHexString());
+
+ return hostCryptogramSCP02;
+
+ }
+
+ public boolean isSCP02() {
+ if (platProtInfo.isGP211() && platProtInfo.isSCP02()) {
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isGP211() {
+
+ if (platProtInfo.isGP211()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public TPSBuffer getDekSessionKeyWrapped() {
+ return dekSessionKeyWrapped;
+ }
+
+ public void setDekSessionKeyWrapped(TPSBuffer dekSessionKeyWrapped) {
+ this.dekSessionKeyWrapped = dekSessionKeyWrapped;
+ }
+
+ public PK11SymKey getDekSessionKey() {
+ return dekSessionKey;
+ }
+
+ public void setDekSessionKey(PK11SymKey dekSessionKey) {
+ this.dekSessionKey = dekSessionKey;
+ }
+
+ public PK11SymKey getRmacSessionKey() {
+ return rmacSessionKey;
+ }
+
+ public void setRmacSessionKey(PK11SymKey rmacSessionKey) {
+ this.rmacSessionKey = rmacSessionKey;
+ }
+
}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
index 3c371a45e..c6537e4c2 100644
--- a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
@@ -22,6 +22,7 @@ import java.util.Hashtable;
import org.dogtagpki.server.connector.IRemoteRequest;
import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.channel.SecureChannel;
import org.dogtagpki.tps.main.TPSBuffer;
import org.dogtagpki.tps.main.Util;
@@ -93,7 +94,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
boolean serverKeygen =
conf.getBoolean("op.enroll." +
- tokenType + ".keyGen.encryption.serverKeygen.enable",
+ tokenType + ".keyGen.encryption.serverKeygen.enable",
false);
String keySet =
conf.getString("connector." + connid + "keySet", "defKeySet");
@@ -205,6 +206,143 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
}
/*
+ * computeSessionKey
+ *
+ * Usage Example:
+ * TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+ * TKSComputeSessionKeyResponse responseObj =
+ * tksReq.computeSessionKey(
+ * cuid,
+ * keyInfo,
+ * card_challenge,
+ * card_cryptogram,
+ * host_challenge);
+ * - on success return, one can say
+ * TPSBuffer value = responseObj.getSessionKey();
+ * to get response param value session key
+ *
+ * @param cuid token cuid
+ * @param keyInfo keyInfo
+ * @param card_challenge card challenge
+ * @param card_cryptogram card cryptogram
+ * @param host_challenge host challenge
+ * @return response TKSComputeSessionKeyResponse class object
+ */
+ public TKSComputeSessionKeyResponse computeSessionKeySCP02(
+ TPSBuffer cuid,
+ TPSBuffer keyInfo,
+ TPSBuffer sequenceCounter,
+ TPSBuffer derivationConstant,
+ String tokenType)
+ throws EBaseException {
+
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): begins.");
+ if (cuid == null || keyInfo == null ||
+ sequenceCounter == null
+ || derivationConstant == null) {
+ throw new EBaseException("TKSRemoteRequestHandler: computeSessionKeySCP02(): input parameter null.");
+ }
+
+ IConfigStore conf = CMS.getConfigStore();
+
+ boolean serverKeygen =
+ conf.getBoolean("op.enroll." +
+ tokenType + ".keyGen.encryption.serverKeygen.enable",
+ false);
+ String keySet =
+ conf.getString("connector." + connid + "keySet", "defKeySet");
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+
+ String requestString = IRemoteRequest.SERVER_SIDE_KEYGEN + "=" + serverKeygen +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid) +
+ "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(keyInfo) +
+ "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet +
+ "&" + IRemoteRequest.CHANNEL_PROTOCOL + "=" + SecureChannel.SECURE_PROTO_02 +
+ "&" + IRemoteRequest.SEQUENCE_COUNTER + "=" + Util.specialURLEncode(sequenceCounter) +
+ "&" + IRemoteRequest.DERIVATION_CONSTANT + "=" + Util.specialURLEncode(derivationConstant);
+
+ HttpResponse resp =
+ conn.send("computeSessionKey",
+ requestString
+ );
+
+ String content = resp.getContent();
+
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /*
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ * Note: serverKeygen and !serverKeygen returns different set of
+ * response values so "missing" might not be bad
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): status not found.");
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): got content = " + content);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): got status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_SessionKey);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_SessionKey);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): got IRemoteRequest.TKS_RESPONSE_SessionKey = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_SessionKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): got IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): got IRemoteRequest.TKS_RESPONSE_KEK_DesKey = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_KEK_DesKey, Util.specialDecode(value));
+
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeyCheck);
+
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_KeyCheck);
+
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): got IRemoteRequest.TKS_RESPONSE_KeyCheck = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_KeyCheck, Util.specialDecode(value));
+ }
+
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): ends.");
+
+ return new TKSComputeSessionKeyResponse(response);
+
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKeySCP02(): no response content.");
+ throw new EBaseException("TKSRemoteRequestHandler: computeSessionKeySCP02(): no response content.");
+ }
+ }
+
+ /*
* createKeySetData
*
* Usage Example:
@@ -226,7 +364,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
public TKSCreateKeySetDataResponse createKeySetData(
TPSBuffer NewMasterVer,
TPSBuffer version,
- TPSBuffer cuid)
+ TPSBuffer cuid, int protocol, TPSBuffer wrappedDekSessionKey)
throws EBaseException {
CMS.debug("TKSRemoteRequestHandler: createKeySetData(): begins.");
if (cuid == null || NewMasterVer == null || version == null) {
@@ -242,12 +380,21 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler
HttpConnector conn =
(HttpConnector) subsystem.getConnectionManager().getConnector(connid);
CMS.debug("TKSRemoteRequestHandler: createKeySetData(): sending request to tks.");
+
+ String command = IRemoteRequest.TOKEN_NEW_KEYINFO + "=" + Util.specialURLEncode(NewMasterVer) +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid) +
+ "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(version) +
+ "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet +
+ "&" + IRemoteRequest.CHANNEL_PROTOCOL + "=" + protocol;
+
+ if(wrappedDekSessionKey != null) { // We have secure channel protocol 02 trying to upgrade the key set.
+ command += "&" + IRemoteRequest.WRAPPED_DEK_SESSION_KEY + "=" + Util.specialURLEncode(wrappedDekSessionKey);
+ }
+
+
HttpResponse resp =
conn.send("createKeySetData",
- IRemoteRequest.TOKEN_NEW_KEYINFO + "=" + Util.specialURLEncode(NewMasterVer) +
- "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid) +
- "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(version) +
- "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet);
+ command);
String content = resp.getContent();
diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
index 9221d1ba0..e7efcc031 100644
--- a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
+++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -106,11 +106,13 @@ public class TPSEngine {
public static final String CFG_APPLET_DIRECTORY = "update.applet.directory";
public static final String CFG_APPLET_EXTENSION = "general.applet_ext";
- public static final String CFG_CHANNEL_BLOCK_SIZE = "channel.blockSize";
+ public static final String CFG_CHANNEL_BLOCK_SIZE = "channel.blocksize";
public static final String CFG_CHANNEL_INSTANCE_SIZE = "channel.instanceSize";
public static final String CFG_CHANNEL_DEFKEY_VERSION = "channel.defKeyVersion";
public static final String CFG_CHANNEL_APPLET_MEMORY_SIZE = "channel.appletMemorySize";
public static final String CFG_CHANNEL_DEFKEY_INDEX = "channel.defKeyIndex";
+ public static final String CFG_CHANNEL_DEF_PLATFORM = "channel.defPlatform";
+ public static final String CFG_CHANNEL_DEF_SECURE_PROTO = "channel.defSecureProtocol";
public static final String CFG_ISSUER_INFO_ENABLE = "issuerinfo.enable";
public static final String CFG_ISSUER_INFO_VALUE = "issuerinfo.value";
public static final String CFG_UPDATE_APPLET_ENCRYPTION = "update.applet.encryption";
@@ -119,6 +121,7 @@ public class TPSEngine {
/* default values */
public static final String CFG_DEF_CARDMGR_INSTANCE_AID = "A0000000030000";
+ public static final String CFG_DEF_CARDMGR_211_INSTANCE_AID = "A000000003000000";
public static final String CFG_DEF_NETKEY_INSTANCE_AID = "627601FF000000";
public static final String CFG_DEF_NETKEY_FILE_AID = "627601FF0000";
public static final String CFG_DEF_NETKEY_OLD_INSTANCE_AID = "A00000000101";
@@ -204,6 +207,45 @@ public class TPSEngine {
return rc;
}
+ public TKSComputeSessionKeyResponse computeSessionKeySCP02(
+ TPSBuffer cuid,
+ TPSBuffer keyInfo,
+ TPSBuffer sequenceCounter,
+ TPSBuffer derivationConstant,
+ String connId,
+ String tokenType)
+ throws TPSException {
+
+ if (cuid == null || keyInfo == null || sequenceCounter == null || derivationConstant == null
+ || tokenType == null) {
+ throw new TPSException("TPSEngine.computeSessionKeySCP02: Invalid input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSEngine.computeSessionKeySCP02");
+
+ TKSRemoteRequestHandler tks = null;
+
+ TKSComputeSessionKeyResponse resp = null;
+ try {
+ tks = new TKSRemoteRequestHandler(connId);
+ resp = tks.computeSessionKeySCP02(cuid, keyInfo, sequenceCounter, derivationConstant, tokenType);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEngine.computeSessionKeySCP02: Error computing session key!" + e,
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ int status = resp.getStatus();
+ if (status != 0) {
+ CMS.debug("TPSEngine.computeSessionKeySCP02: Non zero status result: " + status);
+ throw new TPSException("TPSEngine.computeSessionKeySCP02: invalid returned status: " + status);
+
+ }
+
+ return resp;
+
+ }
+
public TKSComputeSessionKeyResponse computeSessionKey(TPSBuffer cuid,
TPSBuffer keyInfo,
TPSBuffer card_challenge,
@@ -330,7 +372,7 @@ public class TPSEngine {
}
- public TPSBuffer createKeySetData(TPSBuffer newMasterVersion, TPSBuffer oldVersion, TPSBuffer cuid, String connId)
+ public TPSBuffer createKeySetData(TPSBuffer newMasterVersion, TPSBuffer oldVersion, int protocol, TPSBuffer cuid, TPSBuffer wrappedDekSessionKey, String connId)
throws TPSException {
CMS.debug("TPSEngine.createKeySetData. entering...");
@@ -345,7 +387,7 @@ public class TPSEngine {
try {
tks = new TKSRemoteRequestHandler(connId);
- resp = tks.createKeySetData(newMasterVersion, oldVersion, cuid);
+ resp = tks.createKeySetData(newMasterVersion, oldVersion, cuid, protocol,wrappedDekSessionKey);
} catch (EBaseException e) {
throw new TPSException("TPSEngine.createKeySetData, failure to get key set data from TKS",
@@ -541,27 +583,27 @@ public class TPSEngine {
}
- //Check to see if special operations transition is allowed
+ //Check to see if special operations transition is allowed
public boolean isOperationTransitionAllowed(TokenStatus oldState, TokenStatus newState) throws TPSException {
boolean allowed = true;
- if(transitionList == null) {
+ if (transitionList == null) {
IConfigStore configStore = CMS.getConfigStore();
- String transConfig = CFG_OPERATIONS_TRANSITIONS;
+ String transConfig = CFG_OPERATIONS_TRANSITIONS;
CMS.debug("TPSEngine.isOperationTransistionAllowed: getting config: " + transConfig);
try {
- transitionList = configStore.getString(transConfig,null);
+ transitionList = configStore.getString(transConfig, null);
} catch (EBaseException e) {
throw new TPSException(
"TPSProcessor.isOperationTransitionAllowed: Internal error getting config value for operations transition list!",
TPSStatus.STATUS_ERROR_MISCONFIGURATION);
}
- if(transitionList == null) {
+ if (transitionList == null) {
throw new TPSException(
"TPSProcessor.isOperationTransitionAllowed: Can't find non null config value for operations transition list!",
TPSStatus.STATUS_ERROR_MISCONFIGURATION);
@@ -569,21 +611,21 @@ public class TPSEngine {
CMS.debug("TPSEngine.isOperationTransistionAllowed: transitionList is: " + transitionList);
-
}
String transition = oldState.toInt() + ":" + newState.toInt();
CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition);
- if(transitionList.indexOf(transition) == -1) {
+ if (transitionList.indexOf(transition) == -1) {
CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition);
allowed = false;
}
- CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition + " allowed: " + allowed);
+ CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition + " allowed: "
+ + allowed);
- return allowed;
+ return allowed;
}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
index c74fe2cb6..5b8560a1d 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -301,12 +301,10 @@ public class TPSEnrollProcessor extends TPSProcessor {
CMS.debug("TPSEnrollProcessor.enroll: Finished updating applet if needed.");
//Check and upgrade keys if called for
-
SecureChannel channel = checkAndUpgradeSymKeys();
channel.externalAuthenticate();
//Reset the token's pin, create one if we don't have one already
-
checkAndHandlePinReset(channel);
tokenRecord.setKeyInfo(channel.getKeyInfoData().toHexStringPlain());
String tksConnId = getTKSConnectorID();
@@ -2361,6 +2359,10 @@ public class TPSEnrollProcessor extends TPSProcessor {
TPSBuffer keyCheck = channel.getKeyCheck();
+ if (keyCheck == null) {
+ keyCheck = new TPSBuffer();
+ }
+
CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 : keyCheck: " + keyCheck.toHexString());
// String ivParams = ssKeyGenResponse.getIVParam();
@@ -2381,7 +2383,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
CMS.debug("TPSEnrollProcessor.iportPrivateKeyPKC8: null kekWrappedDesKey!");
byte alg = (byte) 0x80;
- if (kekWrappedDesKey == null || kekWrappedDesKey.size() > 0) {
+ if (kekWrappedDesKey != null && kekWrappedDesKey.size() > 0) {
alg = (byte) 0x81;
}
@@ -2392,9 +2394,13 @@ public class TPSEnrollProcessor extends TPSProcessor {
data.add((byte) kekWrappedDesKey.size());
data.add(kekWrappedDesKey);
data.add((byte) keyCheck.size());
- data.add(keyCheck);
+ if (keyCheck.size() > 0) {
+ data.add(keyCheck);
+ }
data.add((byte) ivParamsBuff.size());
data.add(ivParamsBuff);
+ CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8: key data outgoing: " + data.toHexString());
+
int pe1 = (cEnrollInfo.getKeyUser() << 4) + cEnrollInfo.getPrivateKeyNumber();
int pe2 = (cEnrollInfo.getKeyUsage() << 4) + cEnrollInfo.getPublicKeyNumber();
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index 895893924..ee8b7529f 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -39,6 +39,7 @@ import org.dogtagpki.server.tps.TPSSession;
import org.dogtagpki.server.tps.TPSSubsystem;
import org.dogtagpki.server.tps.authentication.AuthUIParameter;
import org.dogtagpki.server.tps.authentication.TPSAuthenticator;
+import org.dogtagpki.server.tps.channel.PlatformAndSecChannelProtoInfo;
import org.dogtagpki.server.tps.channel.SecureChannel;
import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
import org.dogtagpki.server.tps.cms.CARevokeCertResponse;
@@ -57,7 +58,6 @@ import org.dogtagpki.server.tps.profile.BaseTokenProfileResolver;
import org.dogtagpki.server.tps.profile.TokenProfileParams;
import org.dogtagpki.tps.apdu.APDU;
import org.dogtagpki.tps.apdu.APDUResponse;
-import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
import org.dogtagpki.tps.apdu.GetDataAPDU;
import org.dogtagpki.tps.apdu.GetStatusAPDU;
import org.dogtagpki.tps.apdu.GetVersionAPDU;
@@ -104,7 +104,11 @@ public class TPSProcessor {
public static final int DIVERSIFICATION_DATA_SIZE = 10;
public static final int CARD_CRYPTOGRAM_OFFSET = 20;
public static final int CARD_CRYPTOGRAM_SIZE = 8;
+ public static final int CARD_CHALLENGE_SIZE_GP211_SC02 = 6;
+ public static final int SEQUENCE_COUNTER_OFFSET_GP211_SC02 = 12;
+ public static final int SEQUENCE_COUNTER_SIZE_GP211_SC02 = 2;
public static final int CARD_CHALLENGE_OFFSET = 12;
+ public static final int CARD_CHALLENGE_OFFSET_GP211_SC02 = 14;
public static final int CARD_CHALLENGE_SIZE = 8;
protected boolean isExternalReg;
@@ -119,6 +123,7 @@ public class TPSProcessor {
protected String currentTokenOperation;
protected BeginOpMsg beginMsg;
+ private PlatformAndSecChannelProtoInfo platProtInfo;
public TPSProcessor(TPSSession session) {
setSession(session);
@@ -286,7 +291,7 @@ public class TPSProcessor {
}
protected TPSBuffer getCplcData() throws IOException, TPSException {
- CMS.debug("In TPS_Processor.GetData");
+ CMS.debug("In TPS_Processor.");
GetDataAPDU get_data_apdu = new GetDataAPDU();
@@ -304,6 +309,24 @@ public class TPSProcessor {
return respApdu.getData();
}
+ public TPSBuffer getData(byte[] identifier) throws TPSException, IOException {
+ CMS.debug("In TPSProcessor.getData: identifier: " + identifier.toString());
+
+ if (identifier == null || identifier.length != 2) {
+ throw new TPSException("TPSProcessor.getData: Can't get data, invalid input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+ GetDataAPDU get_data_apdu = new GetDataAPDU(identifier);
+
+ APDUResponse respApdu = handleAPDURequest(get_data_apdu);
+
+ if (!respApdu.checkResult()) {
+ throw new TPSException("TPSProcessor.getData: Can't get data!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ return respApdu.getData();
+ }
+
protected TPSBuffer getAppletVersion() throws IOException, TPSException {
//We return null if no applet present
// This is not an error, the token can be blank.
@@ -389,6 +412,10 @@ public class TPSProcessor {
CMS.debug("In TPS_Processor.initializeUpdate.");
InitializeUpdateAPDU initUpdate = new InitializeUpdateAPDU(keyVersion, keyIndex, randomData);
+ int done = 0;
+ if (done == 1)
+ throw new TPSException("TPSProcessor.initializeUpdate. debugging exit...");
+
APDUResponse resp = handleAPDURequest(initUpdate);
if (!resp.checkResult()) {
@@ -418,7 +445,7 @@ public class TPSProcessor {
int defKeyVersion = getChannelDefKeyVersion();
int defKeyIndex = getChannelDefKeyIndex();
- channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, SecurityLevel.SECURE_MSG_MAC_ENC,
+ channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex,
getTKSConnectorID());
channel.externalAuthenticate();
@@ -426,15 +453,20 @@ public class TPSProcessor {
return channel;
}
- protected SecureChannel setupSecureChannel(byte keyVersion, byte keyIndex, SecurityLevel securityLevel,
+ protected SecureChannel setupSecureChannel(byte keyVersion, byte keyIndex,
String connId)
throws IOException, TPSException {
//Assume generating host challenge on TKS, we no longer support not involving the TKS.
+ CMS.debug("TPSProcessor.setupSecureChannel: keyVersion: " + keyVersion + " keyIndex: " + keyIndex
+ );
+
TPSBuffer randomData = computeRandomData(8, connId);
CMS.debug("TPSProcessor.setupSecureChannel: obtained randomData: " + randomData.toHexString());
+ acquireChannelPlatformAndProtocolInfo();
+
TPSBuffer initUpdateResp = initializeUpdate(keyVersion, keyIndex, randomData);
TPSBuffer key_diversification_data = initUpdateResp.substr(0, DIVERSIFICATION_DATA_SIZE);
@@ -446,10 +478,43 @@ public class TPSProcessor {
TokenRecord tokenRecord = getTokenRecord();
tokenRecord.setKeyInfo(key_info_data.toHexStringPlain());
- TPSBuffer card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET, CARD_CRYPTOGRAM_SIZE);
+ TPSBuffer card_cryptogram = null;
+ TPSBuffer sequenceCounter = null;
+
+ boolean isGp211scp02 = false;
+
+ if (platProtInfo.getPlatform().equals(SecureChannel.GP211)) {
+ isGp211scp02 = true;
+ }
+
+ card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET, CARD_CRYPTOGRAM_SIZE);
CMS.debug("TPSProcessor.setupSecureChannel: card cryptogram: " + card_cryptogram.toHexString());
- TPSBuffer card_challenge = initUpdateResp.substr(CARD_CHALLENGE_OFFSET, CARD_CHALLENGE_SIZE);
+ TPSBuffer card_challenge = null;
+
+ if (isGp211scp02) {
+ sequenceCounter = initUpdateResp.substr(SEQUENCE_COUNTER_OFFSET_GP211_SC02, 2);
+
+ {
+ card_challenge = initUpdateResp
+ .substr(CARD_CHALLENGE_OFFSET_GP211_SC02, CARD_CHALLENGE_SIZE_GP211_SC02);
+ card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET, CARD_CRYPTOGRAM_SIZE); //new TPSBuffer(canned_card_challenge);
+
+ CMS.debug("TPSProcessor.setupSecureChannel 02: card cryptogram: " + card_cryptogram.toHexString());
+ CMS.debug("TPSProcessor.setupSecureChannel 02: card challenge: " + card_challenge.toHexString());
+ CMS.debug("TPSProcessor.setupSecureChannel 02: host challenge: " + randomData.toHexString());
+
+ }
+
+ //Set the second byte of the keyInfo data to 0x1, this only gives us the secure protocol version 0x2 here.
+ //This will allow symkey to not get confused with that 0x02.
+ CMS.debug("TPSProcessor.setupSecureChannel 02: key Info , before massage: " + key_info_data.toHexString());
+ key_info_data.setAt(1, (byte) 0x1);
+ CMS.debug("TPSProcessor.setupSecureChannel 02: key Info , after massage: " + key_info_data.toHexString());
+
+ } else {
+ card_challenge = initUpdateResp.substr(CARD_CHALLENGE_OFFSET, CARD_CHALLENGE_SIZE);
+ }
CMS.debug("TPSProcessor.setupSecureChannel: card challenge: " + card_challenge.toHexString());
SecureChannel channel = null;
@@ -457,7 +522,7 @@ public class TPSProcessor {
try {
channel = generateSecureChannel(connId, key_diversification_data, key_info_data, card_challenge,
card_cryptogram,
- randomData);
+ randomData, sequenceCounter);
} catch (EBaseException e) {
throw new TPSException("TPSProcessor.setupSecureChannel: Can't set up secure channel: " + e,
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
@@ -468,27 +533,35 @@ public class TPSProcessor {
}
protected SecureChannel generateSecureChannel(String connId, TPSBuffer keyDiversificationData,
- TPSBuffer keyInfoData, TPSBuffer cardChallenge, TPSBuffer cardCryptogram, TPSBuffer hostChallenge)
- throws EBaseException, TPSException {
+ TPSBuffer keyInfoData, TPSBuffer cardChallenge, TPSBuffer cardCryptogram, TPSBuffer hostChallenge,
+ TPSBuffer sequenceCounter)
+ throws EBaseException, TPSException, IOException {
- CMS.debug("TPSProcessor.generateSecureChannel: entering..");
+ if (connId == null || keyDiversificationData == null || keyInfoData == null || cardChallenge == null
+ || cardCryptogram == null || hostChallenge == null) {
+ throw new TPSException("TPSProcessor.generateSecureChannel: Invalid input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSProcessor.generateSecureChannel: entering.. keyInfoData: " + keyInfoData.toHexString());
+ CMS.debug("TPSProcessor.generateSecureChannel: isSCP02: " + platProtInfo.isSCP02());
TPSEngine engine = getTPSEngine();
SecureChannel channel = null;
TPSBuffer hostCryptogram = null;
+ PK11SymKey sessionKey = null;
+ PK11SymKey encSessionKey = null;
+ TKSComputeSessionKeyResponse resp = null;
+ TKSComputeSessionKeyResponse respEnc02 = null;
+ TKSComputeSessionKeyResponse respDek02 = null;
+ TKSComputeSessionKeyResponse respCMac02 = null;
+ TKSComputeSessionKeyResponse respRMac02 = null;
- TKSComputeSessionKeyResponse resp = engine.computeSessionKey(keyDiversificationData, keyInfoData,
- cardChallenge, hostChallenge, cardCryptogram,
- connId, getSelectedTokenType());
-
- hostCryptogram = resp.getHostCryptogram();
-
- if (hostCryptogram == null) {
- new TPSException("TPSProcessor.generateSecureChannel: No host cryptogram returned from token!",
- TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
-
- }
+ PK11SymKey encSessionKeySCP02 = null;
+ PK11SymKey dekSessionKeySCP02 = null;
+ PK11SymKey cmacSessionKeySCP02 = null;
+ PK11SymKey rmacSessionKeySCP02 = null;
PK11SymKey sharedSecret = null;
@@ -500,59 +573,175 @@ public class TPSProcessor {
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
}
- PK11SymKey sessionKey = null;
- PK11SymKey encSessionKey = null;
String tokenName = "Internal Key Storage Token";
- try {
- TPSBuffer sessionKeyWrapped = resp.getSessionKey();
- TPSBuffer encSessionKeyWrapped = resp.getEncSessionKey();
+ if (platProtInfo.isGP201() || platProtInfo.isSCP01()) {
+
+ resp = engine.computeSessionKey(keyDiversificationData, keyInfoData,
+ cardChallenge, hostChallenge, cardCryptogram,
+ connId, getSelectedTokenType());
- sessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
- sessionKeyWrapped.toBytesArray());
+ hostCryptogram = resp.getHostCryptogram();
- if (sessionKey == null) {
- CMS.debug("TPSProcessor.generateSecureChannel: Can't extract session key!");
- throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract session key!",
+ if (hostCryptogram == null) {
+ throw new TPSException("TPSProcessor.generateSecureChannel: No host cryptogram returned from token!",
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
}
- CMS.debug("TPSProcessor.generateSecureChannel: retrieved session key: " + sessionKey);
- encSessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
- encSessionKeyWrapped.toBytesArray());
+ try {
+ TPSBuffer sessionKeyWrapped = resp.getSessionKey();
+ TPSBuffer encSessionKeyWrapped = resp.getEncSessionKey();
+
+ sessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+ sessionKeyWrapped.toBytesArray());
+
+ if (sessionKey == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't extract session key!");
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract session key!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+ CMS.debug("TPSProcessor.generateSecureChannel: retrieved session key: " + sessionKey);
+
+ encSessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+ encSessionKeyWrapped.toBytesArray());
- if (encSessionKey == null) {
- CMS.debug("TPSProcessor.generateSecureChannel: Can't extract enc session key!");
- throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract enc session key!",
+ if (encSessionKey == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't extract enc session key!");
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract enc session key!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSProcessor.generateSecureChannel: retrieved enc session key: " + encSessionKey);
+
+ TPSBuffer drmDesKey = null;
+ TPSBuffer kekDesKey = null;
+ TPSBuffer keyCheck = null;
+
+ drmDesKey = resp.getDRM_Trans_DesKey();
+ keyCheck = resp.getKeyCheck();
+ kekDesKey = resp.getKekWrappedDesKey();
+
+ if (checkServerSideKeyGen(connId)) {
+
+ CMS.debug("TPSProcessor.generateSecureChannel: drmDesKey: " + drmDesKey + " kekDesKey : "
+ + kekDesKey
+ + " keyCheck: " + keyCheck);
+ //ToDo handle server side keygen.
+
+ }
+ channel = new SecureChannel(this, sessionKey, encSessionKey, drmDesKey,
+ kekDesKey, keyCheck, keyDiversificationData, cardChallenge,
+ cardCryptogram, hostChallenge, hostCryptogram, keyInfoData, platProtInfo);
+
+ } catch (Exception e) {
+ CMS.debug(e);
+ e.printStackTrace();
+ throw new TPSException("TPSProcessor.generateSecureChannel: Problem extracting session keys! " + e,
TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
}
- CMS.debug("TPSProcessor.generateSecureChannel: retrieved enc session key: " + encSessionKey);
- } catch (Exception e) {
- CMS.debug(e);
- e.printStackTrace();
- throw new TPSException("TPSProcessor.generateSecureChannel: Problem extracting session keys! " + e,
- TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
}
- TPSBuffer drmDesKey = null;
- TPSBuffer kekDesKey = null;
- TPSBuffer keyCheck = null;
+ if (platProtInfo.isGP211() && platProtInfo.isSCP02()) {
+ //Generate the 4 keys we need for SCP02, Impl 15
+
+ if (sequenceCounter == null) {
+ throw new TPSException("TPSProcessor.generateSecureChannel: Invalid input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSProcessor.generateSecureChannel Trying secure channel protocol 02");
+ respEnc02 = engine.computeSessionKeySCP02(keyDiversificationData, keyInfoData,
+ sequenceCounter, new TPSBuffer(SecureChannel.ENCDerivationConstant),
+ connId, getSelectedTokenType());
+
+ TPSBuffer encSessionKeyWrappedSCP02 = respEnc02.getSessionKey();
+ encSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+ encSessionKeyWrappedSCP02.toBytesArray());
+
+ if (encSessionKeySCP02 == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't extract the SCP02 enc session key!");
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't the emc SCP02 session keys!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ respCMac02 = engine.computeSessionKeySCP02(keyDiversificationData, keyInfoData,
+ sequenceCounter, new TPSBuffer(SecureChannel.C_MACDerivationConstant),
+ connId, getSelectedTokenType());
+
+ TPSBuffer cmacSessionKeyWrappedSCP02 = respCMac02.getSessionKey();
+
+ cmacSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+ cmacSessionKeyWrappedSCP02.toBytesArray());
+
+ if (cmacSessionKeySCP02 == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't extract the SCP02 cmac session key!");
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't the s,ac SCP02 session keys!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ respRMac02 = engine.computeSessionKeySCP02(keyDiversificationData, keyInfoData,
+ sequenceCounter, new TPSBuffer(SecureChannel.R_MACDerivationConstant),
+ connId, getSelectedTokenType());
+
+ TPSBuffer rmacSessionKeyWrappedSCP02 = respRMac02.getSessionKey();
- drmDesKey = resp.getDRM_Trans_DesKey();
- keyCheck = resp.getKeyCheck();
- kekDesKey = resp.getKekWrappedDesKey();
+ rmacSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+ rmacSessionKeyWrappedSCP02.toBytesArray());
+
+ if (rmacSessionKeySCP02 == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't extract the SCP02 cmac session key!");
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't the cmac SCP02 session keys!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
- if (checkServerSideKeyGen(connId)) {
+ respDek02 = engine.computeSessionKeySCP02(keyDiversificationData, keyInfoData,
+ sequenceCounter, new TPSBuffer(SecureChannel.DEKDerivationConstant),
+ connId, getSelectedTokenType());
+
+ CMS.debug("Past engine.computeSessionKeyData: After dek key request.");
+
+ TPSBuffer dekSessionKeyWrappedSCP02 = respDek02.getSessionKey();
+
+ dekSessionKeySCP02 = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+ dekSessionKeyWrappedSCP02.toBytesArray());
+
+ if (dekSessionKeySCP02 == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't extract the SCP02 dek session key!");
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't the dek SCP02 session keys!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
- CMS.debug("TPSProcessor.generateSecureChannel: drmDesKey: " + drmDesKey + " kekDesKey : " + kekDesKey
- + " keyCheck: " + keyCheck);
- //ToDo handle server side keygen.
+ TPSBuffer drmDesKey = null;
+ TPSBuffer kekDesKey = null;
+ TPSBuffer keyCheck = null;
+ drmDesKey = respDek02.getDRM_Trans_DesKey();
+ kekDesKey = respDek02.getKekWrappedDesKey();
+ keyCheck = respDek02.getKeyCheck();
+
+ if (drmDesKey == null || kekDesKey == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't get drmDesKey or kekDesKey from TKS when processing the DEK session key!");
+ throw new TPSException(
+ "TPSProcessor.generateSecureChannel: Can't get drmDesKey or kekDesKey from TKS when processing the DEK session key!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ channel = new SecureChannel(this, encSessionKeySCP02, cmacSessionKeySCP02,
+ rmacSessionKeySCP02, dekSessionKeySCP02, drmDesKey, kekDesKey, keyCheck,
+ keyDiversificationData,
+ keyInfoData, sequenceCounter, hostChallenge, cardChallenge, cardCryptogram, platProtInfo);
+
+ channel.setDekSessionKeyWrapped(dekSessionKeyWrappedSCP02);
+
+ }
+
+ if (channel == null) {
+ throw new TPSException(
+ "TPSProcessor.generateSecureChannel: Can't create Secure Channel, possibly invalid secure channel protocol requested.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
}
- channel = new SecureChannel(this, sessionKey, encSessionKey, drmDesKey,
- kekDesKey, keyCheck, keyDiversificationData, cardChallenge,
- cardCryptogram, hostChallenge, hostCryptogram, keyInfoData);
return channel;
}
@@ -584,18 +773,12 @@ public class TPSProcessor {
}
protected void checkAndUpgradeApplet(AppletInfo appletInfo) throws TPSException, IOException {
- // TODO Auto-generated method stub
CMS.debug("checkAndUpgradeApplet: entering..");
- SecurityLevel securityLevel = SecurityLevel.SECURE_MSG_MAC;
-
- boolean useEncryption = checkUpdateAppletEncryption();
-
String tksConnId = getTKSConnectorID();
- if (useEncryption)
- securityLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
+ int upgraded = 0;
if (checkForAppletUpdateEnabled()) {
String targetAppletVersion = checkForAppletUpgrade("op." + currentTokenOperation);
@@ -608,18 +791,26 @@ public class TPSProcessor {
if (targetAppletVersion.compareTo(currentAppletVersion) != 0) {
+ upgraded = 1;
CMS.debug("TPSProcessor.checkAndUpgradeApplet: Upgrading applet to : " + targetAppletVersion);
- upgradeApplet("op." + currentTokenOperation, targetAppletVersion, securityLevel, getBeginMessage()
+ upgradeApplet("op." + currentTokenOperation, targetAppletVersion, getBeginMessage()
.getExtensions(),
tksConnId, 5, 12);
- } else {
- CMS.debug("TPSProcessor.checkAndUpgradeApplet: applet already at correct version.");
}
}
+ if (upgraded == 0) {
+ CMS.debug("TPSProcessor.checkAndUpgradeApplet: applet already at correct version or upgrade disabled.");
+
+ // We didn't need to upgrade the applet but create new channel for now.
+ selectCardManager();
+ setupSecureChannel();
+
+ }
+
}
- protected void upgradeApplet(String operation, String new_version, SecurityLevel securityLevel,
+ protected void upgradeApplet(String operation, String new_version,
Map<String, String> extensions, String connId, int startProgress, int endProgress) throws IOException,
TPSException {
@@ -659,17 +850,16 @@ public class TPSProcessor {
throw new TPSException("TPSProcessor.upgradeApplet: Can't selelect the card manager!");
}
- SecureChannel channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, securityLevel, connId);
+ SecureChannel channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, connId);
channel.externalAuthenticate();
+
channel.deleteFileX(netkeyAIDBuff);
channel.deleteFileX(netkeyPAIDBuff);
// Next step will be to load the applet file to token.
- TPSBuffer empty = new TPSBuffer();
-
- channel.installLoad(netkeyPAIDBuff, empty, appletData.length);
+ channel.installLoad(netkeyPAIDBuff, cardMgrAIDBuff, appletData.length);
TPSBuffer appletDataBuff = new TPSBuffer(appletData);
@@ -691,6 +881,7 @@ public class TPSProcessor {
public void selectCoolKeyApplet() throws TPSException, IOException {
+ CMS.debug("In selectCoolKeyApplet!");
TPSBuffer netkeyAIDBuff = getNetkeyAID();
APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, netkeyAIDBuff);
@@ -806,7 +997,6 @@ public class TPSProcessor {
return authInst;
}
-
public void processAuthentication(String op, TPSAuthenticator userAuth, String cuid, TokenRecord tokenRecord)
throws EBaseException, TPSException, IOException {
IAuthCredentials userCred;
@@ -1394,13 +1584,13 @@ public class TPSProcessor {
if (vals != null) {
for (String val : vals) {
CMS.debug(method + ": retrieved certsToDelete:" + val);
-
+
// Each cert is represented as
// (serial#, caID, revokeOnDelete)
// e.g.
// (234, ca1, true)
// note: number above is in decimal
-
+
String[] items = val.split(",");
ExternalRegCertToDelete erCert =
new ExternalRegCertToDelete();
@@ -1674,11 +1864,9 @@ public class TPSProcessor {
CMS.debug("TPSProcessor.format: appletVersion found: " + appletVersion + " requiredVersion: "
+ appletRequiredVersion);
- SecurityLevel secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
-
String tksConnId = getTKSConnectorID();
- upgradeApplet(TPSEngine.OP_FORMAT_PREFIX, appletRequiredVersion, secLevel,
+ upgradeApplet(TPSEngine.OP_FORMAT_PREFIX, appletRequiredVersion,
beginMsg.getExtensions(), tksConnId,
10, 90);
CMS.debug("TPSProcessor.format: Completed applet upgrade.");
@@ -1738,8 +1926,6 @@ public class TPSProcessor {
UnsupportedEncodingException {
if (checkIssuerInfoEnabled()) {
- SecurityLevel secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
-
String tksConnId = getTKSConnectorID();
int defKeyIndex = getChannelDefKeyIndex();
@@ -1751,7 +1937,7 @@ public class TPSProcessor {
channel = origChannel;
} else {
- channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, secLevel, tksConnId);
+ channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, tksConnId);
channel.externalAuthenticate();
}
@@ -1896,6 +2082,8 @@ public class TPSProcessor {
String profileConfig = "config.Profiles." + selectedTokenType + ".state";
String profileState = null;
+ CMS.debug("TPSProcessor.checkProfileStateOK: config value to check: " + profileConfig);
+
try {
profileState = configStore.getString(profileConfig, TPSEngine.CFG_ENABLED);
} catch (EBaseException e) {
@@ -2121,7 +2309,7 @@ public class TPSProcessor {
IConfigStore configStore = CMS.getConfigStore();
try {
- cardMgrAID = configStore.getString(TPSEngine.CFG_DEF_CARDMGR_INSTANCE_AID,
+ cardMgrAID = configStore.getString(TPSEngine.CFG_APPLET_CARDMGR_INSTANCE_AID,
TPSEngine.CFG_DEF_CARDMGR_INSTANCE_AID);
} catch (EBaseException e1) {
@@ -2520,7 +2708,6 @@ public class TPSProcessor {
try {
channel = setupSecureChannel((byte) requiredVersion, (byte) defKeyIndex,
- SecurityLevel.SECURE_MSG_MAC_ENC,
getTKSConnectorID());
} catch (TPSException e) {
@@ -2553,15 +2740,46 @@ public class TPSProcessor {
TPSBuffer curKeyInfo = channel.getKeyInfoData();
TPSEngine engine = getTPSEngine();
- TPSBuffer keySetData = engine.createKeySetData(newVersion, curKeyInfo,
- channel.getKeyDiversificationData(), connId);
+ int protocol = 1;
+ if (channel.isSCP02()) {
+ protocol = 2;
+ }
+
+ TPSBuffer keySetData = engine.createKeySetData(newVersion, curKeyInfo, protocol,
+ channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId);
CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: new keySetData from TKS: " + keySetData.toHexString());
byte curVersion = curKeyInfo.at(0);
byte curIndex = curKeyInfo.at(1);
- channel.putKeys(curVersion, curIndex, keySetData);
+ int done = 0;
+ if (done == 1)
+ throw new TPSException("TPSProcessor.checkAndUpgradeSymKeys: end of progress.");
+
+ try {
+ channel.putKeys(curVersion, curIndex, keySetData);
+ } catch (TPSException e) {
+
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: failed to put key, checking to see if this a SCP02 with 0xFF default key set.");
+
+ if (protocol == 2 && curVersion == (byte) 0xff) {
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: failed to put key, but we have SCP02 and the 0xFF dev key, try again.");
+
+ byte[] nv_dev = { (byte) 0x1, (byte) 0x1 };
+ TPSBuffer devKeySetData = engine.createKeySetData(new TPSBuffer(nv_dev), curKeyInfo, protocol,
+ channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId);
+
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: about to get rid of keyset 0xFF and replace it with keyset 0x1 with developer key set");
+ channel.putKeys((byte) 0x0, (byte) 0x1, devKeySetData);
+
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: We've only upgraded to the dev key set on key set #01, will have to try again to upgrade to #02");
+
+ } else {
+ throw e;
+ }
+
+ }
String curVersionStr = curKeyInfo.toHexString();
String newVersionStr = newVersion.toHexString();
@@ -2571,11 +2789,9 @@ public class TPSProcessor {
CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: curVersionStr: " + curVersionStr + " newVersionStr: "
+ newVersionStr);
-
selectCoolKeyApplet();
channel = setupSecureChannel((byte) requiredVersion, (byte) defKeyIndex,
- SecurityLevel.SECURE_MSG_MAC_ENC,
getTKSConnectorID());
} else {
@@ -2588,7 +2804,7 @@ public class TPSProcessor {
defKeyVersion = getChannelDefKeyVersion();
- channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, SecurityLevel.SECURE_MSG_MAC_ENC,
+ channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex,
getTKSConnectorID());
}
@@ -2878,6 +3094,146 @@ public class TPSProcessor {
}
}
+ public void acquireChannelPlatformAndProtocolInfo() throws TPSException, IOException {
+
+ if (platProtInfo == null) {
+ platProtInfo = new PlatformAndSecChannelProtoInfo();
+ } else { // We don't need this any more
+ return;
+ }
+
+ try {
+ gp211GetSecureChannelProtocolDetails();
+ } catch (TPSException e) {
+ CMS.debug("TPSProcessor.acquireChannelPlatformProtocolInfo: Error getting gp211 protocol data, assume scp01 "
+ + e);
+ platProtInfo.setPlatform(SecureChannel.GP201);
+ platProtInfo.setProtocol(SecureChannel.SECURE_PROTO_01);
+
+ }
+
+ if (platProtInfo.isGP211() && platProtInfo.isSCP02()) {
+ // We only support impl 15, the most common, at this point.
+
+ if (platProtInfo.getImplementation() != SecureChannel.GP211_SCP02_IMPL_15) {
+ throw new TPSException(
+ "SecureChannel.acquireChannelPlatformAndProtocolInfo card returning a non supported implementation for SCP02 "
+ + platProtInfo.getImplementation());
+ }
+ }
+
+ }
+
+ public void gp211GetSecureChannelProtocolDetails() throws TPSException, IOException {
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: Query card for secure channel protocol details for gp211.");
+
+ TPSBuffer data = null;
+ TPSBuffer keyData = null;
+
+ selectCardManager();
+ try {
+
+ data = getData(SecureChannel.GP211_GET_DATA_CARD_DATA);
+ keyData = getData(SecureChannel.GP211_GET_DATA_KEY_INFO);
+
+ } catch (TPSException e) {
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: Card can't understand GP211! " + e);
+
+ throw e;
+
+ }
+
+ if (data.size() < 5) {
+ throw new TPSException("TPSProcessor.gp211GetSecureChannelProtocolDetails: invalide return data.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: returned data: " + data.toHexString());
+
+ // Now process the GP211 data returned by the card.
+
+ int offset = 0;
+ int totalLength = 0;
+ int length = 0;
+
+ if (data.at(offset) == (byte) 0x66) {
+ offset++;
+
+ totalLength = data.getIntFrom1Byte(offset++);
+ offset++;
+
+ } else {
+ offset++;
+ totalLength = data.getIntFrom1Byte(offset++);
+
+ }
+
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: totalLength: " + totalLength);
+
+ if (totalLength == 0 || totalLength >= data.size()) {
+ throw new TPSException("TPSProcessor.gp211GetSecureChannelProtocolDetails: Invalid return data.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ offset++;
+
+ length = data.getIntFrom1Byte(offset++);
+
+ TPSBuffer oidCardRecognitionData = data.substr(offset, length);
+
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: oidCardRecognitionData: "
+ + oidCardRecognitionData.toHexString());
+
+ platProtInfo.setOidCardRecognitionData(oidCardRecognitionData);
+
+ offset += length + 2 + 1;
+
+ length = data.getIntFrom1Byte(offset++);
+
+ TPSBuffer oidCardManagementTypeAndVer = data.substr(offset, length);
+
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: oidCardManagementTypeAndVer: "
+ + oidCardManagementTypeAndVer.toHexString());
+
+ platProtInfo.setOidCardManagementTypeAndVer(oidCardManagementTypeAndVer);
+
+ offset += length + 2 + 1;
+
+ length = data.getIntFrom1Byte(offset++);
+
+ TPSBuffer oidCardIdentificationScheme = data.substr(offset, length);
+
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: oidCardIdentificationScheme: "
+ + oidCardIdentificationScheme.toHexString());
+
+ platProtInfo.setOidCardIdentificationScheme(oidCardIdentificationScheme);
+
+ offset += length + 2 + 1;
+
+ length = data.getIntFrom1Byte(offset++);
+
+ TPSBuffer oidSecureChannelProtocol = data.substr(offset, length);
+
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: oidSecureChannelProtocol: "
+ + oidSecureChannelProtocol.toHexString());
+
+ byte protocol = oidSecureChannelProtocol.at(length - 2);
+ byte implementation = oidSecureChannelProtocol.at(length - 1);
+
+ platProtInfo.setProtocol(protocol);
+ platProtInfo.setImplementation(implementation);
+ platProtInfo.setKeysetInfoData(keyData);
+ platProtInfo.setPlatform(SecureChannel.GP211);
+
+ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: protocol: " + protocol + " implementation: "
+ + implementation + " keyInfoData: " + keyData.toHexString());
+
+ }
+
+ public PlatformAndSecChannelProtoInfo getChannelPlatformAndProtocolInfo() {
+ return platProtInfo;
+ }
+
public static void main(String[] args) {
}