SSE4E

Home

GPError
GPSystem
ByteString
ByteBuffer
TLV
TLVList
Card
Atr
Key
Crypto
Application GPApplication GPSecDomain

ASN1
CardFile
IsoSecureChannel
ApplFactory
GPXML
JsScript
CardSim

X509
CRL
KeyStore
CMSSignedData
CMSGenerator
XMLSignature
OCSPQuery
LDAP
SOAP
URLConnection

PKCS11Provider
PKCS11Session
PKCS11Object

OutlineNode

OpenSCDP

IsoSecureChannel - Reference Documentation

Class to support a secure communication channel via secure messaging according to ISO 7816-4 and CWA 14890 (eSign-K).

This implementation supports 3-TDES and AES keys for MAC and encryption.

For 3-TDES keys the MAC algorithm is ISO 9797 Algorithm 3 (Retail-MAC or EMV-MAC), the encryption algorithm is DES-CBC.

For AES keys the MAC algorithm is AES-CMAC and the encryption algorithm is AES-CBC.

Three policies for handling send sequence counters are available:

SSC_DEFAULT_POLICY

If a send sequence counter for MAC is defined, then it is incremented for each new MAC and prepended to the protected message.

If a send sequence counter for encryption is defined, then it is incremented for each new cryptogram and used as initialisation vector.

SSC_SYNC_POLICY

If a send sequence counter for MAC is defined, then it is incremented for each new MAC and prepended to the protected message.

The same send sequence counter is used as initialisation vector for encrypted data (EAC 2.0 with 3-TDES).

SSC_SYNC_ENC_POLICY

If a send sequence counter for MAC is defined, then it is incremented for each new MAC and prepended to the protected message.

The same send sequence counter is encrypted and the result is used as initialisation vector for encrypted data.´This has the same effect as prepending the message to be encrypted with the SSC (EAC 2.0 with AES).

Index of Methods

Constants

TypeNameDescription
NumberSSC_DEFAULT_POLICYDefault SSC policy
NumberSSC_SYNC_POLICYSame send sequence counter for MAC and encryption
NumberSSC_SYNC_ENC_POLICYSame send sequence counter for MAC and encrypted SSC for encryption

Properties

TypeNameDescription
ByteStringencryptionSendSequenceCounterCurrent value of send sequence counter for encryption
ByteStringMACSendSequenceCounterCurrent value of send sequence counter for MAC calculation

Constructor

Prototype

IsoSecureChannel(Crypto crypto)

IsoSecureChannel(Crypto crypto, Number policy)

Description

Instantiate an IsoSecureChannel object that allows to wrap command-APDUs and unwrap response-APDUs using secure messaging as defined in ISO 7816-4 and CWA 14890 (eSign-K).

The object instantiated with this constructor must be further initialized using the setEncKey(), setMacKey() and setMACSendSequenceCounter() methods.

The class only supports 3DES/CBC and RetailMAC as cryptographic algorithms using a double or triple length DES key.

Objects of this class can be used in Card.setCredential() and CardFile.setCredential() as credential object.

Arguments

TypeNameDescription
CryptocryptoCrypto object to use for cryptographic operations
NumberpolicyOne of SSC_DEFAULT_POLICY, SSC_SYNC_POLICY or SSC_SYNC_ENC_POLICY

Exceptions

NameValueDescription
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call

Example


var crypto = new Crypto();
var isc = new IsoSecureChannel(crypto);

setEncKey()

Prototype

void setEncKey(Key kenc)

Description

Set the key to be used for encryption of command-APDUs and decryption of response-APDUs.

Arguments

TypeNameDescription
KeykencThe encryption key

Return

voidThe method does not return a value

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEArgument must be of type Key

Example


var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E4A1A6E570131D961", HEX);
var kenc = new Key();
kenc.setComponent(Key.DES, kencval);

isc.setEncKey(kenc);

setMacKey()

Prototype

void setMacKey(Key kmac)

Description

Set the key to be used for calculating and verifying the message authentication code (MAC).

