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 */