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; 045 046 import java.io.BufferedReader; 047 import java.io.IOException; 048 import java.io.PrintWriter; 049 //import java.util.HashMap; 050 import java.util.Enumeration; 051 import java.util.Hashtable; 052 //import java.util.Iterator; 053 //import java.util.List; 054 //import java.util.Map; 055 import java.util.Vector; 056 057 import iaik.pkcs.pkcs11.Module; 058 import iaik.pkcs.pkcs11.Session; 059 import iaik.pkcs.pkcs11.Slot; 060 import iaik.pkcs.pkcs11.Token; 061 import iaik.pkcs.pkcs11.TokenException; 062 import iaik.pkcs.pkcs11.TokenInfo; 063 import iaik.pkcs.pkcs11.objects.Key; 064 import iaik.pkcs.pkcs11.objects.Object; 065 import iaik.pkcs.pkcs11.objects.PrivateKey; 066 import iaik.pkcs.pkcs11.objects.RSAPrivateKey; 067 import iaik.pkcs.pkcs11.objects.X509PublicKeyCertificate; 068 import iaik.x509.X509Certificate; 069 070 071 072 /** 073 * This class contains only static methods. It is the place for all functions 074 * that are used by several classes in this package. 075 * 076 * @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at> 077 */ 078 public class Util { 079 080 /** 081 * Maps mechanism strings to their codes as Long. 082 */ 083 protected static Hashtable mechansimCodes_; 084 085 /** 086 * Converts the names of mechanisms to their long value code. 087 * 088 * @param mechansimName The name of the mechanism to get the code; e.g. 089 * "CKM_RSA_PKCS". 090 * @return The code of the mechanism or null, if this name is unknown. 091 * @preconditions (mechansimName <> null) 092 * @postconditions 093 */ 094 public static Long mechanismCodeToString(String mechansimName) { 095 if (mechansimName == null) { 096 throw new NullPointerException("Argument \"mechansimName\" must not be null."); 097 } 098 099 Long mechanismCode; 100 101 if (mechansimName.startsWith("0x")) { 102 // we try to parse it as hex encoded long 103 mechanismCode = new Long(Long.parseLong(mechansimName, 16)); 104 } else { 105 if (mechansimCodes_ == null) { 106 mechansimCodes_ = new Hashtable(160); 107 mechansimCodes_.put("CKM_RSA_PKCS_KEY_PAIR_GEN", new Long(0x00000000)); 108 mechansimCodes_.put("CKM_RSA_PKCS", new Long(0x00000001)); 109 mechansimCodes_.put("CKM_RSA_9796", new Long(0x00000002)); 110 mechansimCodes_.put("CKM_RSA_X_509", new Long(0x00000003)); 111 mechansimCodes_.put("CKM_MD2_RSA_PKCS", new Long(0x00000004)); 112 mechansimCodes_.put("CKM_MD5_RSA_PKCS", new Long(0x00000005)); 113 mechansimCodes_.put("CKM_SHA1_RSA_PKCS", new Long(0x00000006)); 114 mechansimCodes_.put("CKM_RIPEMD128_RSA_PKCS", new Long(0x00000007)); 115 mechansimCodes_.put("CKM_RIPEMD160_RSA_PKCS", new Long(0x00000008)); 116 mechansimCodes_.put("CKM_RSA_PKCS_OAEP", new Long(0x00000009)); 117 mechansimCodes_.put("CKM_DSA_KEY_PAIR_GEN", new Long(0x00000010)); 118 mechansimCodes_.put("CKM_DSA", new Long(0x00000011)); 119 mechansimCodes_.put("CKM_DSA_SHA1", new Long(0x00000012)); 120 mechansimCodes_.put("CKM_DH_PKCS_KEY_PAIR_GEN", new Long(0x00000020)); 121 mechansimCodes_.put("CKM_DH_PKCS_DERIVE", new Long(0x00000021)); 122 mechansimCodes_.put("CKM_RC2_KEY_GEN", new Long(0x00000100)); 123 mechansimCodes_.put("CKM_RC2_ECB", new Long(0x00000101)); 124 mechansimCodes_.put("CKM_RC2_CBC", new Long(0x00000102)); 125 mechansimCodes_.put("CKM_RC2_MAC", new Long(0x00000103)); 126 mechansimCodes_.put("CKM_RC2_MAC_GENERAL", new Long(0x00000104)); 127 mechansimCodes_.put("CKM_RC2_CBC_PAD", new Long(0x00000105)); 128 mechansimCodes_.put("CKM_RC4_KEY_GEN", new Long(0x00000110)); 129 mechansimCodes_.put("CKM_RC4", new Long(0x00000111)); 130 mechansimCodes_.put("CKM_DES_KEY_GEN", new Long(0x00000120)); 131 mechansimCodes_.put("CKM_DES_ECB", new Long(0x00000121)); 132 mechansimCodes_.put("CKM_DES_CBC", new Long(0x00000122)); 133 mechansimCodes_.put("CKM_DES_MAC", new Long(0x00000123)); 134 mechansimCodes_.put("CKM_DES_MAC_GENERAL", new Long(0x00000124)); 135 mechansimCodes_.put("CKM_DES_CBC_PAD", new Long(0x00000125)); 136 mechansimCodes_.put("CKM_DES2_KEY_GEN", new Long(0x00000130)); 137 mechansimCodes_.put("CKM_DES3_KEY_GEN", new Long(0x00000131)); 138 mechansimCodes_.put("CKM_DES3_ECB", new Long(0x00000132)); 139 mechansimCodes_.put("CKM_DES3_CBC", new Long(0x00000133)); 140 mechansimCodes_.put("CKM_DES3_MAC", new Long(0x00000134)); 141 mechansimCodes_.put("CKM_DES3_MAC_GENERAL", new Long(0x00000135)); 142 mechansimCodes_.put("CKM_DES3_CBC_PAD", new Long(0x00000136)); 143 mechansimCodes_.put("CKM_CDMF_KEY_GEN", new Long(0x00000140)); 144 mechansimCodes_.put("CKM_CDMF_ECB", new Long(0x00000141)); 145 mechansimCodes_.put("CKM_CDMF_CBC", new Long(0x00000142)); 146 mechansimCodes_.put("CKM_CDMF_MAC", new Long(0x00000143)); 147 mechansimCodes_.put("CKM_CDMF_MAC_GENERAL", new Long(0x00000144)); 148 mechansimCodes_.put("CKM_CDMF_CBC_PAD", new Long(0x00000145)); 149 mechansimCodes_.put("CKM_MD2", new Long(0x00000200)); 150 mechansimCodes_.put("CKM_MD2_HMAC", new Long(0x00000201)); 151 mechansimCodes_.put("CKM_MD2_HMAC_GENERAL", new Long(0x00000202)); 152 mechansimCodes_.put("CKM_MD5", new Long(0x00000210)); 153 mechansimCodes_.put("CKM_MD5_HMAC", new Long(0x00000211)); 154 mechansimCodes_.put("CKM_MD5_HMAC_GENERAL", new Long(0x00000212)); 155 mechansimCodes_.put("CKM_SHA_1", new Long(0x00000220)); 156 mechansimCodes_.put("CKM_SHA_1_HMAC", new Long(0x00000221)); 157 mechansimCodes_.put("CKM_SHA_1_HMAC_GENERAL", new Long(0x00000222)); 158 mechansimCodes_.put("CKM_RIPEMD128", new Long(0x00000230)); 159 mechansimCodes_.put("CKM_RIPEMD128_HMAC", new Long(0x00000231)); 160 mechansimCodes_.put("CKM_RIPEMD128_HMAC_GENERAL", new Long(0x00000232)); 161 mechansimCodes_.put("CKM_RIPEMD160", new Long(0x00000240)); 162 mechansimCodes_.put("CKM_RIPEMD160_HMAC", new Long(0x00000241)); 163 mechansimCodes_.put("CKM_RIPEMD160_HMAC_GENERAL", new Long(0x00000242)); 164 mechansimCodes_.put("CKM_CAST_KEY_GEN", new Long(0x00000300)); 165 mechansimCodes_.put("CKM_CAST_ECB", new Long(0x00000301)); 166 mechansimCodes_.put("CKM_CAST_CBC", new Long(0x00000302)); 167 mechansimCodes_.put("CKM_CAST_MAC", new Long(0x00000303)); 168 mechansimCodes_.put("CKM_CAST_MAC_GENERAL", new Long(0x00000304)); 169 mechansimCodes_.put("CKM_CAST_CBC_PAD", new Long(0x00000305)); 170 mechansimCodes_.put("CKM_CAST3_KEY_GEN", new Long(0x00000310)); 171 mechansimCodes_.put("CKM_CAST3_ECB", new Long(0x00000311)); 172 mechansimCodes_.put("CKM_CAST3_CBC", new Long(0x00000312)); 173 mechansimCodes_.put("CKM_CAST3_MAC", new Long(0x00000313)); 174 mechansimCodes_.put("CKM_CAST3_MAC_GENERAL", new Long(0x00000314)); 175 mechansimCodes_.put("CKM_CAST3_CBC_PAD", new Long(0x00000315)); 176 mechansimCodes_.put("CKM_CAST5_KEY_GEN", new Long(0x00000320)); 177 mechansimCodes_.put("CKM_CAST128_KEY_GEN", new Long(0x00000320)); 178 mechansimCodes_.put("CKM_CAST5_ECB", new Long(0x00000321)); 179 mechansimCodes_.put("CKM_CAST128_ECB", new Long(0x00000321)); 180 mechansimCodes_.put("CKM_CAST5_CBC", new Long(0x00000322)); 181 mechansimCodes_.put("CKM_CAST128_CBC", new Long(0x00000322)); 182 mechansimCodes_.put("CKM_CAST5_MAC", new Long(0x00000323)); 183 mechansimCodes_.put("CKM_CAST128_MAC", new Long(0x00000323)); 184 mechansimCodes_.put("CKM_CAST5_MAC_GENERAL", new Long(0x00000324)); 185 mechansimCodes_.put("CKM_CAST128_MAC_GENERAL", new Long(0x00000324)); 186 mechansimCodes_.put("CKM_CAST5_CBC_PAD", new Long(0x00000325)); 187 mechansimCodes_.put("CKM_CAST128_CBC_PAD", new Long(0x00000325)); 188 mechansimCodes_.put("CKM_RC5_KEY_GEN", new Long(0x00000330)); 189 mechansimCodes_.put("CKM_RC5_ECB", new Long(0x00000331)); 190 mechansimCodes_.put("CKM_RC5_CBC", new Long(0x00000332)); 191 mechansimCodes_.put("CKM_RC5_MAC", new Long(0x00000333)); 192 mechansimCodes_.put("CKM_RC5_MAC_GENERAL", new Long(0x00000334)); 193 mechansimCodes_.put("CKM_RC5_CBC_PAD", new Long(0x00000335)); 194 mechansimCodes_.put("CKM_IDEA_KEY_GEN", new Long(0x00000340)); 195 mechansimCodes_.put("CKM_IDEA_ECB", new Long(0x00000341)); 196 mechansimCodes_.put("CKM_IDEA_CBC", new Long(0x00000342)); 197 mechansimCodes_.put("CKM_IDEA_MAC", new Long(0x00000343)); 198 mechansimCodes_.put("CKM_IDEA_MAC_GENERAL", new Long(0x00000344)); 199 mechansimCodes_.put("CKM_IDEA_CBC_PAD", new Long(0x00000345)); 200 mechansimCodes_.put("CKM_GENERIC_SECRET_KEY_GEN", new Long(0x00000350)); 201 mechansimCodes_.put("CKM_CONCATENATE_BASE_AND_KEY", new Long(0x00000360)); 202 mechansimCodes_.put("CKM_CONCATENATE_BASE_AND_DATA", new Long(0x00000362)); 203 mechansimCodes_.put("CKM_CONCATENATE_DATA_AND_BASE", new Long(0x00000363)); 204 mechansimCodes_.put("CKM_XOR_BASE_AND_DATA", new Long(0x00000364)); 205 mechansimCodes_.put("CKM_EXTRACT_KEY_FROM_KEY", new Long(0x00000365)); 206 mechansimCodes_.put("CKM_SSL3_PRE_MASTER_KEY_GEN", new Long(0x00000370)); 207 mechansimCodes_.put("CKM_SSL3_MASTER_KEY_DERIVE", new Long(0x00000371)); 208 mechansimCodes_.put("CKM_SSL3_KEY_AND_MAC_DERIVE", new Long(0x00000372)); 209 mechansimCodes_.put("CKM_SSL3_MD5_MAC", new Long(0x00000380)); 210 mechansimCodes_.put("CKM_SSL3_SHA1_MAC", new Long(0x00000381)); 211 mechansimCodes_.put("CKM_MD5_KEY_DERIVATION", new Long(0x00000390)); 212 mechansimCodes_.put("CKM_MD2_KEY_DERIVATION", new Long(0x00000391)); 213 mechansimCodes_.put("CKM_SHA1_KEY_DERIVATION", new Long(0x00000392)); 214 mechansimCodes_.put("CKM_PBE_MD2_DES_CBC", new Long(0x000003A0)); 215 mechansimCodes_.put("CKM_PBE_MD5_DES_CBC", new Long(0x000003A1)); 216 mechansimCodes_.put("CKM_PBE_MD5_CAST_CBC", new Long(0x000003A2)); 217 mechansimCodes_.put("CKM_PBE_MD5_CAST3_CBC", new Long(0x000003A3)); 218 mechansimCodes_.put("CKM_PBE_MD5_CAST5_CBC", new Long(0x000003A4)); 219 mechansimCodes_.put("CKM_PBE_MD5_CAST128_CBC", new Long(0x000003A4)); 220 mechansimCodes_.put("CKM_PBE_SHA1_CAST5_CBC", new Long(0x000003A5)); 221 mechansimCodes_.put("CKM_PBE_SHA1_CAST128_CBC", new Long(0x000003A5)); 222 mechansimCodes_.put("CKM_PBE_SHA1_RC4_128", new Long(0x000003A6)); 223 mechansimCodes_.put("CKM_PBE_SHA1_RC4_40", new Long(0x000003A7)); 224 mechansimCodes_.put("CKM_PBE_SHA1_DES3_EDE_CBC", new Long(0x000003A8)); 225 mechansimCodes_.put("CKM_PBE_SHA1_DES2_EDE_CBC", new Long(0x000003A9)); 226 mechansimCodes_.put("CKM_PBE_SHA1_RC2_128_CBC", new Long(0x000003AA)); 227 mechansimCodes_.put("CKM_PBE_SHA1_RC2_40_CBC", new Long(0x000003AB)); 228 mechansimCodes_.put("CKM_PKCS5_PBKD2", new Long(0x000003B0)); 229 mechansimCodes_.put("CKM_PBA_SHA1_WITH_SHA1_HMAC", new Long(0x000003C0)); 230 mechansimCodes_.put("CKM_KEY_WRAP_LYNKS", new Long(0x00000400)); 231 mechansimCodes_.put("CKM_KEY_WRAP_SET_OAEP", new Long(0x00000401)); 232 mechansimCodes_.put("CKM_SKIPJACK_KEY_GEN", new Long(0x00001000)); 233 mechansimCodes_.put("CKM_SKIPJACK_ECB64", new Long(0x00001001)); 234 mechansimCodes_.put("CKM_SKIPJACK_CBC64", new Long(0x00001002)); 235 mechansimCodes_.put("CKM_SKIPJACK_OFB64", new Long(0x00001003)); 236 mechansimCodes_.put("CKM_SKIPJACK_CFB64", new Long(0x00001004)); 237 mechansimCodes_.put("CKM_SKIPJACK_CFB32", new Long(0x00001005)); 238 mechansimCodes_.put("CKM_SKIPJACK_CFB16", new Long(0x00001006)); 239 mechansimCodes_.put("CKM_SKIPJACK_CFB8", new Long(0x00001007)); 240 mechansimCodes_.put("CKM_SKIPJACK_WRAP", new Long(0x00001008)); 241 mechansimCodes_.put("CKM_SKIPJACK_PRIVATE_WRAP", new Long(0x00001009)); 242 mechansimCodes_.put("CKM_SKIPJACK_RELAYX", new Long(0x0000100a)); 243 mechansimCodes_.put("CKM_KEA_KEY_PAIR_GEN", new Long(0x00001010)); 244 mechansimCodes_.put("CKM_KEA_KEY_DERIVE", new Long(0x00001011)); 245 mechansimCodes_.put("CKM_FORTEZZA_TIMESTAMP", new Long(0x00001020)); 246 mechansimCodes_.put("CKM_BATON_KEY_GEN", new Long(0x00001030)); 247 mechansimCodes_.put("CKM_BATON_ECB128", new Long(0x00001031)); 248 mechansimCodes_.put("CKM_BATON_ECB96", new Long(0x00001032)); 249 mechansimCodes_.put("CKM_BATON_CBC128", new Long(0x00001033)); 250 mechansimCodes_.put("CKM_BATON_COUNTER", new Long(0x00001034)); 251 mechansimCodes_.put("CKM_BATON_SHUFFLE", new Long(0x00001035)); 252 mechansimCodes_.put("CKM_BATON_WRAP", new Long(0x00001036)); 253 mechansimCodes_.put("CKM_ECDSA_KEY_PAIR_GEN", new Long(0x00001040)); 254 mechansimCodes_.put("CKM_ECDSA", new Long(0x00001041)); 255 mechansimCodes_.put("CKM_ECDSA_SHA1", new Long(0x00001042)); 256 mechansimCodes_.put("CKM_JUNIPER_KEY_GEN", new Long(0x00001060)); 257 mechansimCodes_.put("CKM_JUNIPER_ECB128", new Long(0x00001061)); 258 mechansimCodes_.put("CKM_JUNIPER_CBC128", new Long(0x00001062)); 259 mechansimCodes_.put("CKM_JUNIPER_COUNTER", new Long(0x00001063)); 260 mechansimCodes_.put("CKM_JUNIPER_SHUFFLE", new Long(0x00001064)); 261 mechansimCodes_.put("CKM_JUNIPER_WRAP", new Long(0x00001065)); 262 mechansimCodes_.put("CKM_FASTHASH", new Long(0x00001070)); 263 mechansimCodes_.put("CKM_VENDOR_DEFINED", new Long(0x80000000)); 264 } 265 266 mechanismCode = (Long) mechansimCodes_.get(mechansimName); 267 } 268 269 return mechanismCode ; 270 } 271 272 /** 273 * Lists all available tokens of the given module and lets the user select 274 * one, if there is more than one available. 275 * 276 * @param pkcs11Module The PKCS#11 module to use. 277 * @param output The output stream to write the user prompts to. 278 * @param input The input stream where to read user input from. 279 * @return The selected token or null, if no token is available or the user 280 * canceled the action. 281 * @exception TokenException If listing the tokens failed. 282 * @exception IOException If writing a user prompt faild or if reading user 283 * input failed. 284 * @preconditions (pkcs11Module <> null) 285 * and (output <> null) 286 * and (input <> null) 287 * @postconditions 288 */ 289 public static Token selectToken(Module pkcs11Module, PrintWriter output, BufferedReader input) 290 throws TokenException, IOException 291 { 292 if (pkcs11Module == null) { 293 throw new NullPointerException("Argument \"pkcs11Module\" must not be null."); 294 } 295 if (output == null) { 296 throw new NullPointerException("Argument \"output\" must not be null."); 297 } 298 if (input == null) { 299 throw new NullPointerException("Argument \"input\" must not be null."); 300 } 301 302 output.println("################################################################################"); 303 output.println("getting list of all tokens"); 304 Slot[] slotsWithToken = pkcs11Module.getSlotList(Module.SlotRequirement.TOKEN_PRESENT); 305 Token[] tokens = new Token[slotsWithToken.length]; 306 Hashtable tokenIDtoToken = new Hashtable(tokens.length); 307 308 for (int i = 0; i < slotsWithToken.length; i++) { 309 output.println("________________________________________________________________________________"); 310 tokens[i] = slotsWithToken[i].getToken(); 311 TokenInfo tokenInfo = tokens[i].getTokenInfo(); 312 long tokenID = tokens[i].getTokenID(); 313 tokenIDtoToken.put(new Long(tokenID), tokens[i]); 314 output.println("Token ID: " + tokenID); 315 output.println(tokenInfo); 316 output.println("________________________________________________________________________________"); 317 } 318 output.println("################################################################################"); 319 320 output.println("################################################################################"); 321 Token token = null; 322 Long selectedTokenID = null; 323 if (tokens.length == 0) { 324 output.println("There is no slot with a present token."); 325 } else if (tokens.length == 1) { 326 output.println("Taking token with ID: " + tokens[0].getTokenID()); 327 selectedTokenID = new Long(tokens[0].getTokenID()); 328 token = tokens[0]; 329 } else { 330 boolean gotTokenID = false; 331 while (!gotTokenID) { 332 output.print("Enter the ID of the token to use or 'x' to exit: "); 333 output.flush(); 334 String tokenIDstring = input.readLine(); 335 if (tokenIDstring.equalsIgnoreCase("x")) { 336 break; 337 } 338 try { 339 selectedTokenID = new Long(tokenIDstring); 340 token = (Token) tokenIDtoToken.get(selectedTokenID); 341 if (token != null) { 342 gotTokenID = true; 343 } else { 344 output.println("A token with the entered ID \"" + tokenIDstring + "\" does not exist. Try again."); 345 } 346 } catch (NumberFormatException ex) { 347 output.println("The entered ID \"" + tokenIDstring + "\" is invalid. Try again."); 348 } 349 } 350 } 351 output.println("################################################################################"); 352 353 return token ; 354 } 355 356 /** 357 * Opens an authorized session for the given token. If the token requires the 358 * user to login for private operations, the method loggs in the user. 359 * 360 * @param token The token to open a session for. 361 * @param rwSession If the session should be a read-write session. This may be 362 * Token.SessionReadWriteBehavior.RO_SESSION or 363 * Token.SessionReadWriteBehavior.RW_SESSION. 364 * @param output The output stream to write the user prompts to. 365 * @param input The input stream where to read user input from. 366 * @return The selected token or null, if no token is available or the user 367 * canceled the action. 368 * @exception TokenException If listing the tokens failed. 369 * @exception IOException If writing a user prompt faild or if reading user 370 * input failed. 371 * @preconditions (token <> null) 372 * and (output <> null) 373 * and (input <> null) 374 * @postconditions (result <> null) 375 */ 376 public static Session openAuthorizedSession(Token token, boolean rwSession, PrintWriter output, BufferedReader input) 377 throws TokenException, IOException 378 { 379 if (token == null) { 380 throw new NullPointerException("Argument \"token\" must not be null."); 381 } 382 if (output == null) { 383 throw new NullPointerException("Argument \"output\" must not be null."); 384 } 385 if (input == null) { 386 throw new NullPointerException("Argument \"input\" must not be null."); 387 } 388 389 output.println("################################################################################"); 390 output.println("opening session"); 391 Session session = 392 token.openSession(Token.SessionType.SERIAL_SESSION, rwSession, null, null); 393 394 TokenInfo tokenInfo = token.getTokenInfo(); 395 if (tokenInfo.isLoginRequired()) { 396 if (tokenInfo.isProtectedAuthenticationPath()) { 397 output.print("Please enter the user-PIN at the PIN-pad of your reader."); 398 output.flush(); 399 session.login(Session.UserType.USER, null); // the token prompts the PIN by other means; e.g. PIN-pad 400 } else { 401 output.print("Enter user-PIN and press [return key]: "); 402 output.flush(); 403 String userPINString = input.readLine(); 404 session.login(Session.UserType.USER, userPINString.toCharArray()); 405 } 406 } 407 output.println("################################################################################"); 408 409 return session ; 410 } 411 412 /** 413 * Lists all keys that match the given key template and lets the user choose 414 * one, if there is more than one. If there is a corresponding certificate for 415 * a key, this method displays the certificate for this key. 416 * 417 * @param session The session to use for key and certificate searching. 418 * @param keyTemplate The template for searching for keys. 419 * @param output The output stream to write the user prompts to. 420 * @param input The input stream where to read user input from. 421 * @return The selected key or null, if there is no matching key or the user 422 * canceled the operation. The return object also contains a 423 * corresponding certificate, if there is one for the selected key. 424 * @exception TokenException If searching for keys or certificates failed. 425 * @exception IOException If writing a user prompt faild or if reading user 426 * input failed. 427 * @preconditions (session <> null) 428 * and (keyTemplate <> keyTemplate) 429 * and (output <> null) 430 * and (input <> null) 431 * @postconditions (result <> null) 432 */ 433 public static KeyAndCertificate selectKeyAndCertificate(Session session, Key keyTemplate, 434 PrintWriter output, BufferedReader input) 435 throws TokenException, IOException 436 { 437 if (session == null) { 438 throw new NullPointerException("Argument \"session\" must not be null."); 439 } 440 if (keyTemplate == null) { 441 throw new NullPointerException("Argument \"keyTemplate\" must not be null."); 442 } 443 if (output == null) { 444 throw new NullPointerException("Argument \"output\" must not be null."); 445 } 446 if (input == null) { 447 throw new NullPointerException("Argument \"input\" must not be null."); 448 } 449 450 output.println("################################################################################"); 451 output.println("searching for keys"); 452 453 Vector keyList = new Vector(4); 454 455 session.findObjectsInit(keyTemplate); 456 Object[] matchingKeys; 457 458 while ((matchingKeys = session.findObjects(1)).length > 0) { 459 keyList.addElement(matchingKeys[0]); 460 } 461 session.findObjectsFinal(); 462 463 // try to find the corresponding certificates for the signature keys 464 Hashtable keyToCertificateTable = new Hashtable(4); 465 Enumeration keyListEnumeration = keyList.elements(); 466 while (keyListEnumeration.hasMoreElements()) { 467 PrivateKey signatureKey = (PrivateKey) keyListEnumeration.nextElement(); 468 byte[] keyID = signatureKey.getId().getByteArrayValue(); 469 X509PublicKeyCertificate certificateTemplate = new X509PublicKeyCertificate(); 470 certificateTemplate.getId().setByteArrayValue(keyID); 471 472 session.findObjectsInit(certificateTemplate); 473 Object[] correspondingCertificates = session.findObjects(1); 474 475 if (correspondingCertificates.length > 0) { 476 keyToCertificateTable.put(signatureKey, correspondingCertificates[0]); 477 } 478 session.findObjectsFinal(); 479 } 480 481 Key selectedKey = null; 482 X509PublicKeyCertificate correspondingCertificate = null; 483 if (keyList.size() == 0) { 484 output.println("Found NO matching key that can be used."); 485 } else if (keyList.size() == 1) { 486 // there is no choice, take this key 487 selectedKey = (Key) keyList.elementAt(0); 488 // create a IAIK JCE certificate from the PKCS11 certificate 489 correspondingCertificate = (X509PublicKeyCertificate) keyToCertificateTable.get(selectedKey); 490 String correspondingCertificateString = toString(correspondingCertificate); 491 output.println("Found just one private RSA signing key. This key will be used:"); 492 output.println(selectedKey); 493 output.println("--------------------------------------------------------------------------------"); 494 output.println("The certificate for this key is:"); 495 output.println((correspondingCertificateString != null) 496 ? correspondingCertificateString 497 : "<no certificate found>"); 498 } else { 499 // give the user the choice 500 output.println("found these private RSA signing keys:"); 501 Hashtable objectHandleToObjectMap = new Hashtable(keyList.size()); 502 Enumeration keyListEnumeration2 = keyList.elements(); 503 while (keyListEnumeration2.hasMoreElements()) { 504 Object signatureKey = (Object) keyListEnumeration2.nextElement(); 505 long objectHandle = signatureKey.getObjectHandle(); 506 objectHandleToObjectMap.put(new Long(objectHandle), signatureKey); 507 correspondingCertificate = (X509PublicKeyCertificate) keyToCertificateTable.get(signatureKey); 508 String correspondingCertificateString = toString(correspondingCertificate); 509 output.println("________________________________________________________________________________"); 510 output.println("RSA signature key with handle: " + objectHandle); 511 output.println(signatureKey); 512 output.println("--------------------------------------------------------------------------------"); 513 output.println("The certificate for this key is: "); 514 output.println((correspondingCertificateString != null) ? correspondingCertificateString : "<no certificate found>"); 515 output.println("________________________________________________________________________________"); 516 } 517 518 boolean gotObjectHandle = false; 519 Long selectedObjectHandle; 520 while (!gotObjectHandle) { 521 output.print("Enter the handle of the key to use for signing or 'x' to exit: "); 522 output.flush(); 523 String objectHandleString = input.readLine(); 524 if (objectHandleString.equalsIgnoreCase("x")) { 525 break; 526 } 527 try { 528 selectedObjectHandle = new Long(objectHandleString); 529 selectedKey = (RSAPrivateKey) objectHandleToObjectMap.get(selectedObjectHandle); 530 if (selectedKey != null) { 531 correspondingCertificate = (X509PublicKeyCertificate) keyToCertificateTable.get(selectedKey); 532 gotObjectHandle = true; 533 } else { 534 output.println("An object with the handle \"" + objectHandleString + "\" does not exist. Try again."); 535 } 536 } catch (NumberFormatException ex) { 537 output.println("The entered handle \"" + objectHandleString + "\" is invalid. Try again."); 538 } 539 } 540 } 541 542 output.println("################################################################################"); 543 544 return (selectedKey != null) 545 ? new KeyAndCertificate(selectedKey, correspondingCertificate) 546 : null ; 547 } 548 549 /** 550 * Gets a string representation of the given PKCS#11 certificate. 551 * 552 * @param certificate The PKCS#11 certificate. 553 * @return The string representing the certificate. 554 * @preconditions 555 * @postconditions 556 */ 557 public static String toString(X509PublicKeyCertificate certificate) { 558 String certificateString = null; 559 560 if (certificate != null) { 561 try { 562 X509Certificate correspondingCertificate = new X509Certificate(certificate.getValue().getByteArrayValue()); 563 certificateString = correspondingCertificate.toString(true); 564 } catch (Exception ex) { 565 certificateString = certificate.toString(); 566 } 567 } 568 569 return certificateString ; 570 } 571 572 }