Arguments

TypeNameDescription
KeykmacThe message authentication key

Return

voidThe method does not return a value

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEArgument must be of type Key

Example


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E579DC1376E7CA11045", HEX);
var kmac = new Key();
kmac.setComponent(Key.DES, kmacval);

isc.setMacKey(kmac);

setMACSendSequenceCounter()

Prototype

void setMACSendSequencCounter(ByteString ssc)

Description

Set the initial value for the send sequence counter using for message authentication codes.

If a send sequence counter is defined, then this counter will be incremented for each command or response APDU that contains a MAC.

The deprecated setSendSequenceCounter() maps to this method.

Arguments

TypeNameDescription
ByteStringsscThe initial value for the send sequence counter or null

Return

voidThe method does not return a value

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEThe argument must be of type ByteString

Example


var ssc = new ByteString("FFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);

setEncryptionSendSequenceCounter()

Prototype

void setEncryptionSendSequencCounter(ByteString ssc)

Description

Set the initial value for the send sequence counter used for encryption.

If a send sequence counter is defined, then this counter will be incremented for each command or response APDU that contains encrypted contents.

Arguments

TypeNameDescription
ByteStringsscThe initial value for the send sequence counter or null

Return

voidThe method does not return a value

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEThe argument must be of type ByteString

Example


// see setMACSendSequenceCounter() for an example.

setIV()

Prototype

void setIV(ByteString iv)

Description

Set the initial vector for DES/CBC encryption and decryption.

The default value used without using this method is '0000000000000000'.

Arguments

TypeNameDescription
ByteStringivThe initial vector or null

Return

voidThe method does not return a value

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEThe argument must be of type ByteString

Example


var iv = new ByteString("1111111111111111", HEX);
isc.setIV(iv);

setMacLength()

Prototype

void setMacLength(Number maclen)

Description

Set the length of the message authentication code as number of most significant bytes from the last cryptographic operation.

The default value is 8 byte.

Arguments

TypeNameDescription
NumbermaclenThe number of leftmost / most significant bytes to be used as MAC

Return

voidThe method does not return a value

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEThe argument must be of type ByteString

Example


isc.setMacLength(8);

wrap()

Prototype

ByteString wrap(ByteString apduToWrap, Number usageQualifier)

Description

Wrap a command-APDU with a secure messaging block.

Depending on the usageQualifier, no transformation (0), an encryption (Card.CENC), a MAC calculation (Card.CPRO) or both (Card.CENC|Card.CPRO) is performed.

The APDU is transformed as defined in ISO 7816-4 and CWA 14890 (eSignK).

Arguments

TypeNameDescription
ByteStringapduToWrapThe command APDU to wrap
NumberusageQualifierA bitwise combination of Card.CPRO and Card.CENC.

Return

ByteStringWrapped command APDU

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEThe type of the argument passed to the method is invalid
GPErrorGPError.INVALID_MECHThe cryptographic operating is not supported by the selected crypto service

Example


// #### Using 3-TDES with short APDUs ####

var ssc = new ByteString("FFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);

// Case 1 Command APDU CLA=00 INS=10 P1=20 P2=30
var apdu = new ByteString("00102030", HEX);

// Case 1 Plain 	-> CLA'|INS|P1|P2
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "08102030");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF6");



// Case 1 CENC  	-> CLA'|INS|P1|P2
var r = isc.wrap(apdu, Card.CENC);

// Test result
assert(r.toString(16) == "08102030");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF6");



// Case 1 CPRO		-> CLA'|INS|P1|P2|Lc'|TLmac
var r = isc.wrap(apdu, Card.CPRO);

// Test result
var exp = new ByteString("0C1020300A8E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFF70C10203080000000", HEX));
exp = exp.concat(mac);
assert(r.equals(exp));



// Case 1 CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLmac
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

// Test result
var exp = new ByteString("0C1020300A8E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFF80C10203080000000", HEX));
exp = exp.concat(mac);
assert(r.equals(exp));



