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.File; 048 import java.io.FileOutputStream; 049 import java.io.InputStreamReader; 050 import java.io.PrintWriter; 051 import java.util.Hashtable; 052 053 import iaik.pkcs.pkcs11.DefaultInitializeArgs; 054 import iaik.pkcs.pkcs11.Info; 055 import iaik.pkcs.pkcs11.Module; 056 import iaik.pkcs.pkcs11.Session; 057 import iaik.pkcs.pkcs11.SessionInfo; 058 import iaik.pkcs.pkcs11.Token; 059 import iaik.pkcs.pkcs11.TokenInfo; 060 import iaik.pkcs.pkcs11.objects.Attribute; 061 import iaik.pkcs.pkcs11.objects.ByteArrayAttribute; 062 import iaik.pkcs.pkcs11.objects.Object; 063 import iaik.pkcs.pkcs11.objects.X509AttributeCertificate; 064 import iaik.pkcs.pkcs11.objects.X509PublicKeyCertificate; 065 066 067 068 /** 069 * This demo program lists information about a library, the available slots, 070 * the available tokens and the objects on them. It takes the name of the module 071 * and prompts the user PIN. If the user PIN is not available, 072 * the program will list only public objects but no private objects; i.e. as 073 * defined in PKCS#11 for public read-only sessions. 074 * 075 * @author <a href="mailto:Karl.Scheibelhofer@iaik.at"> Karl Scheibelhofer </a> 076 * @version 0.1 077 * @invariants 078 */ 079 public class DumpObjects { 080 081 static PrintWriter output_; 082 083 static BufferedReader input_; 084 085 static { 086 try { 087 //output_ = new PrintWriter(new FileWriter("GetInfo_output.txt"), true); 088 output_ = new PrintWriter(System.out, true); 089 input_ = new BufferedReader(new InputStreamReader(System.in)); 090 } catch (Throwable thr) { 091 thr.printStackTrace(); 092 output_ = new PrintWriter(System.out, true); 093 input_ = new BufferedReader(new InputStreamReader(System.in)); 094 } 095 } 096 097 public static void main(String[] args) { 098 if (args.length >= 2) { 099 String outputDirectroyName = args[1]; 100 File outputDirectory = new File(outputDirectroyName); 101 if (outputDirectory.exists() && !outputDirectory.isDirectory()) { 102 output_.println(outputDirectroyName + " is not a directory!"); 103 System.exit(1); 104 } 105 106 try { 107 // create directory if not present 108 if (!outputDirectory.exists()) { 109 outputDirectory.mkdirs(); 110 } 111 112 String moduleName = args[0]; 113 output_.println("################################################################################"); 114 output_.println("load and initialize module: " + moduleName); 115 output_.flush(); 116 Module pkcs11Module = Module.getInstance(moduleName); 117 118 if (args.length == 2) { 119 pkcs11Module.initialize(null); 120 } else { 121 DefaultInitializeArgs arguments = new DefaultInitializeArgs(); 122 byte[] stringBytes = args[2].getBytes(); 123 byte[] reservedBytes = new byte[stringBytes.length + 5]; 124 System.arraycopy(stringBytes, 0, reservedBytes, 0, stringBytes.length); 125 arguments.setReserved(reservedBytes); 126 pkcs11Module.initialize(arguments); 127 } 128 129 Info info = pkcs11Module.getInfo(); 130 output_.println(info); 131 output_.println("################################################################################"); 132 133 Token token = Util.selectToken(pkcs11Module, output_, input_); 134 if (token == null) { 135 output_.println("We have no token to proceed. Finished."); 136 output_.flush(); 137 System.exit(0); 138 } 139 140 output_.println("################################################################################"); 141 output_.println("dumping objects for token: "); 142 TokenInfo tokenInfo = token.getTokenInfo(); 143 output_.println(tokenInfo); 144 Session session = token 145 .openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RO_SESSION, null, null); 146 147 if (tokenInfo.isLoginRequired()) { 148 if (tokenInfo.isProtectedAuthenticationPath()) { 149 session.login(Session.UserType.USER, null); // the token prompts the PIN by other means; e.g. PIN-pad 150 } else { 151 output_.print("Enter user-PIN or press [return] to list just public objects: "); 152 output_.flush(); 153 String userPINString = input_.readLine(); 154 output_.println(); 155 output_.print("listing all" + ((userPINString.length() > 0) ? "" : " public") + " objects on token"); 156 if (userPINString.length() > 0) { 157 // login user 158 session.login(Session.UserType.USER, userPINString.toCharArray()); 159 } 160 } 161 } 162 SessionInfo sessionInfo = session.getSessionInfo(); 163 output_.println(" using session:"); 164 output_.println(sessionInfo); 165 166 String pathSepatator = System.getProperty("file.separator"); 167 168 session.findObjectsInit(null); 169 Object[] objects = session.findObjects(1); 170 171 while ((objects.length > 0) && (objects[0] != null)) { 172 Object object = objects[0]; 173 output_.println("--------------------------------------------------------------------------------"); 174 long handle = object.getObjectHandle(); 175 output_.println("Dumping object with handle " + handle); 176 String textDumpFilename = outputDirectroyName + pathSepatator + handle + ".txt"; 177 output_.println("Dumping text output to file " + textDumpFilename); 178 FileOutputStream textDumpStream = new FileOutputStream(textDumpFilename); 179 textDumpStream.write(object.toString().getBytes("UTF-8")); 180 textDumpStream.flush(); 181 textDumpStream.close(); 182 183 Hashtable attributes = object.getAttributeTable(); 184 if (attributes.containsKey(Attribute.VALUE)) { 185 ByteArrayAttribute valueAttribute = (ByteArrayAttribute) attributes.get(Attribute.VALUE); 186 byte[] value = valueAttribute.getByteArrayValue(); 187 if (value != null) { 188 String valueDumpFilename = outputDirectroyName + pathSepatator + handle + ".value.bin"; 189 output_.println("Dumping value attribut to file " + valueDumpFilename); 190 FileOutputStream valueDumpStream = new FileOutputStream(valueDumpFilename); 191 valueDumpStream.write(value); 192 valueDumpStream.flush(); 193 valueDumpStream.close(); 194 if ((object instanceof X509PublicKeyCertificate) || (object instanceof X509AttributeCertificate)) { 195 String certificateDumpFilename = outputDirectroyName + pathSepatator + handle + ".der.cer"; 196 output_.println("Dumping DER encoding of certificate to file " + certificateDumpFilename); 197 FileOutputStream certificateDumpStream = new FileOutputStream(certificateDumpFilename); 198 certificateDumpStream.write(value); 199 certificateDumpStream.flush(); 200 certificateDumpStream.close(); 201 } 202 } 203 } 204 205 output_.println("--------------------------------------------------------------------------------"); 206 objects = session.findObjects(1); 207 } 208 session.findObjectsFinal(); 209 210 session.closeSession(); 211 output_.println("################################################################################"); 212 213 pkcs11Module.finalize(null); 214 } catch (Throwable ex) { 215 ex.printStackTrace(); 216 } 217 } else { 218 printUsage(); 219 } 220 System.gc(); // to finalize and disconnect the pkcs11Module 221 } 222 223 protected static void printUsage() { 224 output_.println("DumpObjects <PKCS#11 module name> <output directory> [<initialization parameters>]"); 225 output_.println("e.g.: DumpObjects slbck.dll dumpdir"); 226 } 227 228 }