/*
* ---------
* |.##> <##.| Open Smart Card Development Platform (www.openscdp.org)
* |# #|
* |# #| Copyright (c) 1999-2006 CardContact Software & System Consulting
* |'##> <##'| Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
* ---------
*
* This file is part of OpenSCDP.
*
* OpenSCDP is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* OpenSCDP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenSCDP; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Card-to-Card authentification between German HPC und eGK
*
*/
load("cvc.js");
//
// Perform a card to card mutual authentication between a German eGK and HPC
//
// The procedure involves 6 steps
// 1. Read ICCSN and card verifiable certificates (CVC) from eGK
// 2. Read ICCSN and card verifiable certificates (CVC) from HPC
// 3. Verify CVC chain from eGK in HPC
// 4. Verify CVC chain from HPC in eGK
// 5. Authenticate eGK against HPC
// 6. Authenticate HPC against eGK
//
// Prerequisite: The PIN must be verified on the HPC
//
function Card2CardAuthentication(card_HIC, card_HPC, rootpuk) {
// Step 1 - Read ICCSN.EGK, CVC.eGK.AUT and CVC.CA_eGK.CS from eGK
// Read ICCSN.EGK, construct ASN1 object and extract ICCSN
var ef_gdo = new CardFile(card_HIC, ":02");
var gdo = ef_gdo.readBinary();
var gdo_tlv = new ASN1(gdo);
// print(gdo_tlv);
var iccsn = gdo_tlv.value;
var iccsn_egk = iccsn;
print("ICCSN of eGK:");
print(iccsn_egk);
// Read CVC.CA_eGK.CS and construct ASN1 object
var ef_cvc_ca_egk = new CardFile(card_HIC, ":04");
var cvc_ca_egk_bin = ef_cvc_ca_egk.readBinary();
var cvc_ca_egk_tlv = new ASN1(cvc_ca_egk_bin);
print("CVC.CA_eGK.CS:");
// print(cvc_ca_egk_tlv);
var cvc_ca_egk = new CVC(cvc_ca_egk_bin);
cvc_ca_egk.verifyWithOneOf(rootpuk);
cvc_ca_egk.dump();
// Read CVC.eGK.AUT and construct ASN1 object
var ef_cvc_egk = new CardFile(card_HIC, ":03");
var cvc_egk_bin = ef_cvc_egk.readBinary();
var cvc_egk_tlv = new ASN1(cvc_egk_bin);
print("CVC.eGK.AUT:");
// print(cvc_egk_tlv);
var cvc_egk = new CVC(cvc_egk_bin);
cvc_egk.verifyWith(cvc_ca_egk.getPublicKey());
cvc_egk.dump();
// Step 2 - Read ICCSN.HPC, CVC.HPC.AUT and CVC.CA_HPC.CS from HPC
// Read ICCSN.HPC, construct ASN1 object and extract ICCSN
var ef_gdo = new CardFile(card_HPC, ":02");
var gdo = ef_gdo.readBinary();
var gdo_tlv = new ASN1(gdo);
// print(gdo_tlv);
var iccsn = gdo_tlv.value;
var iccsn_hpc = iccsn;
print("ICCSN of HPC");
print(iccsn_hpc);
// Read CVC.CA_HPC.CS and construct ASN1 object
var ef_cvc_ca_hpc = new CardFile(card_HPC, ":04");
var cvc_ca_hpc_bin = ef_cvc_ca_hpc.readBinary();
var cvc_ca_hpc_tlv = new ASN1(cvc_ca_hpc_bin);
print("CVC.CA_HPC.AUT:");
// print(cvc_ca_hpc_tlv);
var cvc_ca_hpc = new CVC(cvc_ca_hpc_bin);
cvc_ca_hpc.verifyWithOneOf(rootpuk);
cvc_ca_hpc.dump();
// Read CVC.HPC.AUT and construct ASN1 object
var ef_cvc_hpc = new CardFile(card_HPC, ":03");
var cvc_hpc_bin = ef_cvc_hpc.readBinary();
var cvc_hpc_tlv = new ASN1(cvc_hpc_bin);
print("CVC.HPC.AUT:");
// print(cvc_hpc_tlv);
var cvc_hpc = new CVC(cvc_hpc_bin);
cvc_hpc.verifyWith(cvc_ca_hpc.getPublicKey());
cvc_hpc.dump();
// Step 3 - Verify CVC chain from eGK in HPC
// Make PuK.eGK.AUT available in HPC
// Send MANAGE_SE to select root public key
// Create data body with tag '83' and the Certificate Authority Reference (CAR) from
// CVC.CA_eGK.CS
var do_tlv = new ASN1(0x83, cvc_ca_egk.getCertificationAuthorityReference());
print("Selecting key for certificate verification: " + do_tlv.getBytes());
card_HPC.sendApdu(0x00, 0x22, 0x81, 0xB6, do_tlv.getBytes(), [0x9000]);
// Send PSO:VERIFY_CERTIFICATE to verify cvc_ca_egk
// Create data body with concatenation of signature and public key remainder
var data = new ByteBuffer();
data.append(cvc_ca_egk_tlv.get(0).getBytes());
data.append(cvc_ca_egk_tlv.get(1).getBytes());
print("Sending PSO:VERIFY_CERTIFICATE(CVC.CA_eGK.CS) to HPC");
// print(data.toByteString());
card_HPC.sendApdu(0x00, 0x2A, 0x00, 0xAE, data.toByteString(), [0x9000]);
print("CVC.CA_eGK.CS verified.");
// Send MANAGE_SE to select public key of certification authority from CVC.CA_eGK.CS
// Create data body with tag '83' and the Certificate Authority Reference (CAR) from
// CVC.eGK.AUT
var do_tlv = new ASN1(0x83, cvc_egk.getCertificationAuthorityReference());
print("Selecting key for certificate verification: " + do_tlv.getBytes());
card_HPC.sendApdu(0x00, 0x22, 0x81, 0xB6, do_tlv.getBytes(), [0x9000]);
// Send PSO:VERIFY_CERTIFICATE to verify cvc_egk
// Create data body with concatenation of signature and public key remainder
var data = new ByteBuffer();
data.append(cvc_egk_tlv.get(0).getBytes());
data.append(cvc_egk_tlv.get(1).getBytes());
print("Sending PSO:VERIFY_CERTIFICATE(CVC.eGK.AUT) to HPC");
// print(data.toByteString());
card_HPC.sendApdu(0x00, 0x2A, 0x00, 0xAE, data.toByteString(), [0x9000]);
print("CVC.eGK.AUT verified.");
// Step 4 - Verify CVC chain from HPC in eGK
// Make PuK.HPC.AUT available in HIC
// Send MANAGE_SE to select root public key
// Create data body with tag '83' and the Certificate Authority Reference (CAR) from
// CVC.CA_HPC.CS
var do_tlv = new ASN1(0x83, cvc_ca_hpc.getCertificationAuthorityReference());
print("Selecting key for certificate verification: " + do_tlv.getBytes());
card_HIC.sendApdu(0x00, 0x22, 0x81, 0xB6, do_tlv.getBytes(), [0x9000]);
// Send PSO:VERIFY_CERTIFICATE to verify cvc_ca_hpc
// Create data body with concatenation of signature and public key remainder
var data = new ByteBuffer();
data.append(cvc_ca_hpc_tlv.get(0).getBytes());
data.append(cvc_ca_hpc_tlv.get(1).getBytes());
print("Sending PSO:VERIFY_CERTIFICATE(CVC.CA_HPC.CS) to eGK");
// print(data.toByteString());
card_HIC.sendApdu(0x00, 0x2A, 0x00, 0xAE, data.toByteString(), [0x9000]);
print("CVC.CA_HPC.CS verified.");
// Send MANAGE_SE to select public key of certification authority from CVC.CA_HPC.CS
// Create data body with tag '83' and the Certificate Authority Reference (CAR) from
// CVC.HPC.AUT
// var car = cvc_hpc_tlv.get(2).value;
// var car = new ByteString("44 45 44 54 58 11 01 08", HEX); // #### tmp !!!! DEDTX
// var prefix = new ByteString("00000000", HEX); // Siemens ?
// car = prefix.concat(car);
var do_tlv = new ASN1(0x83, cvc_hpc.getCertificationAuthorityReference());
print("Selecting key for certificate verification: " + do_tlv.getBytes());
card_HIC.sendApdu(0x00, 0x22, 0x81, 0xB6, do_tlv.getBytes(), [0x9000]);
// Send PSO:VERIFY_CERTIFICATE to verify cvc_hpc
// Create data body with concatenation of signature and public key remainder
var data = new ByteBuffer();
data.append(cvc_hpc_tlv.get(0).getBytes());
data.append(cvc_hpc_tlv.get(1).getBytes());
print("Sending PSO:VERIFY_CERTIFICATE(CVC.HPC.AUT) to eGK");
// print(data.toByteString());
card_HIC.sendApdu(0x00, 0x2A, 0x00, 0xAE, data.toByteString(), [0x9000]);
print("CVC.HPC.AUT verified.");
// Step 5 - Perform HIC to HPC authentification
// Send MANAGE_SE to key references for PuK.eGK.AUT
// Create data body with tag '83' and the key identifier
var data = new ByteBuffer();
data.append((new ASN1(0x83, cvc_egk.getCertificateHolderReference())).getBytes());
data.append((new ASN1(0x80, new ByteString("00", HEX))).getBytes());
print("Selecting key in HPC for eGK authentification: " + data.toByteString());
card_HPC.sendApdu(0x00, 0x22, 0x81, 0xA4, data.toByteString(), [0x9000]);
// Send MANAGE_SE to key references for PrK.eGK.AUT
// Create data body with tag '83' and the Certificate Authority Reference (CAR) from
// CVC.HPC.AUT
var data = new ByteBuffer();
data.append((new ASN1(0x84, new ByteString("10", HEX))).getBytes());
data.append((new ASN1(0x80, new ByteString("00", HEX))).getBytes());
print("Selecting key in eGK for HPC authentification: " + data.toByteString());
card_HIC.sendApdu(0x00, 0x22, 0x41, 0xA4, data.toByteString(), [0x9000]);
// GET_CHALLENGE from HPC
var challenge_hpc = card_HPC.sendApdu(0x00, 0x84, 0x00, 0x00, 0x08, [0x9000]);
print("Challenge from HPC = " + challenge_hpc);
// Do INTERNAL_AUTHENTICATE with HIC
var cryptograminput = challenge_hpc.concat(iccsn_hpc.bytes(2, 8));
var cryptogram_hic = card_HIC.sendApdu(0x00, 0x88, 0x00, 0x00, cryptograminput, 0x00, [0x9000]);
print("Cryptogram from HIC = " + cryptogram_hic);
// Do EXTERNAL_AUTHENTICATE with HPC
card_HPC.sendApdu(0x00, 0x82, 0x00, 0x00, cryptogram_hic, [0x9000]);
// Step 6 - Perform HPC to HIC authentification
// Send MANAGE_SE to key references for PuK.HPC.AUT
// Create data body with tag '83' and the key identifier
var data = new ByteBuffer();
data.append((new ASN1(0x83, cvc_hpc.getCertificateHolderReference())).getBytes());
data.append((new ASN1(0x80, new ByteString("00", HEX))).getBytes());
print("Selecting key in eGK for HPC authentification: " + data.toByteString());
card_HIC.sendApdu(0x00, 0x22, 0x81, 0xA4, data.toByteString(), [0x9000]);
// Send MANAGE_SE to key references for PrK.HPC.AUT
// Create data body with tag '83' and the Certificate Authority Reference (CAR) from
// CVC.HPC.AUT
var data = new ByteBuffer();
data.append((new ASN1(0x84, new ByteString("10", HEX))).getBytes());
data.append((new ASN1(0x80, new ByteString("00", HEX))).getBytes());
print("Selecting key in HPC for eGK authentification: " + data.toByteString());
card_HPC.sendApdu(0x00, 0x22, 0x41, 0xA4, data.toByteString(), [0x9000]);
// GET_CHALLENGE from HIC
var challenge_hic = card_HIC.sendApdu(0x00, 0x84, 0x00, 0x00, 0x08, [0x9000]);
print("Challenge from HIC = " + challenge_hic);
// Do INTERNAL_AUTHENTICATE with HPC
var cryptograminput = challenge_hic.concat(iccsn_egk.bytes(2, 8));
var cryptogram_hpc = card_HPC.sendApdu(0x00, 0x88, 0x00, 0x00, cryptograminput, 0x00, [0x9000]);
print("Cryptogram from HPC = " + cryptogram_hpc);
// Do EXTERNAL_AUTHENTICATE with HIC
card_HIC.sendApdu(0x00, 0x82, 0x00, 0x00, cryptogram_hpc, [0x9000]);
}
/*
// Create the card objects
// Uncomment the following, if you have two PC/SC reader rather than a terminal
// with multiple slots.
// var card_HIC = new Card("ORGA CardMouse USB 0"); // Reader with eGK
// var card_HPC = new Card("SCM Microsystems Inc. SCR33x USB Smart Card Reader 0"); // Reader with HPC
var card_HIC = new Card(_scsh3.reader + "#1"); // Reader with eGK
var card_HPC = new Card(_scsh3.reader + "#2"); // Reader with HPC
card_HPC.reset(Card.RESET_COLD);
card_HIC.reset(Card.RESET_COLD);
// Select application on HPC
var mf_hpc = new CardFile(card_HPC, ":3F00");
print("Please enter PIN for HPC");
// Verify PIN for HPC
ok = mf_hpc.performCHV(true, 1);
if (!ok) {
print("PIN Verification failed");
exit;
}
Card2CardAuthentication(card_HIC, card_HPC);
*/
© Copyright 2003 - 2013 CardContact Software & System Consulting, Minden, Germany