// Case 2s Command APDU CLA=00 INS=10 P1=20 P2=30 Le=80
var apdu = new ByteString("0010203080", HEX);

// Case 2s Plain		-> CLA'|INS|P1|P2|Lc'|TLle|00
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "081020300396018000");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8");



// Case 2s CENC		-> CLA'|INS|P1|P2|Lc'|TLle|00
var r = isc.wrap(apdu, Card.CENC);

// Test result
assert(r.toString(16) == "081020300396018000");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8");



// Case 2s CPRO		-> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CPRO);

// Test result
var exp = new ByteString("0C1020300D9701808E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFF90C102030800000009701808000000000", HEX));
exp = exp.concat(mac).concat(new ByteString("00", HEX));
assert(r.equals(exp));



// Case 2s CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CPRO|Card.CENC);

// Test result
var exp = new ByteString("0C1020300D9701808E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFFA0C102030800000009701808000000000", HEX));
exp = exp.concat(mac).concat(new ByteString("00", HEX));
assert(r.equals(exp));



// Case 3s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344
var apdu = new ByteString("001020300441424344", HEX);

// Case 3s Plain		-> CLA'|INS|P1|P2|Lc'|TLplain
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "0810203006800441424344");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFA");



// Case 3s CENC		-> CLA'|INS|P1|P2|Lc'|TLenc
var r = isc.wrap(apdu, Card.CENC);

// Test result
var exp = new ByteString("081020300B860901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
assert(r.equals(exp));
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFB");



// Case 3s CPRO		-> CLA'|INS|P1|P2|Lc'|TLplain|TLmac
var r = isc.wrap(apdu, Card.CPRO);

// Test result
var exp = new ByteString("0C102030108104414243448E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFFC0C102030800000008104414243448000", HEX));
exp = exp.concat(mac);
assert(r.equals(exp));


// Case 3s CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLmac
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

// Test result
var exp = new ByteString("0C10203015870901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("8E08", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFD0C10203080000000870901", HEX);
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("8000000000", HEX));
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp);
exp = exp.concat(mac);
assert(r.equals(exp));



// Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80
var apdu = new ByteString("00102030044142434480", HEX);

// Case 4s Plain		-> CLA'|INS|P1|P2|Lc'|TLplain|TLle|00
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "081020300980044142434496018000");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFD");



// Case 4s CENC		-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|00
var r = isc.wrap(apdu, Card.CENC);

// Test result
var exp = new ByteString("081020300E860901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("96018000", HEX));
assert(r.equals(exp));
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFE");



// Case 4s CPRO		-> CLA'|INS|P1|P2|Lc'|TLplain|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CPRO);

// Test result
var exp = new ByteString("0C102030138104414243449701808E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFFF0C1020308000000081044142434497018080000000000000", HEX));
exp = exp.concat(mac).concat(new ByteString("00", HEX));
assert(r.equals(exp));



// Case 4s CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

// Test result
var exp = new ByteString("0C10203018870901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("9701808E08", HEX));
var macinp = new ByteString("00000000000000000C10203080000000870901", HEX);
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("970180", HEX));
macinp = macinp.concat(new ByteString("8000", HEX));
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp);
exp = exp.concat(mac).concat(new ByteString("00", HEX));
assert(r.equals(exp));


//#### Using 3-TDES with extended APDUs ####

var ssc = new ByteString("FFFFFFFFFFFFFFF8", HEX);
isc.setMACSendSequenceCounter(ssc);

//Case 2e Command APDU CLA=00 INS=10 P1=20 P2=30 Le=000180
var apdu = new ByteString("00102030000180", HEX);

// Case 2e Plain		-> CLA'|INS|P1|P2|Lc'|TLle|00
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "08102030000004960201800000");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8");



// Case 2e CENC		-> CLA'|INS|P1|P2|Lc'|TLle|00
var r = isc.wrap(apdu, Card.CENC);

// Test result
assert(r.toString(16) == "08102030000004960201800000");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8");



