diff options
author | Jack Magne <jmagne@redhat.com> | 2014-10-13 13:40:59 -0700 |
---|---|---|
committer | Jack Magne <jmagne@redhat.com> | 2015-02-27 18:44:07 -0800 |
commit | f39e3387f8a671ef97a08d1c0c3e4b2b6fd65ad3 (patch) | |
tree | 256bd8cca169f87c99c8ef6874b173bed3f1db4e /base/tps/src/org | |
parent | 7b1d897ba4cf9de1459d2aad37e969ce9a93a05a (diff) | |
download | pki-f39e3387f8a671ef97a08d1c0c3e4b2b6fd65ad3.tar.gz pki-f39e3387f8a671ef97a08d1c0c3e4b2b6fd65ad3.tar.xz pki-f39e3387f8a671ef97a08d1c0c3e4b2b6fd65ad3.zip |
Ticket: TPS Rewrite: Implement Secure Channel Protocol 02 (#883).
First cut of gp211 and scp protocol 02 for tokens.
Allow token operations using a GP211 token over secure channel protocol 02.
This patch supports the following:
1. Token operations with a GP211 card and SCP02 protocol, implementation 15.
2. Token still supports GP201 cards with SCP01.
3. SCP02 tested with SC650 gp211/scp02 card.
Things still to do:
1. Right now the SCP02 support has been tested with the current gp201 applet and
enrollment and formatting works just fine. We need to modify and compile the applet
against the GP211 spec and retest to see if any further changes are needed.
2. The nistSP800 key derivation stuff is not completed for the SCP02 protocol. Some
of the routines are self contained vs similar SCP01 ones. We have another ticket to
complete the nistSP800 support from end to end. This work will be done for that ticket.
3. One of the new scp02 deriviation functions can make use of a new NSS derive mechanism.
As of now this work is done by simple encryption, this can be done later.
4. The security APDU level of "RMAC" is not supported because the card does not support it.
It could have been done to the spec, but it having the card to test is more convenient and there
were more crucial issues to this point.
Diffstat (limited to 'base/tps/src/org')
6 files changed, 1268 insertions, 147 deletions
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) { } |