1 /* 2 * --------- 3 * |.##> <##.| Open Smart Card Development Platform (www.openscdp.org) 4 * |# #| 5 * |# #| Copyright (c) 1999-2006 CardContact Software & System Consulting 6 * |'##> <##'| Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de) 7 * --------- 8 * 9 * This file is part of OpenSCDP. 10 * 11 * OpenSCDP is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 * 15 * OpenSCDP is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with OpenSCDP; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 * 24 * Card-to-Card authentification between German HPC und eGK 25 * 26 */ 27 28 load("cvc.js"); 29 30 // 31 // Perform a card to card mutual authentication between a German eGK and HPC 32 // 33 // The procedure involves 6 steps 34 // 1. Read ICCSN and card verifiable certificates (CVC) from eGK 35 // 2. Read ICCSN and card verifiable certificates (CVC) from HPC 36 // 3. Verify CVC chain from eGK in HPC 37 // 4. Verify CVC chain from HPC in eGK 38 // 5. Authenticate eGK against HPC 39 // 6. Authenticate HPC against eGK 40 // 41 // Prerequisite: The PIN must be verified on the HPC 42 // 43 function Card2CardAuthentication(card_HIC, card_HPC, rootpuk) { 44 45 // Step 1 - Read ICCSN.EGK, CVC.eGK.AUT and CVC.CA_eGK.CS from eGK 46 47 // Read ICCSN.EGK, construct ASN1 object and extract ICCSN 48 49 var ef_gdo = new CardFile(card_HIC, ":02"); 50 var gdo = ef_gdo.readBinary(); 51 var gdo_tlv = new ASN1(gdo); 52 // print(gdo_tlv); 53 var iccsn = gdo_tlv.value; 54 var iccsn_egk = iccsn; 55 print("ICCSN of eGK:"); 56 print(iccsn_egk); 57 58 // Read CVC.CA_eGK.CS and construct ASN1 object 59 60 var ef_cvc_ca_egk = new CardFile(card_HIC, ":04"); 61 var cvc_ca_egk_bin = ef_cvc_ca_egk.readBinary(); 62 63 var cvc_ca_egk_tlv = new ASN1(cvc_ca_egk_bin); 64 print("CVC.CA_eGK.CS:"); 65 // print(cvc_ca_egk_tlv); 66 67 var cvc_ca_egk = new CVC(cvc_ca_egk_bin); 68 cvc_ca_egk.verifyWithOneOf(rootpuk); 69 cvc_ca_egk.dump(); 70 71 // Read CVC.eGK.AUT and construct ASN1 object 72 73 var ef_cvc_egk = new CardFile(card_HIC, ":03"); 74 var cvc_egk_bin = ef_cvc_egk.readBinary(); 75 var cvc_egk_tlv = new ASN1(cvc_egk_bin); 76 print("CVC.eGK.AUT:"); 77 // print(cvc_egk_tlv); 78 79 var cvc_egk = new CVC(cvc_egk_bin); 80 cvc_egk.verifyWith(cvc_ca_egk.getPublicKey()); 81 cvc_egk.dump(); 82 83 84 85 // Step 2 - Read ICCSN.HPC, CVC.HPC.AUT and CVC.CA_HPC.CS from HPC 86 87 // Read ICCSN.HPC, construct ASN1 object and extract ICCSN 88 89 var ef_gdo = new CardFile(card_HPC, ":02"); 90 var gdo = ef_gdo.readBinary(); 91 var gdo_tlv = new ASN1(gdo); 92 // print(gdo_tlv); 93 var iccsn = gdo_tlv.value; 94 var iccsn_hpc = iccsn; 95 print("ICCSN of HPC"); 96 print(iccsn_hpc); 97 98 // Read CVC.CA_HPC.CS and construct ASN1 object 99 100 var ef_cvc_ca_hpc = new CardFile(card_HPC, ":04"); 101 var cvc_ca_hpc_bin = ef_cvc_ca_hpc.readBinary(); 102 var cvc_ca_hpc_tlv = new ASN1(cvc_ca_hpc_bin); 103 print("CVC.CA_HPC.AUT:"); 104 // print(cvc_ca_hpc_tlv); 105 106 var cvc_ca_hpc = new CVC(cvc_ca_hpc_bin); 107 cvc_ca_hpc.verifyWithOneOf(rootpuk); 108 cvc_ca_hpc.dump(); 109 110 // Read CVC.HPC.AUT and construct ASN1 object 111 112 var ef_cvc_hpc = new CardFile(card_HPC, ":03"); 113 var cvc_hpc_bin = ef_cvc_hpc.readBinary(); 114 var cvc_hpc_tlv = new ASN1(cvc_hpc_bin); 115 print("CVC.HPC.AUT:"); 116 // print(cvc_hpc_tlv); 117 118 var cvc_hpc = new CVC(cvc_hpc_bin); 119 cvc_hpc.verifyWith(cvc_ca_hpc.getPublicKey()); 120 cvc_hpc.dump(); 121 122 123 124 // Step 3 - Verify CVC chain from eGK in HPC 125 126 // Make PuK.eGK.AUT available in HPC 127 // Send MANAGE_SE to select root public key 128 129 // Create data body with tag '83' and the Certificate Authority Reference (CAR) from 130 // CVC.CA_eGK.CS 131 var do_tlv = new ASN1(0x83, cvc_ca_egk.getCertificationAuthorityReference()); 132 133 print("Selecting key for certificate verification: " + do_tlv.getBytes()); 134 card_HPC.sendApdu(0x00, 0x22, 0x81, 0xB6, do_tlv.getBytes(), [0x9000]); 135 136 // Send PSO:VERIFY_CERTIFICATE to verify cvc_ca_egk 137 138 // Create data body with concatenation of signature and public key remainder 139 var data = new ByteBuffer(); 140 data.append(cvc_ca_egk_tlv.get(0).getBytes()); 141 data.append(cvc_ca_egk_tlv.get(1).getBytes()); 142 143 print("Sending PSO:VERIFY_CERTIFICATE(CVC.CA_eGK.CS) to HPC"); 144 // print(data.toByteString()); 145 card_HPC.sendApdu(0x00, 0x2A, 0x00, 0xAE, data.toByteString(), [0x9000]); 146 147 print("CVC.CA_eGK.CS verified."); 148 149 // Send MANAGE_SE to select public key of certification authority from CVC.CA_eGK.CS 150 151 // Create data body with tag '83' and the Certificate Authority Reference (CAR) from 152 // CVC.eGK.AUT 153 var do_tlv = new ASN1(0x83, cvc_egk.getCertificationAuthorityReference()); 154 155 print("Selecting key for certificate verification: " + do_tlv.getBytes()); 156 card_HPC.sendApdu(0x00, 0x22, 0x81, 0xB6, do_tlv.getBytes(), [0x9000]); 157 158 // Send PSO:VERIFY_CERTIFICATE to verify cvc_egk 159 160 // Create data body with concatenation of signature and public key remainder 161 var data = new ByteBuffer(); 162 data.append(cvc_egk_tlv.get(0).getBytes()); 163 data.append(cvc_egk_tlv.get(1).getBytes()); 164 165 print("Sending PSO:VERIFY_CERTIFICATE(CVC.eGK.AUT) to HPC"); 166 // print(data.toByteString()); 167 card_HPC.sendApdu(0x00, 0x2A, 0x00, 0xAE, data.toByteString(), [0x9000]); 168 169 print("CVC.eGK.AUT verified."); 170 171 172 173 // Step 4 - Verify CVC chain from HPC in eGK 174 175 // Make PuK.HPC.AUT available in HIC 176 // Send MANAGE_SE to select root public key 177 178 // Create data body with tag '83' and the Certificate Authority Reference (CAR) from 179 // CVC.CA_HPC.CS 180 var do_tlv = new ASN1(0x83, cvc_ca_hpc.getCertificationAuthorityReference()); 181 182 print("Selecting key for certificate verification: " + do_tlv.getBytes()); 183 card_HIC.sendApdu(0x00, 0x22, 0x81, 0xB6, do_tlv.getBytes(), [0x9000]); 184 185 // Send PSO:VERIFY_CERTIFICATE to verify cvc_ca_hpc 186 187 // Create data body with concatenation of signature and public key remainder 188 var data = new ByteBuffer(); 189 data.append(cvc_ca_hpc_tlv.get(0).getBytes()); 190 data.append(cvc_ca_hpc_tlv.get(1).getBytes()); 191 192 print("Sending PSO:VERIFY_CERTIFICATE(CVC.CA_HPC.CS) to eGK"); 193 // print(data.toByteString()); 194 card_HIC.sendApdu(0x00, 0x2A, 0x00, 0xAE, data.toByteString(), [0x9000]); 195 196 print("CVC.CA_HPC.CS verified."); 197 198 // Send MANAGE_SE to select public key of certification authority from CVC.CA_HPC.CS 199 200 // Create data body with tag '83' and the Certificate Authority Reference (CAR) from 201 // CVC.HPC.AUT 202 // var car = cvc_hpc_tlv.get(2).value; 203 // var car = new ByteString("44 45 44 54 58 11 01 08", HEX); // #### tmp !!!! DEDTX 204 205 // var prefix = new ByteString("00000000", HEX); // Siemens ? 206 // car = prefix.concat(car); 207 var do_tlv = new ASN1(0x83, cvc_hpc.getCertificationAuthorityReference()); 208 209 print("Selecting key for certificate verification: " + do_tlv.getBytes()); 210 card_HIC.sendApdu(0x00, 0x22, 0x81, 0xB6, do_tlv.getBytes(), [0x9000]); 211 212 // Send PSO:VERIFY_CERTIFICATE to verify cvc_hpc 213 214 // Create data body with concatenation of signature and public key remainder 215 var data = new ByteBuffer(); 216 data.append(cvc_hpc_tlv.get(0).getBytes()); 217 data.append(cvc_hpc_tlv.get(1).getBytes()); 218 219 print("Sending PSO:VERIFY_CERTIFICATE(CVC.HPC.AUT) to eGK"); 220 // print(data.toByteString()); 221 card_HIC.sendApdu(0x00, 0x2A, 0x00, 0xAE, data.toByteString(), [0x9000]); 222 223 print("CVC.HPC.AUT verified."); 224 225 226 227 // Step 5 - Perform HIC to HPC authentification 228 229 // Send MANAGE_SE to key references for PuK.eGK.AUT 230 231 // Create data body with tag '83' and the key identifier 232 233 var data = new ByteBuffer(); 234 data.append((new ASN1(0x83, cvc_egk.getCertificateHolderReference())).getBytes()); 235 data.append((new ASN1(0x80, new ByteString("00", HEX))).getBytes()); 236 237 print("Selecting key in HPC for eGK authentification: " + data.toByteString()); 238 card_HPC.sendApdu(0x00, 0x22, 0x81, 0xA4, data.toByteString(), [0x9000]); 239 240 // Send MANAGE_SE to key references for PrK.eGK.AUT 241 242 // Create data body with tag '83' and the Certificate Authority Reference (CAR) from 243 // CVC.HPC.AUT 244 245 var data = new ByteBuffer(); 246 data.append((new ASN1(0x84, new ByteString("10", HEX))).getBytes()); 247 data.append((new ASN1(0x80, new ByteString("00", HEX))).getBytes()); 248 249 print("Selecting key in eGK for HPC authentification: " + data.toByteString()); 250 card_HIC.sendApdu(0x00, 0x22, 0x41, 0xA4, data.toByteString(), [0x9000]); 251 252 // GET_CHALLENGE from HPC 253 254 var challenge_hpc = card_HPC.sendApdu(0x00, 0x84, 0x00, 0x00, 0x08, [0x9000]); 255 print("Challenge from HPC = " + challenge_hpc); 256 257 // Do INTERNAL_AUTHENTICATE with HIC 258 259 var cryptograminput = challenge_hpc.concat(iccsn_hpc.bytes(2, 8)); 260 var cryptogram_hic = card_HIC.sendApdu(0x00, 0x88, 0x00, 0x00, cryptograminput, 0x00, [0x9000]); 261 print("Cryptogram from HIC = " + cryptogram_hic); 262 263 // Do EXTERNAL_AUTHENTICATE with HPC 264 265 card_HPC.sendApdu(0x00, 0x82, 0x00, 0x00, cryptogram_hic, [0x9000]); 266 267 268 269 // Step 6 - Perform HPC to HIC authentification 270 271 // Send MANAGE_SE to key references for PuK.HPC.AUT 272 273 // Create data body with tag '83' and the key identifier 274 275 var data = new ByteBuffer(); 276 data.append((new ASN1(0x83, cvc_hpc.getCertificateHolderReference())).getBytes()); 277 data.append((new ASN1(0x80, new ByteString("00", HEX))).getBytes()); 278 279 print("Selecting key in eGK for HPC authentification: " + data.toByteString()); 280 card_HIC.sendApdu(0x00, 0x22, 0x81, 0xA4, data.toByteString(), [0x9000]); 281 282 // Send MANAGE_SE to key references for PrK.HPC.AUT 283 284 // Create data body with tag '83' and the Certificate Authority Reference (CAR) from 285 // CVC.HPC.AUT 286 287 var data = new ByteBuffer(); 288 data.append((new ASN1(0x84, new ByteString("10", HEX))).getBytes()); 289 data.append((new ASN1(0x80, new ByteString("00", HEX))).getBytes()); 290 291 print("Selecting key in HPC for eGK authentification: " + data.toByteString()); 292 card_HPC.sendApdu(0x00, 0x22, 0x41, 0xA4, data.toByteString(), [0x9000]); 293 294 // GET_CHALLENGE from HIC 295 296 var challenge_hic = card_HIC.sendApdu(0x00, 0x84, 0x00, 0x00, 0x08, [0x9000]); 297 print("Challenge from HIC = " + challenge_hic); 298 299 // Do INTERNAL_AUTHENTICATE with HPC 300 301 var cryptograminput = challenge_hic.concat(iccsn_egk.bytes(2, 8)); 302 var cryptogram_hpc = card_HPC.sendApdu(0x00, 0x88, 0x00, 0x00, cryptograminput, 0x00, [0x9000]); 303 print("Cryptogram from HPC = " + cryptogram_hpc); 304 305 // Do EXTERNAL_AUTHENTICATE with HIC 306 307 card_HIC.sendApdu(0x00, 0x82, 0x00, 0x00, cryptogram_hpc, [0x9000]); 308 } 309 310 311 /* 312 // Create the card objects 313 314 // Uncomment the following, if you have two PC/SC reader rather than a terminal 315 // with multiple slots. 316 // var card_HIC = new Card("ORGA CardMouse USB 0"); // Reader with eGK 317 // var card_HPC = new Card("SCM Microsystems Inc. SCR33x USB Smart Card Reader 0"); // Reader with HPC 318 319 var card_HIC = new Card(_scsh3.reader + "#1"); // Reader with eGK 320 var card_HPC = new Card(_scsh3.reader + "#2"); // Reader with HPC 321 322 card_HPC.reset(Card.RESET_COLD); 323 card_HIC.reset(Card.RESET_COLD); 324 325 // Select application on HPC 326 var mf_hpc = new CardFile(card_HPC, ":3F00"); 327 328 print("Please enter PIN for HPC"); 329 // Verify PIN for HPC 330 ok = mf_hpc.performCHV(true, 1); 331 332 if (!ok) { 333 print("PIN Verification failed"); 334 exit; 335 } 336 337 Card2CardAuthentication(card_HIC, card_HPC); 338 */