// Case 2e CPRO		-> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CPRO);

// Test result
var exp = new ByteString("0C10203000000E970201808E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFF90C102030800000009702018080000000", HEX));
exp = exp.concat(mac).concat(new ByteString("0000", HEX));
// print("Expected " + exp);
// print("Received " + r);
assert(r.equals(exp));



// Case 2e CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CPRO|Card.CENC);

// Test result
var exp = new ByteString("0C10203000000E970201808E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFFA0C102030800000009702018080000000", HEX));
exp = exp.concat(mac).concat(new ByteString("0000", HEX));
assert(r.equals(exp));



//Case 3e Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344
var apdu = new ByteString("0010203000000441424344", HEX);

// Case 3e Plain		-> CLA'|INS|P1|P2|Lc'|TLplain
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "08102030000006800441424344");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFA");



// Case 3e CENC		-> CLA'|INS|P1|P2|Lc'|TLenc
var r = isc.wrap(apdu, Card.CENC);

// Test result
var exp = new ByteString("0810203000000B860901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
assert(r.equals(exp));
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFB");



// Case 3e CPRO		-> CLA'|INS|P1|P2|Lc'|TLplain|TLmac
var r = isc.wrap(apdu, Card.CPRO);

// Test result
var exp = new ByteString("0C1020300000108104414243448E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFFC0C102030800000008104414243448000", HEX));
exp = exp.concat(mac);
assert(r.equals(exp));


// Case 3e CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLmac
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

// Test result
var exp = new ByteString("0C102030000015870901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("8E08", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFD0C10203080000000870901", HEX);
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("8000000000", HEX));
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp);
exp = exp.concat(mac);
assert(r.equals(exp));



//Case 4e Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=000004 Data=41424344 Le=000180
var apdu = new ByteString("00102030000004414243440180", HEX);

// Case 4e Plain		-> CLA'|INS|P1|P2|Lc'|TLplain|TLle|00
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "0810203000000A800441424344960201800000");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFD");



// Case 4e CENC		-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|00
var r = isc.wrap(apdu, Card.CENC);

// Test result
var exp = new ByteString("0810203000000F860901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("960201800000", HEX));
assert(r.equals(exp));
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFE");



// Case 4e CPRO		-> CLA'|INS|P1|P2|Lc'|TLplain|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CPRO);

// Test result
var exp = new ByteString("0C102030000014810441424344970201808E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFFF0C1020308000000081044142434497020180800000000000", HEX));
exp = exp.concat(mac).concat(new ByteString("0000", HEX));
assert(r.equals(exp));



// Case 4e CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

// Test result
var exp = new ByteString("0C102030000019870901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("970201808E08", HEX));
var macinp = new ByteString("00000000000000000C10203080000000870901", HEX);
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("97020180", HEX));
macinp = macinp.concat(new ByteString("80", HEX));
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp);
exp = exp.concat(mac).concat(new ByteString("0000", HEX));
assert(r.equals(exp));



// Special case: No MAC and no ENC
var ssc = new ByteString("FFFFFFFFFFFFFFF8", HEX);
isc.setMACSendSequenceCounter(ssc);

//Case 2e Command APDU CLA=00 INS=10 P1=20 P2=30 Le=000180
var apdu = new ByteString("00102030000000", HEX);

// Case 2e Plain		-> CLA'|INS|P1|P2|Lc'|TLle|00
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "08102030000004960200000000");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8");




// Using AES with SSC default policy

var isc = new IsoSecureChannel(crypto);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);

var iv = new ByteString("11111111111111111111111111111111", HEX);
isc.setIV(iv);

//Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80
var apdu = new ByteString("00102030044142434480", HEX);

//Case 4s CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

//Test result
var exp = new ByteString("0C10203020871101", HEX);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("41424344800000000000000000000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("9701808E08", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70C102030800000000000000000000000871101", HEX);
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("970180", HEX));
macinp = macinp.concat(new ByteString("80000000000000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
exp = exp.concat(mac.left(8)).concat(new ByteString("00", HEX));

// print("Expected " + exp);
// print("Received " + r);

assert(r.equals(exp));



// Using AES with SSC_SYNC_POLICY

var isc = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_POLICY);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);
var nextssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);

