001 /* Copyright (c) 2002 Graz University of Technology. All rights reserved.
002 *
003 * Redistribution and use in source and binary forms, with or without
004 * modification, are permitted provided that the following conditions are met:
005 *
006 * 1. Redistributions of source code must retain the above copyright notice,
007 * this list of conditions and the following disclaimer.
008 *
009 * 2. Redistributions in binary form must reproduce the above copyright notice,
010 * this list of conditions and the following disclaimer in the documentation
011 * and/or other materials provided with the distribution.
012 *
013 * 3. The end-user documentation included with the redistribution, if any, must
014 * include the following acknowledgment:
015 *
016 * "This product includes software developed by IAIK of Graz University of
017 * Technology."
018 *
019 * Alternately, this acknowledgment may appear in the software itself, if
020 * and wherever such third-party acknowledgments normally appear.
021 *
022 * 4. The names "Graz University of Technology" and "IAIK of Graz University of
023 * Technology" must not be used to endorse or promote products derived from
024 * this software without prior written permission.
025 *
026 * 5. Products derived from this software may not be called
027 * "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
028 * written permission of Graz University of Technology.
029 *
030 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
031 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
032 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
033 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
034 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
035 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
036 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
037 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
038 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
039 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
040 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
041 * POSSIBILITY OF SUCH DAMAGE.
042 */
043
044 package demo.pkcs.pkcs11.wrapper;
045
046 import java.io.File;
047 import java.io.FileInputStream;
048 import java.io.FileOutputStream;
049 import java.io.IOException;
050 import java.io.InputStream;
051 import java.security.MessageDigest;
052 import java.util.Arrays;
053
054 import iaik.pkcs.pkcs11.wrapper.CK_ATTRIBUTE;
055 import iaik.pkcs.pkcs11.wrapper.CK_INFO;
056 import iaik.pkcs.pkcs11.wrapper.CK_MECHANISM;
057 import iaik.pkcs.pkcs11.wrapper.CK_MECHANISM_INFO;
058 import iaik.pkcs.pkcs11.wrapper.CK_SESSION_INFO;
059 import iaik.pkcs.pkcs11.wrapper.CK_SLOT_INFO;
060 import iaik.pkcs.pkcs11.wrapper.CK_TOKEN_INFO;
061 import iaik.pkcs.pkcs11.wrapper.Functions;
062 import iaik.pkcs.pkcs11.wrapper.PKCS11;
063 import iaik.pkcs.pkcs11.wrapper.PKCS11Connector;
064 import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
065 import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
066
067
068
069 /**
070 * This is a simple class for testing the implementation.
071 * Notice that this is an sample that may not run as is with many tokens.
072 * It may be required to exclude some test methods in the main method.
073 */
074 public class SimpleTest {
075
076 protected static final String CERTIFICATE_FILE = "tokenCertificate.der";
077
078 protected static final String SIGNATURE_FILE = "signature.bin";
079
080 protected static final String DIGEST_FILE = "digest.dat";
081
082 protected PKCS11 myPKCS11Module_;
083
084 protected String userPin_;
085
086 protected long token_ = -1L;
087
088 protected long session_;
089
090 protected long[] objects_;
091
092 protected long signatureKeyHandle_;
093
094 protected long certificateHandle_;
095
096 protected byte[] derEncodedCertificate_;
097
098 protected File file_;
099
100 protected CK_MECHANISM signatureMechanism_;
101
102 protected CK_MECHANISM digestMechanism_;
103
104 protected MessageDigest messageDigest_;
105
106 protected byte[] signature_;
107
108 protected byte[] digest_;
109
110 public SimpleTest(String pkcs11Module, String userPin, File file)
111 throws IOException, PKCS11Exception
112 {
113 System.out.print("trying to connect to PKCS#11 module: " + pkcs11Module);
114 myPKCS11Module_ = PKCS11Connector.connectToPKCS11Module(pkcs11Module);
115 userPin_ = userPin;
116 file_ = file;
117 signatureMechanism_ = new CK_MECHANISM();
118 signatureMechanism_.mechanism = PKCS11Constants.CKM_SHA1_RSA_PKCS;
119 signatureMechanism_.pParameter = null;
120 digestMechanism_ = new CK_MECHANISM();
121 digestMechanism_.mechanism = PKCS11Constants.CKM_SHA_1;
122 digestMechanism_.pParameter = null;
123 System.out.println(" FINISHED");
124 }
125
126 public static void main(String[] args) {
127 if (args.length != 3) {
128 printUsage();
129 System.exit(1);
130 }
131
132 try {
133 SimpleTest test = new SimpleTest(args[0], args[1], new File(args[2]));
134
135 test.initialize();
136 test.getInfo();
137 test.getSlotInfo();
138 test.getTokenInfo();
139 test.getMechanismInfo();
140 //test.initToken();
141 test.openROSession();
142 test.getSessionInfo();
143 test.findAllObjects();
144 test.printAllObjects();
145 test.loginUser();
146 test.getSessionInfo();
147 test.findAllObjects();
148 test.printAllObjects();
149 test.findSignatureKey();
150 test.findCertificate();
151 test.readCertificate();
152 test.writeCertificateToFile();
153 test.signData();
154 test.writeSignatureToFile();
155 test.digestData();
156 test.writeDigestToFile();
157 test.logout();
158 test.closeSession();
159
160 } catch (Throwable thr) {
161 thr.printStackTrace();
162 }
163 }
164
165 public static void printUsage() {
166 System.out.println("Usage: SimepleTest <PKCS#11 module> <userPIN> <file to be signed>");
167 System.out.println(" e.g.: SimpleTest pk2priv.dll password data.dat");
168 System.out.println("The given DLL must be in the search path of the system.");
169 }
170
171 public void initialize()
172 throws PKCS11Exception
173 {
174 System.out.print("initializing... ");
175 myPKCS11Module_.C_Initialize(null);
176 System.out.println("FINISHED\n");
177 }
178
179 public void getInfo()
180 throws PKCS11Exception
181 {
182 System.out.println("getting info");
183 CK_INFO moduleInfo = myPKCS11Module_.C_GetInfo();
184 System.out.println("Module Info: ");
185 System.out.println(moduleInfo);
186 System.out.println("FINISHED\n");
187 }
188
189 public void getSlotInfo()
190 throws PKCS11Exception
191 {
192 System.out.println("getting slot list");
193 long[] slotIDs = myPKCS11Module_.C_GetSlotList(false);
194 CK_SLOT_INFO slotInfo;
195 for (int i=0; i < slotIDs.length; i++) {
196 System.out.println("Slot Info: ");
197 slotInfo = myPKCS11Module_.C_GetSlotInfo(slotIDs[i]);
198 System.out.println(slotInfo);
199 }
200 System.out.println("FINISHED\n");
201 }
202
203 public void getTokenInfo()
204 throws PKCS11Exception
205 {
206 System.out.println("getting token list");
207 long[] tokenIDs = myPKCS11Module_.C_GetSlotList(true);
208 CK_TOKEN_INFO tokenInfo;
209 for (int i=0; i < tokenIDs.length; i++) {
210 System.out.println("Token Info: ");
211 tokenInfo = myPKCS11Module_.C_GetTokenInfo(tokenIDs[i]);
212 System.out.println(tokenInfo);
213 if (token_ == -1L) {
214 token_ = tokenIDs[i];
215 }
216 }
217 System.out.println("FINISHED\n");
218 }
219
220 public void getMechanismInfo()
221 throws PKCS11Exception
222 {
223 CK_MECHANISM_INFO mechanismInfo;
224
225 System.out.println("getting mechanism list");
226 System.out.println("getting slot list");
227 long[] slotIDs = myPKCS11Module_.C_GetSlotList(true);
228 for (int i=0; i < slotIDs.length; i++) {
229 System.out.println("getting mechanism list for slot " + slotIDs[i]);
230 long[] mechanismIDs = myPKCS11Module_.C_GetMechanismList(slotIDs[i]);
231 for (int j=0; j < mechanismIDs.length; j++) {
232 System.out.println("mechanism info for mechanism " + Functions.mechanismCodeToString(mechanismIDs[j]) +
233 ": ");
234 mechanismInfo = myPKCS11Module_.C_GetMechanismInfo(slotIDs[i],
235 mechanismIDs[j]);
236 System.out.println(mechanismInfo);
237 }
238 }
239 System.out.println("FINISHED\n");
240 }
241
242 public void initToken()
243 throws PKCS11Exception
244 {
245 String label = "The Label! ";
246 String pin = "password";
247
248 System.out.println("init token");
249 long[] slotIDs = myPKCS11Module_.C_GetSlotList(false);
250 myPKCS11Module_.C_InitToken(slotIDs[0], pin.toCharArray(), label.toCharArray());
251 System.out.println("FINISHED");
252 }
253
254 public void openROSession()
255 throws PKCS11Exception
256 {
257 System.out.println("open RO session");
258 session_ = myPKCS11Module_.C_OpenSession(token_, PKCS11Constants.CKF_SERIAL_SESSION, null, null);
259 System.out.println("FINISHED\n");
260 }
261
262 public void getSessionInfo()
263 throws PKCS11Exception
264 {
265 System.out.println("get session info");
266 CK_SESSION_INFO sessionInfo;
267 System.out.println("Session Info: ");
268 sessionInfo = myPKCS11Module_.C_GetSessionInfo(session_);
269 System.out.println(sessionInfo);
270 System.out.println("FINISHED\n");
271 }
272
273 public void findAllObjects()
274 throws PKCS11Exception
275 {
276 System.out.println("find all objects");
277 myPKCS11Module_.C_FindObjectsInit(session_, null);
278 objects_ = myPKCS11Module_.C_FindObjects(session_, 100); //maximum of 100 at once
279 if (objects_ == null) {
280 System.out.println("null returned - no objects found");
281 } else {
282 System.out.println("found " + objects_.length + " objects");
283 }
284 myPKCS11Module_.C_FindObjectsFinal(session_);
285 System.out.println("FINISHED\n");
286 }
287
288 public void printAllObjects()
289 throws PKCS11Exception
290 {
291 System.out.println("print all objects");
292
293 for (int i = 0; i < objects_.length; i++) {
294 System.out.println("object No. " + i);
295 CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[1];
296 template[0] = new CK_ATTRIBUTE();
297 template[0].type = PKCS11Constants.CKA_CLASS;
298 myPKCS11Module_.C_GetAttributeValue(session_, objects_[i], template);
299 System.out.println("CKA_CLASS: " + Functions.classTypeToString(((Long) template[0].pValue).longValue()));
300 }
301
302 System.out.println("FINISHED\n");
303 }
304
305 public void loginUser()
306 throws PKCS11Exception
307 {
308 System.out.println("login user to session with password \"" + userPin_ + "\"");
309 myPKCS11Module_.C_Login(session_, PKCS11Constants.CKU_USER, userPin_.toCharArray());
310 System.out.println("FINISHED\n");
311 }
312
313 public void findSignatureKey()
314 throws PKCS11Exception
315 {
316 System.out.println("find signature key");
317 CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[2];
318
319 attributeTemplateList[0] = new CK_ATTRIBUTE();
320 attributeTemplateList[0].type = PKCS11Constants.CKA_CLASS;
321 attributeTemplateList[0].pValue = new Long(PKCS11Constants.CKO_PRIVATE_KEY);
322 attributeTemplateList[1] = new CK_ATTRIBUTE();
323 attributeTemplateList[1].type = PKCS11Constants.CKA_SIGN;
324 attributeTemplateList[1].pValue = new Boolean(PKCS11Constants.TRUE);
325
326 myPKCS11Module_.C_FindObjectsInit(session_, attributeTemplateList);
327 long[] availableSignatureKeys = myPKCS11Module_.C_FindObjects(session_, 100); //maximum of 100 at once
328 if (availableSignatureKeys == null) {
329 System.out.println("null returned - no signature key found");
330 } else {
331 System.out.println("found " + availableSignatureKeys.length + " signature keys");
332 for (int i=0; i < availableSignatureKeys.length; i++) {
333 if (i == 0) { // the first we find, we take as our signature key
334 signatureKeyHandle_ = availableSignatureKeys[i];
335 System.out.print("for signing we use ");
336 }
337 System.out.println("signature key " + i);
338 }
339 }
340 myPKCS11Module_.C_FindObjectsFinal(session_);
341 System.out.println("FINISHED\n");
342 }
343
344 public void findCertificate()
345 throws PKCS11Exception
346 {
347 System.out.println("find certificate");
348
349 // first get the ID of the signature key
350 CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[1];
351 attributeTemplateList[0] = new CK_ATTRIBUTE();
352 attributeTemplateList[0].type = PKCS11Constants.CKA_ID;
353
354 myPKCS11Module_.C_GetAttributeValue(session_, signatureKeyHandle_ , attributeTemplateList);
355 byte[] keyAndCertificateID = (byte[]) attributeTemplateList[0].pValue;
356 System.out.println("ID of siganture key: " + Functions.toHexString(keyAndCertificateID));
357
358 // now get the certificate with the same ID as the signature key
359 attributeTemplateList = new CK_ATTRIBUTE[2];
360
361 attributeTemplateList[0] = new CK_ATTRIBUTE();
362 attributeTemplateList[0].type = PKCS11Constants.CKA_CLASS;
363 attributeTemplateList[0].pValue = new Long(PKCS11Constants.CKO_CERTIFICATE);
364 attributeTemplateList[1] = new CK_ATTRIBUTE();
365 attributeTemplateList[1].type = PKCS11Constants.CKA_ID;
366 attributeTemplateList[1].pValue = keyAndCertificateID;
367
368 myPKCS11Module_.C_FindObjectsInit(session_, attributeTemplateList);
369 long[] availableCertificates = myPKCS11Module_.C_FindObjects(session_, 100); //maximum of 100 at once
370 if (availableCertificates == null) {
371 System.out.println("null returned - no certificate found");
372 } else {
373 System.out.println("found " + availableCertificates.length + " certificates with matching ID");
374 for (int i=0; i < availableCertificates.length; i++) {
375 if (i == 0) { // the first we find, we take as our certificate
376 certificateHandle_ = availableCertificates[i];
377 System.out.print("for verification we use ");
378 }
379 System.out.println("certificate " + i);
380 }
381 }
382 myPKCS11Module_.C_FindObjectsFinal(session_);
383 System.out.println("FINISHED\n");
384 }
385
386 public void readCertificate()
387 throws PKCS11Exception
388 {
389 System.out.println("read certificate");
390
391 CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[1];
392 template[0] = new CK_ATTRIBUTE();
393 template[0].type = PKCS11Constants.CKA_VALUE;
394 myPKCS11Module_.C_GetAttributeValue(session_, certificateHandle_ , template);
395 derEncodedCertificate_ = (byte[]) template[0].pValue;
396 System.out.println("DER encoded certificate (" + derEncodedCertificate_.length + " bytes):");
397 System.out.println(Functions.toHexString(derEncodedCertificate_));
398
399 System.out.println("FINISHED\n");
400 }
401
402 public void writeCertificateToFile()
403 throws IOException, PKCS11Exception
404 {
405 System.out.println("write certificate to file: " + CERTIFICATE_FILE);
406
407 FileOutputStream fos = new FileOutputStream(CERTIFICATE_FILE);
408 fos.write(derEncodedCertificate_);
409 fos.flush();
410 fos.close();
411
412 System.out.println("FINISHED\n");
413 }
414
415 public void signData()
416 throws IOException, PKCS11Exception
417 {
418 byte[] buffer = new byte[1024];
419 byte[] helpBuffer;
420 int bytesRead;
421
422 InputStream dataInput = new FileInputStream(file_);
423 myPKCS11Module_.C_SignInit(session_, signatureMechanism_, signatureKeyHandle_);
424 while ((bytesRead = dataInput.read(buffer, 0, buffer.length)) >= 0) {
425 helpBuffer = new byte[bytesRead]; // we need a buffer that only holds what to send for signing
426 System.arraycopy(buffer, 0, helpBuffer, 0, bytesRead);
427 myPKCS11Module_.C_SignUpdate(session_, helpBuffer);
428 Arrays.fill(helpBuffer, (byte) 0);
429 }
430 Arrays.fill(buffer, (byte) 0);
431 signature_ = myPKCS11Module_.C_SignFinal(session_);
432 }
433
434 public void writeSignatureToFile()
435 throws IOException, PKCS11Exception
436 {
437 System.out.println("write signature to file: " + SIGNATURE_FILE);
438
439 FileOutputStream fos = new FileOutputStream(SIGNATURE_FILE);
440 fos.write(signature_);
441 fos.flush();
442 fos.close();
443
444 System.out.println("FINISHED");
445 }
446
447 public void digestData()
448 throws IOException, PKCS11Exception
449 {
450 byte[] buffer = new byte[1024];
451 byte[] helpBuffer, testDigest;
452 int bytesRead;
453
454 System.out.println("Digest Data");
455 myPKCS11Module_.C_DigestInit(session_, digestMechanism_);
456 try {
457 messageDigest_ = MessageDigest.getInstance("SHA-1");
458 } catch (Exception e) {
459 System.out.println(e);
460 }
461 InputStream dataInput = new FileInputStream(file_);
462 while ((bytesRead = dataInput.read(buffer, 0, buffer.length)) >= 0) {
463 helpBuffer = new byte[bytesRead]; // we need a buffer that only holds what to send for digesting
464 System.arraycopy(buffer, 0, helpBuffer, 0, bytesRead);
465 myPKCS11Module_.C_DigestUpdate(session_, helpBuffer);
466 messageDigest_.update(helpBuffer);
467 Arrays.fill(helpBuffer, (byte) 0);
468 }
469 Arrays.fill(buffer, (byte) 0);
470 digest_ = myPKCS11Module_.C_DigestFinal(session_);
471 testDigest = messageDigest_.digest();
472 System.out.println("PKCS11digest:"+Functions.toHexString(digest_));
473 System.out.println("TestDigest :"+Functions.toHexString(testDigest));
474 System.out.println("FINISHED\n");
475 }
476
477 public void writeDigestToFile()
478 throws IOException, PKCS11Exception
479 {
480 System.out.println("write digest to file: " + DIGEST_FILE);
481
482 FileOutputStream fos = new FileOutputStream(DIGEST_FILE);
483 fos.write(digest_);
484 fos.flush();
485 fos.close();
486
487 System.out.println("FINISHED\n");
488 }
489
490 public void logout()
491 throws PKCS11Exception
492 {
493 System.out.println("logout session");
494 myPKCS11Module_.C_Logout(session_);
495 System.out.println("FINISHED\n");
496 }
497
498 public void closeSession()
499 throws PKCS11Exception
500 {
501 System.out.println("close session");
502 myPKCS11Module_.C_CloseSession(session_);
503 System.out.println("FINISHED\n");
504 }
505
506
507 }