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 }