var iv = new ByteString("00000000000000000000000000000000", HEX);


//Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80
var apdu = new ByteString("00102030044142434480", HEX);

//Case 4s CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

//Test result
var exp = new ByteString("0C10203020871101", HEX);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("41424344800000000000000000000000", HEX), nextssc);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("9701808E08", HEX));

var macinp = nextssc.concat(new ByteString("0C102030800000000000000000000000871101", HEX));
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("970180", HEX));
macinp = macinp.concat(new ByteString("80000000000000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
exp = exp.concat(mac.left(8)).concat(new ByteString("00", HEX));

// print("Expected " + exp);
// print("Received " + r);

assert(r.equals(exp));


//Using AES with SSC_SYNC_POLICY

var isc = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_ENC_POLICY);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);
var nextssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);

var iv = new ByteString("00000000000000000000000000000000", HEX);


//Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80
var apdu = new ByteString("00102030044142434480", HEX);

//Case 4s CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

//Test result
var exp = new ByteString("0C10203020871101", HEX);
var niv = crypto.encrypt(kenc, Crypto.AES_CBC, nextssc, iv);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("41424344800000000000000000000000", HEX), niv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("9701808E08", HEX));

var macinp = nextssc.concat(new ByteString("0C102030800000000000000000000000871101", HEX));
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("970180", HEX));
macinp = macinp.concat(new ByteString("80000000000000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
exp = exp.concat(mac.left(8)).concat(new ByteString("00", HEX));

// print("Expected " + exp);
// print("Received " + r);

assert(r.equals(exp));



//Using AES with SSC default policy and odd instruction byte

var isc = new IsoSecureChannel(crypto);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);

var iv = new ByteString("11111111111111111111111111111111", HEX);
isc.setIV(iv);

//Case 4s Command APDU CLA=00 INS=11 P1=20 P2=30 Lc=04 Data=41424344 Le=80
var apdu = new ByteString("00112030048002123480", HEX);

//Case 4s CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

//Test result
var exp = new ByteString("0C1120301F8510", HEX);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("80021234800000000000000000000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("9701808E08", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70C1120308000000000000000000000008510", HEX);
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("970180", HEX));
macinp = macinp.concat(new ByteString("8000000000000000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
exp = exp.concat(mac.left(8)).concat(new ByteString("00", HEX));

print("Expected " + exp);
print("Received " + r);

assert(r.equals(exp));

unwrap()

Prototype

ByteString unwrap(ByteString apduToUnwrap, Number usageQualifier)

Description

Unwrap a response-APDU from a secure messaging block and check the encryption and MAC.

Depending on the usageQualifier, no transformation (0), an decryption (Card.RENC), a MAC verification (Card.RPRO) or both (Card.RENC|Card.RPRO) is performed.

The APDU is transformed as defined in ISO 7816-4 and CWA 14890 (eSignK).

Arguments

TypeNameDescription
ByteStringapduToUnwrapThe response APDU to unwrap
NumberusageQualifierA bitwise combination of Card.RPRO and Card.RENC.

Return

ByteStringUnwrapped response APDU

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEThe type of the argument passed to the method is invalid
GPErrorGPError.INVALID_MECHThe cryptographic operating is not supported by the selected crypto service
GPErrorGPError.CRYPTO_FAILEDEither the MAC verification or data block decryption failed

Example


var isc = new IsoSecureChannel(crypto);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E4A1A6E570131D961", HEX);
var kenc = new Key();
kenc.setComponent(Key.DES, kencval);
isc.setEncKey(kenc);

var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E579DC1376E7CA11045", HEX);
var kmac = new Key();
kmac.setComponent(Key.DES, kmacval);
isc.setMacKey(kmac);

var iv = new ByteString("1111111111111111", HEX);
isc.setIV(iv);

var ssc = new ByteString("0000000000000000", HEX);
isc.setMACSendSequenceCounter(ssc);

// SW1/SW2 only, Plain			-> SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("9000", HEX);

var r = isc.unwrap(apdu, 0);

// Test result
assert(r.toString(16) == "9000");



// SW1/SW2 only, RPRO			-> TLmac|SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("8E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("00000000000000018000000000000000", HEX));
apdu = apdu.concat(mac);
apdu = apdu.concat(new ByteString("9000", HEX));

var r = isc.unwrap(apdu, Card.RPRO);

// Test result
assert(r.toString(16) == "9000");



// SW1/SW2 only, RPRO with SW1SW2	-> TLsw|TLmac|SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("990212348E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("00000000000000029902123480000000", HEX));
apdu = apdu.concat(mac);
apdu = apdu.concat(new ByteString("9000", HEX));

var r = isc.unwrap(apdu, Card.RPRO);

// Test result
assert(r.toString(16) == "1234");



// Data | SW1/SW2, Plain		-> TLplain|SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("8004414243449000", HEX);

var r = isc.unwrap(apdu, 0);

// Test result
assert(r.toString(16) == "414243449000");



// Data | SW1/SW2, RENC			-> TLenc|SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("860901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
apdu = apdu.concat(enc);
apdu = apdu.concat(new ByteString("9000", HEX));

var r = isc.unwrap(apdu, Card.RENC);

// Test result
assert(r.toString(16) == "414243449000");
assert(isc.sendSequenceCounter.toString(16) == "0000000000000003");



// Data | SW1/SW2, RPRO			-> TLplain|TLmac|SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("810441424344", HEX);
var macinp = new ByteString("0000000000000004", HEX);
macinp = macinp.concat(apdu);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp.pad(Crypto.ISO9797_METHOD_2));
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac);
apdu = apdu.concat(new ByteString("9000", HEX));

