/**
 *  ---------
 * |.##> <##.|  SmartCard-HSM Support Scripts
 * |#       #|
 * |#       #|  Copyright (c) 2011-2012 CardContact Software & System Consulting
 * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
 *  ---------
 *
 * Consult your license package for usage terms and conditions.
 *
 * @fileoverview Initializer for JCOP4 cards
 */

var File = require("scsh/file/File").File;
var SCPAuthenticator = require("scsh/perso/SCPAuthenticator").SCPAuthenticator;



function JCOP4Initializer(job) {
	this.job = job;
	this.jcopkeys = JCOPKeys.JCOP4;

	this.authenticator = new SCPAuthenticator(CustomerKeys[job.Keys]);

	this.aid = new ByteString("A000000151000000", HEX);

	this.af = new ApplicationFactory(new Crypto());

	var f = new File("profiles");
	var l = f.list();
	for (var i = 0; i < l.length; i++) {
		if (l[i].search(/^ap_jcop.*$/) == 0) {
			var name = l[i];
			print("Loading profile " + name);
			this.af.addApplicationProfile("profiles/" + name);
		}
	}
}

exports.JCOP4Initializer = JCOP4Initializer;

JCOP4Initializer.type = "initializer";



JCOP4Initializer.prototype.determineConfigId = function(card) {
	var iddata = card.sendApdu(0x80, 0xCA, 0x00, 0xFE, new ByteString("DF28", HEX), 0);

	if (card.SW != 0x9000) {
		return;
	}

	print("IDENTIFY returns:");
	print(iddata);

	var a = new ASN1(0x30, (new ASN1(iddata)).get(0).value);
	var a = new ASN1(a.getBytes());

	var epromid = a.find(0x01).value;
	print("EEPROM ID          " + epromid.toString(HEX));
	var configid = epromid.bytes(1,3).toString(HEX);
	print("  Configuration ID " + configid);
	var backgroundid = epromid.bytes(4,8);
	print("  Background ID    " + backgroundid.toString(HEX));
	print("Patch ID           " + a.find(0x02).value.toString(HEX));
	var pbid = a.find(0x03).value;
	print("Platform build ID  " + pbid.bytes(0, 16).toString(ASCII) + "-" + pbid.bytes(16, 8).toString(HEX));
	print("FIPS Mode          " + a.find(0x05).value.toString(HEX));
	print("Pre-perso state    " + a.find(0x07).value.toString(HEX));
	print("ROM ID             " + a.find(0x08).value.toString(HEX));

	return configid;
}



JCOP4Initializer.prototype.determineKeyVersion = function(card) {
	card.sendApdu(0x00, 0xA4, 0x04, 0x00, this.aid, [0x9000, 0x6D00]);

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

	if (card.SW == 0x6982) {
		return 0xFF;
	}

	var kid = kit.byteAt(3);
	print("ISD Key Version    " + kid);
	return kid;
}



JCOP4Initializer.prototype.handleCard = function(card) {

	card.reset(Card.RESET_COLD);
	this.configid = this.determineConfigId(card);
	var kid = this.determineKeyVersion(card);

	if (typeof(this.job.RequiredKID) == "object") {
		if (this.job.RequiredKID.indexOf(kid) < 0) {
			throw new Error("KID does not match requirement");
		}
	}

	var jkeys = this.jcopkeys[this.configid];

	if (kid == 255) {
		if (typeof(jkeys) == "undefined") {
			throw new Error("Configuration id " + configid + " not found. Entry in keys.js missing ?");
		}

		this.authenticator.transportKeys = jkeys.transportKey;
	}

	var data = {
		applAid: new ByteString("E82B0601040181C31F0201", HEX)
	};

	var dm = {
		get: function(name, fixed, length, encoding) {
			if (typeof(data[name]) == "undefined") {
				return null;
			}

			return data[name];
		}
	}

	var appl = this.af.getApplicationInstance(dm, this.aid, card, this.job.Profile);
	appl.keyProvider = this.authenticator;

	for (var i = 0; i < this.job.Steps.length; i++) {
		var e = this.job.Steps[i];
		if (typeof(e) == "string") {
			appl.run(this.job.Steps[i]);
		} else {
			data = e.data;
			appl.run(e.step);
		}
	}

	return "OK";
}



JCOP4Initializer.prototype.configure = function() {
}
