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 }