var r = isc.unwrap(apdu, Card.RPRO);

// Test result
assert(r.toString(16) == "414243449000");



// Data | SW1/SW2, RPRO with SW1/SW2	-> TLplain|TLsw|TLmac|SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("81044142434499021234", HEX);
var macinp = new ByteString("0000000000000005", HEX);
macinp = macinp.concat(apdu);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp.pad(Crypto.ISO9797_METHOD_2));
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac);
apdu = apdu.concat(new ByteString("9000", HEX));

var r = isc.unwrap(apdu, Card.RPRO);

// Test result
assert(r.toString(16) == "414243441234");



// Data | SW1/SW2, RENC|RPRO		-> TLenc|TLmac|SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("870901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
apdu = apdu.concat(enc);
var macinp = new ByteString("0000000000000006", HEX);
macinp = macinp.concat(apdu);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp.pad(Crypto.ISO9797_METHOD_2));
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac);
apdu = apdu.concat(new ByteString("9000", HEX));

var r = isc.unwrap(apdu, Card.RPRO|Card.RENC);

// Test result
assert(r.toString(16) == "414243449000");



// Data | SW1/SW2, RENC|RPRO with SW1/SW2	-> TLenc|TLsw|TLmac|SW1/SW2
// Prepare response from ICC
var apdu = new ByteString("870901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
apdu = apdu.concat(enc);
apdu = apdu.concat(new ByteString("99021234", HEX));
var macinp = new ByteString("0000000000000007", HEX);
macinp = macinp.concat(apdu);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp.pad(Crypto.ISO9797_METHOD_2));
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac);
apdu = apdu.concat(new ByteString("9000", HEX));

var r = isc.unwrap(apdu, Card.RPRO|Card.RENC);

// Test result
assert(r.toString(16) == "414243441234");



// Using AES with default policy

var isc = new IsoSecureChannel(crypto);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);

var iv = new ByteString("11111111111111111111111111111111", HEX);
isc.setIV(iv);


