<?xml version="1.0" encoding="UTF-8"?>
<gp:ApplicationProfile xmlns="http://namespaces.globalplatform.org/systems-profiles/1.1.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://namespaces.globalplatform.org/systems-profiles/1.1.0 http://namespaces.globalplatform.org/systems-profiles/1.1.0/GP.systems.profiles.1.1.0.ApplicationProfile.xsd"
	xmlns:gp="http://namespaces.globalplatform.org/systems-profiles/1.1.0"
	xmlns:scdp="http://www.openscdp.org/namespaces/gp/systems-profiles/1.0.0"
	UniqueID="2B0601040181C31F10050201" ProfileVersion="1.0.0">
	<gp:Description>JCOP Card Manager Application Profile</gp:Description>
	<gp:Revisions arrayElement="Revision" arrayIndex="#">
		<gp:Revision Version="1.0.0" Date="2006-07-24" Time="12:00:00" By="www.CardContact.de" Digest=""></gp:Revision>
	</gp:Revisions>
	<gp:ConflictRules arrayElement="" arrayIndex=""></gp:ConflictRules>
	<gp:ApplicationInfo Version="1.0.0" Type="GP" Subtype="CM" Owner="GP" Developer="CardContact" Provider="GP" Domain="GP" VolatileDataSpaceMin="1000" NonVolatileDataSpaceMin="2000">
		<gp:Privileges/>
		<gp:LifeCycles arrayElement="LifeCycle" arrayIndex="#">
			<gp:LifeCycle Name=""/>
			<gp:LifeCycle Name=""/>
			<gp:LifeCycle Name=""/>
		</gp:LifeCycles>
	</gp:ApplicationInfo>

	<gp:DataElement Name="loadFileName" External="true" Type="ByteString" Encoding="ASCII"/>
	<gp:DataElement Name="loadFileAid" External="true" Type="ByteString"/>
	<gp:DataElement Name="moduleAid" External="true" Type="ByteString"/>
	<gp:DataElement Name="applAid" External="true" Type="ByteString"/>
	<gp:DataElement Name="applPrivileges" External="true" Type="ByteString"/>
	<gp:DataElement Name="installParam" External="true" Type="ByteString"/>

	<gp:Function Name="encryptDESkey" Param="dek, key">
		<gp:Description />
		<gp:Script><![CDATA[

			// Determine KCV, encrypt and encode key for PUT KEY command

			var zeros = new ByteString("0000000000000000", HEX);
			var kcv = this.crypto.encrypt(key, Crypto.DES_ECB, zeros).left(3);

			var ck = this.crypto.encrypt(dek, Crypto.DES_ECB, key.getComponent(Key.DES));
			var ckbin = (new ByteString("8010", HEX)).concat(ck);
			ckbin = ckbin.concat(new ByteString("03", HEX));
			ckbin = ckbin.concat(kcv);

			return ckbin;

		]]></gp:Script>

	</gp:Function>

	<gp:Function Name="encryptAESkey" Param="dek, key">
		<gp:Description />
		<gp:Script><![CDATA[

			var kv = dek.getComponent(Key.DES);
			if (kv) {
				print("Rewrite DES key " + kv + " to AES");
				var dek = new Key();
				dek.setComponent(Key.AES, kv);
			}

			var kv = key.getComponent(Key.DES);
			if (kv) {
				print("Rewrite DES key " + kv + " to AES");
				var key = new Key();
				key.setComponent(Key.AES, kv);
			}

			assert(dek instanceof Key, "Argument dek must be instance of Key");
			assert(key instanceof Key, "Argument key must be instance of Key");

			var keysize = key.getSize() >> 3;
			var ones = new ByteString("01010101010101010101010101010101", HEX);
			var kcv = this.crypto.encrypt(key, Crypto.AES_ECB, ones).left(3);

			var iv = ByteString.valueOf(0, 16);
			var ck = this.crypto.encrypt(dek, Crypto.AES_CBC, key.getComponent(Key.AES), iv);
			var ckbin = new ByteBuffer("88", HEX);
			ckbin.append(keysize + 1);
			ckbin.append(keysize);
			ckbin.append(ck);
			ckbin.append(3);
			ckbin.append(kcv);

			return ckbin.toByteString();
		]]></gp:Script>

	</gp:Function>

	<gp:ScriptFragment Name="TEST" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("TEST script started");

			this.select();
			this.openSecureChannel(3);		// 00-Plain, 01-Mac, 03-Mac+Enc

			]]></gp:Script>
	</gp:ScriptFragment>

    <gp:ScriptFragment Name="SETKST" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("SETKST script started");

			this.select();

			this.openSecureChannel(3);		// 00-Plain, 01-Mac, 03-Mac+Enc

			var kit = this.sendApdu(0x00, 0xCA, 0x00, 0xE0, 0, [0x9000, 0x6982]);

			if (this.card.SW == 0x9000) {
				var kid = kit.byteAt(3);
			} else {
				var kid = 255;
			}
			GPSystem.trace("ISD Key Version    " + kid);

			var scp = this.secureChannel instanceof GPScp02 ? 2 : 3;
			var keyset = this.keyProvider.getGPScpKeySet(scp, 1, kid == 1);

			// Encrypt card keys and add KCV
			if (scp == 2) {
				var ckbinenc = this.encryptDESkey(this.secureChannel.getDekKey(), keyset.getEncKey());
				var ckbinmac = this.encryptDESkey(this.secureChannel.getDekKey(), keyset.getMacKey());
				var ckbindek = this.encryptDESkey(this.secureChannel.getDekKey(), keyset.getDekKey());
			} else {
				var ckbinenc = this.encryptAESkey(this.secureChannel.getDekKey(), keyset.getEncKey());
				var ckbinmac = this.encryptAESkey(this.secureChannel.getDekKey(), keyset.getMacKey());
				var ckbindek = this.encryptAESkey(this.secureChannel.getDekKey(), keyset.getDekKey());
			}

			var cdata = new ByteString("01", HEX);
			cdata = cdata.concat(ckbinenc).concat(ckbinmac).concat(ckbindek);

			var p1 = kid == 255 ? 0 : kid;
			this.sendApdu(0x80, 0xD8, p1, 0x81, cdata, [0x9000]);
		]]></gp:Script>
	</gp:ScriptFragment>

	<gp:ScriptFragment Name="LOAD" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("LOAD script started");
			this.card.reset(Card.RESET_COLD);

			assert(this instanceof GPSecurityDomain);
			this.select();

			this.openSecureChannel(3);		// 00-Plain, 01-Mac, 03-Mac+Enc

			GPSystem.trace("Delete old applet instance...");
			this.deleteAID(this.data.applAid, [0x9000, 0x6A88, 0x6A80] );

			GPSystem.trace("Delete old applet load file...");
			this.deleteAID(this.data.loadFileAid, [0x9000, 0x6A88, 0x6A80] );

			GPSystem.trace("InstallForLoad applet...");
			this.installForLoad(this.data.loadFileAid, this.aid, null, null, null);

			GPSystem.trace("Loading " + this.data.loadFileName.toString(ASCII) + "...");
			print("Loading " + this.data.loadFileName.toString(ASCII) + "...");
			this.loadByName(this.data.loadFileName);

			GPSystem.trace("Instantiating applet...");
			var applPrivileges = new ByteString("00", HEX);
			var installParam = new ByteString("C900", HEX);
			this.installForInstallAndSelectable(this.data.loadFileAid, this.data.moduleAid, this.data.applAid, this.data.applPrivileges, this.data.installParam, null);

			]]></gp:Script>
	</gp:ScriptFragment>

	<gp:ScriptFragment Name="LOADCAP" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("LOADCAP script started");

			this.select();
			this.openSecureChannel(3);		// 00-Plain, 01-Mac, 03-Mac+Enc

			GPSystem.trace("InstallForLoad applet...");
			this.installForLoad(this.data.loadFileAid, this.aid, null, null, null);

			GPSystem.trace("Requesting " + this.data.loadFileName.toString(ASCII) + "...");
			var fn = this.data.loadFileName.toString(ASCII);
			if (fn.indexOf("apps/persoserver/") == 0) {
				fn = "sc-hsm-persoserver/" + fn.substr(17);
			}

			print("Loading " + fn + "...");
			this.loadByName(fn);
			]]></gp:Script>
	</gp:ScriptFragment>

	<gp:ScriptFragment Name="LOADROM" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("LOADROM script started");

			this.select();
			this.openSecureChannel(1);		// 00-Plain, 01-Mac, 03-Mac+Enc

			GPSystem.trace("InstallForLoad applet from ROM...");
			this.installForLoad(this.data.loadFileAid, this.aid, null, this.data.installParam, null);
			]]></gp:Script>
	</gp:ScriptFragment>

	<gp:ScriptFragment Name="DELETECAP" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("DELETECAP script started");

			this.select();
			this.openSecureChannel(1);		// 00-Plain, 01-Mac, 03-Mac+Enc

			GPSystem.trace("Delete old applet instance...");
			this.deleteAID(this.data.applAid, [0x9000, 0x6A88, 0x6A80] );

			GPSystem.trace("Delete old applet load file...");
			this.deleteAID(this.data.loadFileAid, [0x9000, 0x6A88, 0x6A80] );
			]]></gp:Script>
	</gp:ScriptFragment>

	<gp:ScriptFragment Name="INSTANTIATE" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("INSTANTIATE script started");

			this.select();
			this.openSecureChannel(1);		// 00-Plain, 01-Mac, 03-Mac+Enc

			GPSystem.trace("Instantiating applet...");
			var applPrivileges = new ByteString("00", HEX);
			var installParam = new ByteString("C900", HEX);
			this.installForInstallAndSelectable(this.data.loadFileAid, this.data.moduleAid, this.data.applAid, this.data.applPrivileges, this.data.installParam, null);
			]]></gp:Script>
	</gp:ScriptFragment>

	<gp:ScriptFragment Name="DELETEINSTANCE" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("DELETEINSTANCE script started");

			this.select();
			this.openSecureChannel(1);		// 00-Plain, 01-Mac, 03-Mac+Enc

			GPSystem.trace("Delete old applet instance...");
			this.deleteAID(this.data.applAid, [0x9000, 0x6A88, 0x6A80] );
			]]></gp:Script>
	</gp:ScriptFragment>

	<gp:ScriptFragment Name="SECURED" StartLifeCycle="one" EndLifeCycle="two">
		<gp:Script><![CDATA[
			GPSystem.trace("SECURED script started");

			this.select();

			this.openSecureChannel(1);		// 00-Plain, 01-Mac, 03-Mac+Enc

			var rsp = this.sendApdu(0x80, 0xF2, 0x80, 0x00, [0x9000]);
			var lc = rsp.byteAt(rsp.byteAt(0) + 1);

			if (lc == 1) {
				GPSystem.trace("Setting life cycle to INITIALIZED...");
				this.sendApdu(0x80, 0xF0, 0x80, 0x07, [0x9000]);
				GPSystem.trace("Setting life cycle to SECURED...");
				this.sendApdu(0x80, 0xF0, 0x80, 0x0F, [0x9000]);
			}
			]]></gp:Script>
	</gp:ScriptFragment>
</gp:ApplicationProfile>

