# Smart Card Shell

- - Home
- - GPError
  - GPSystem
  - ByteString
  - ByteBuffer
  - TLV
  - TLVList
  - Card
  - Atr
  - Key
  - Crypto
  - Application
  - GPApplication
  - GPSecDomain
- - ASN1
  - CardFile
  - IsoSecureChannel
  - ApplFactory
  - GPXML
  - JsScript
  - CardSim
- - X509
  - CRL
  - KeyStore
  - Signed CMS
  - Enveloped CMS
  - CMS Generator
  - XMLSignature
  - SSS
  - OCSPQuery
  - LDAP
  - SOAP
  - URLConnection
- - PKCS11Provider
  - PKCS11Session
  - PKCS11Object
- - OutlineNode
  - Dialog
  - Task
- - Tools
  - Modules
- - 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

- IsoSecureChannel() constructor
- setEncKey()
- setMacKey()
- setMACSendSequenceCounter()
- setEncryptionSendSequenceCounter()
- setIV()
- setMacLength()
- wrap()
- unwrap()
- setCRT()

## Constants

Type | Name | Description
--- | --- | ---
Number | SSC_DEFAULT_POLICY | Default SSC policy
Number | SSC_SYNC_POLICY | Same send sequence counter for MAC and encryption
Number | SSC_SYNC_ENC_POLICY | Same send sequence counter for MAC and encrypted SSC for encryption

## Properties

Type | Name | Description
--- | --- | ---
ByteString | encryptionSendSequenceCounter | Current value of send sequence counter for encryption
ByteString | MACSendSequenceCounter | Current 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

Type | Name | Description
--- | --- | ---
`Crypto` | crypto | Crypto object to use for cryptographic operations
`Number` | policy | One of SSC_DEFAULT_POLICY, SSC_SYNC_POLICY or SSC_SYNC_ENC_POLICY

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.INVALID_ARGUMENTS | Too 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

Type | Name | Description
--- | --- | ---
`Key` | kenc | The encryption key

### Return

`void` | The method does not return a value

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | Argument 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

Type | Name | Description
--- | --- | ---
`Key` | kmac | The message authentication key

### Return

`void` | The method does not return a value

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | Argument 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

Type | Name | Description
--- | --- | ---
`ByteString` | ssc | The initial value for the send sequence counter or null

### Return

`void` | The method does not return a value

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | The 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

Type | Name | Description
--- | --- | ---
`ByteString` | ssc | The initial value for the send sequence counter or null

### Return

`void` | The method does not return a value

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | The 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

Type | Name | Description
--- | --- | ---
`ByteString` | iv | The initial vector or null

### Return

`void` | The method does not return a value

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | The 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

Type | Name | Description
--- | --- | ---
`Number` | maclen | The number of leftmost / most significant bytes to be used as MAC

### Return

`void` | The method does not return a value

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | The 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

Type | Name | Description
--- | --- | ---
`ByteString` | apduToWrap | The command APDU to wrap
`Number` | usageQualifier | A bitwise combination of Card.CPRO and Card.CENC.

### Return

`ByteString` | Wrapped command APDU

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | The type of the argument passed to the method is invalid
GPError | GPError.INVALID_MECH | The 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(
                "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70C" +
    			"102030800000000000000000000000871101", 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(
                "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70C" +
                "1120308000000000000000000000008510", 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

Type | Name | Description
--- | --- | ---
`ByteString` | apduToUnwrap | The response APDU to unwrap
`Number` | usageQualifier | A bitwise combination of Card.RPRO and Card.RENC.

### Return

`ByteString` | Unwrapped response APDU

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | The type of the argument passed to the method is invalid
GPError | GPError.INVALID_MECH | The cryptographic operating is not supported by the selected crypto service
GPError | GPError.CRYPTO_FAILED | Either the MAC verification or data block decryption failed

### Example

    var isc = new IsoSecureChannel(crypto);

    var kencval = new ByteString("7CA110454A1A6E570131D961" +
                                 "9DC1376E4A1A6E570131D961", HEX);
    var kenc = new Key();
    kenc.setComponent(Key.DES, kencval);
    isc.setEncKey(kenc);

    var kmacval = new ByteString("0131D9619DC1376E7CA11045" +
                                 "4A1A6E579DC1376E7CA11045", 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

Type | Name | Description
--- | --- | ---
`ByteString` | crt | The cryptographic reference template or null

### Return

`void` | The method does not return a value

### Exceptions

Name | Value | Description
--- | --- | ---
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call
GPError | GPError.INVALID_TYPE | The argument must be of type ByteString

### Example

    var isc = new IsoSecureChannel(crypto);

    var kencval = new ByteString("7CA110454A1A6E570131D961" +
                                 "9DC1376E4A1A6E570131D961", HEX);
    var kenc = new Key();
    kenc.setComponent(Key.DES, kencval);
    isc.setEncKey(kenc);

    var kmacval = new ByteString("0131D9619DC1376E7CA11045" +
                                 "4A1A6E579DC1376E7CA11045", 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(
                "FFFFFFFFFFFFFFFF0C10203080000000" +
                "81044142434497018080000000000000", 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));

© Copyright 2003 - 2026 CardContact Systems GmbH , Minden, Germany