//Data | SW1/SW2, RENC|RPRO with SW1/SW2	-> TLenc|TLsw|TLmac|SW1/SW2
//Prepare response from ICC
var apdu = new ByteString("871101", HEX);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("41424344800000000000000000000000", HEX), iv);
apdu = apdu.concat(enc);
apdu = apdu.concat(new ByteString("99021234", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);
macinp = macinp.concat(apdu);
macinp = macinp.concat(new ByteString("800000000000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac.left(8));
apdu = apdu.concat(new ByteString("9000", HEX));

// print("APDU " + apdu);
var r = isc.unwrap(apdu, Card.RPRO|Card.RENC);

// print("Received " + r);

//Test result
assert(r.toString(16) == "414243441234");



//Using AES with SSC_SYNC_POLICY

var isc = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_POLICY);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);
var nextssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);

var iv = new ByteString("00000000000000000000000000000000", HEX);


//Data | SW1/SW2, RENC|RPRO with SW1/SW2	-> TLenc|TLsw|TLmac|SW1/SW2
//Prepare response from ICC
var apdu = new ByteString("871101", HEX);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("41424344800000000000000000000000", HEX), nextssc);
apdu = apdu.concat(enc);
apdu = apdu.concat(new ByteString("99021234", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);
macinp = macinp.concat(apdu);
macinp = macinp.concat(new ByteString("800000000000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac.left(8));
apdu = apdu.concat(new ByteString("9000", HEX));

// print("APDU " + apdu);
var r = isc.unwrap(apdu, Card.RPRO|Card.RENC);

// print("Received " + r);

//Test result
assert(r.toString(16) == "414243441234");



//Using AES with SSC_SYNC_ENC_POLICY

var isc = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_ENC_POLICY);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);
var nextssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);

var iv = new ByteString("00000000000000000000000000000000", HEX);


//Data | SW1/SW2, RENC|RPRO with SW1/SW2	-> TLenc|TLsw|TLmac|SW1/SW2
//Prepare response from ICC
var apdu = new ByteString("871101", HEX);
var niv = crypto.encrypt(kenc, Crypto.AES_CBC, nextssc, iv);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("41424344800000000000000000000000", HEX), niv);
apdu = apdu.concat(enc);
apdu = apdu.concat(new ByteString("99021234", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);
macinp = macinp.concat(apdu);
macinp = macinp.concat(new ByteString("800000000000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac.left(8));
apdu = apdu.concat(new ByteString("9000", HEX));

// print("APDU " + apdu);
var r = isc.unwrap(apdu, Card.RPRO|Card.RENC);

// print("Received " + r);

//Test result
assert(r.toString(16) == "414243441234");



//Using AES with default policy and TLV data

var isc = new IsoSecureChannel(crypto);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);

var iv = new ByteString("11111111111111111111111111111111", HEX);
isc.setIV(iv);


//Data | SW1/SW2, RENC|RPRO with SW1/SW2	-> TLenc|TLsw|TLmac|SW1/SW2
//Prepare response from ICC
var apdu = new ByteString("8510", HEX);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("80021234800000000000000000000000", HEX), iv);
apdu = apdu.concat(enc);
apdu = apdu.concat(new ByteString("99021234", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);
macinp = macinp.concat(apdu);
macinp = macinp.concat(new ByteString("80000000000000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac.left(8));
apdu = apdu.concat(new ByteString("9000", HEX));

print("APDU " + apdu);
var r = isc.unwrap(apdu, Card.RPRO|Card.RENC);

print("Received " + r);

//Test result
assert(r.toString(16) == "800212341234");



//Using AES with default policy and plain data

var isc = new IsoSecureChannel(crypto);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX);
var kenc = new Key();
kenc.setComponent(Key.AES, kencval);

isc.setEncKey(kenc);


var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX);
var kmac = new Key();
kmac.setComponent(Key.AES, kmacval);

isc.setMacKey(kmac);

var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX);
isc.setMACSendSequenceCounter(ssc);

var iv = new ByteString("11111111111111111111111111111111", HEX);
isc.setIV(iv);


//Data | SW1/SW2, RENC|RPRO with SW1/SW2	-> TLenc|TLsw|TLmac|SW1/SW2
//Prepare response from ICC
var apdu = new ByteString("B304", HEX);
var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("80021234800000000000000000000000", HEX), iv);
apdu = apdu.concat(new ByteString("80021234", HEX));
apdu = apdu.concat(new ByteString("99021234", HEX));
var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX);
macinp = macinp.concat(apdu);
macinp = macinp.concat(new ByteString("800000000000", HEX));
var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp);
apdu = apdu.concat(new ByteString("8E08", HEX));
apdu = apdu.concat(mac.left(8));
apdu = apdu.concat(new ByteString("9000", HEX));

