diff options
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, ¶m); + 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, ¶msItem, 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, ¶msItem, 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, ¶msItem, 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, ¶msItem, CKA_ENCRYPT, CKA_DERIVE, 16); + macKey16 = PK11_Derive(new_mac_key, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, 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) { } |