print("APDU " + apdu);
var r = isc.unwrap(apdu, Card.RPRO);

print("Received " + r);

//Test result
assert(r.toString(16) == "800212341234");



setCRT()

Prototype

void setCRT(ByteString crt)

Description

Set a cryptographic reference template to be included in the body of the command APDU.

The CRT is included in the MAC if the tag is odd.

Arguments

TypeNameDescription
ByteStringcrtThe cryptographic reference template or null

Return

voidThe method does not return a value

Exceptions

NameValueDescription
GPErrorGPError.ARGUMENTS_MISSINGToo few arguments in call
GPErrorGPError.INVALID_ARGUMENTSToo many arguments in call
GPErrorGPError.INVALID_TYPEThe argument must be of type ByteString

Example


var isc = new IsoSecureChannel(crypto);

var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E4A1A6E570131D961", HEX);
var kenc = new Key();
kenc.setComponent(Key.DES, kencval);
isc.setEncKey(kenc);

var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E579DC1376E7CA11045", HEX);
var kmac = new Key();
kmac.setComponent(Key.DES, kmacval);
isc.setMacKey(kmac);

var iv = new ByteString("1111111111111111", HEX);
isc.setIV(iv);

var crt = new ByteString("B803830103", HEX);
isc.setCRT(crt);

var ssc = new ByteString("FFFFFFFFFFFFFFFD", HEX);
isc.setMACSendSequenceCounter(ssc);

//Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80
var apdu = new ByteString("00102030044142434480", HEX);

// Case 4s Plain		-> CLA'|INS|P1|P2|Lc'|TLplain|TLle|00
var r = isc.wrap(apdu, 0);

// Test result
assert(r.toString(16) == "081020300EB80383010380044142434496018000");
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFD");



// Case 4s CENC		-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|00
var r = isc.wrap(apdu, Card.CENC);

// Test result
var exp = new ByteString("0810203013B803830103860901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("96018000", HEX));
assert(r.equals(exp));
assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFE");



// Case 4s CPRO		-> CLA'|INS|P1|P2|Lc'|TLplain|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CPRO);

// Test result
var exp = new ByteString("0C10203018B8038301038104414243449701808E08", HEX);
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString("FFFFFFFFFFFFFFFF0C1020308000000081044142434497018080000000000000", HEX));
exp = exp.concat(mac).concat(new ByteString("00", HEX));
assert(r.equals(exp));


var crt = new ByteString("B903830103", HEX);
isc.setCRT(crt);

// Case 4s CENC|CPRO	-> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00
var r = isc.wrap(apdu, Card.CENC|Card.CPRO);

// Test result
var exp = new ByteString("0C1020301DB903830103870901", HEX);
var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv);
exp = exp.concat(enc);
exp = exp.concat(new ByteString("9701808E08", HEX));
var macinp = new ByteString("00000000000000000C10203080000000B903830103870901", HEX);
macinp = macinp.concat(enc);
macinp = macinp.concat(new ByteString("970180", HEX));
macinp = macinp.concat(new ByteString("8000000000", HEX));
var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp);
exp = exp.concat(mac).concat(new ByteString("00", HEX));

// print("Expected " + exp);
// print("Received " + r);

assert(r.equals(exp));