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.InputStreamReader;
048 import java.io.PrintWriter;
049 import java.util.Hashtable;
050 import java.util.Iterator;
051 import java.util.List;
052 import java.util.Vector;
053
054 import iaik.pkcs.pkcs11.Module;
055 import iaik.pkcs.pkcs11.Session;
056 import iaik.pkcs.pkcs11.Slot;
057 import iaik.pkcs.pkcs11.Token;
058 import iaik.pkcs.pkcs11.objects.Attribute;
059 import iaik.pkcs.pkcs11.objects.BooleanAttribute;
060 import iaik.pkcs.pkcs11.objects.GenericTemplate;
061 import iaik.pkcs.pkcs11.objects.Object;
062 import iaik.pkcs.pkcs11.objects.PrivateKey;
063 import iaik.pkcs.pkcs11.objects.X509PublicKeyCertificate;
064
065
066
067 /**
068 * This class demonstrates how to use the GenericSearchTemplate class.
069 *
070 * @author <a href="mailto:Karl.Scheibelhofer@iaik.at"> Karl Scheibelhofer </a>
071 * @version 0.1
072 * @invariants
073 */
074 public class GenericFind {
075
076 static PrintWriter output_;
077
078 static BufferedReader input_;
079
080 static {
081 try {
082 //output_ = new PrintWriter(new FileWriter("GetInfo_output.txt"), true);
083 output_ = new PrintWriter(System.out, true);
084 input_ = new BufferedReader(new InputStreamReader(System.in));
085 } catch (Throwable thr) {
086 thr.printStackTrace();
087 output_ = new PrintWriter(System.out, true);
088 input_ = new BufferedReader(new InputStreamReader(System.in));
089 }
090 }
091
092 public static void main(String[] args) {
093 if ((args.length != 1) && (args.length != 2)) {
094 printUsage();
095 System.exit(1);
096 }
097
098 try {
099
100 Module pkcs11Module = Module.getInstance(args[0]);
101 pkcs11Module.initialize(null);
102
103 Slot[] slots = pkcs11Module.getSlotList(Module.SlotRequirement.TOKEN_PRESENT);
104
105 if (slots.length == 0) {
106 output_.println("No slot with present token found!");
107 System.exit(0);
108 }
109
110 Slot selectedSlot = slots[0];
111 Token token = selectedSlot.getToken();
112
113 Session session =
114 token.openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RO_SESSION, null, null);
115
116 // if we have the user PIN, we login the session, this enables us to find private objects too
117 if (args.length == 2) {
118 session.login(Session.UserType.USER, args[1].toCharArray());
119 }
120
121 output_.println("################################################################################");
122 output_.println("Find all signature keys.");
123 GenericTemplate signatureKeyTemplate = new GenericTemplate();
124 BooleanAttribute signAttribute = new BooleanAttribute(Attribute.SIGN);
125 signAttribute.setBooleanValue(Boolean.TRUE);
126 signatureKeyTemplate.addAttribute(signAttribute);
127
128 // this find operation will find all objects that posess a CKA_SIGN attribute with value true
129 session.findObjectsInit(signatureKeyTemplate);
130
131 Object[] foundSignatureKeyObjects = session.findObjects(1); // find first
132
133 List signatureKeys = null;
134 if (foundSignatureKeyObjects.length > 0) {
135 signatureKeys = new Vector();
136 output_.println("________________________________________________________________________________");
137 output_.println(foundSignatureKeyObjects[0]);
138 signatureKeys.add(foundSignatureKeyObjects[0]);
139 while ((foundSignatureKeyObjects = session.findObjects(1)).length > 0) {
140 output_.println("________________________________________________________________________________");
141 output_.println(foundSignatureKeyObjects[0]);
142 signatureKeys.add(foundSignatureKeyObjects[0]);
143 }
144 output_.println("________________________________________________________________________________");
145 } else {
146 output_.println("There is no object with a CKA_SIGN attribute set to true.");
147 output_.flush();
148 System.exit(0);
149 }
150 session.findObjectsFinal();
151
152 output_.println("################################################################################");
153
154
155 output_.println("################################################################################");
156 output_.println("Find corresponding certificates for private signature keys.");
157
158 List privateSignatureKeys = new Vector();
159
160 // sort out all signature keys that are private keys
161 Iterator signatureKeysIterator = signatureKeys.iterator();
162 while (signatureKeysIterator.hasNext()) {
163 Object signatureKey = (Object) signatureKeysIterator.next();
164 if (signatureKey instanceof PrivateKey) {
165 privateSignatureKeys.add(signatureKey);
166 }
167 }
168
169 // for each private signature key try to find a public key certificate with the same ID
170 Iterator privateSignatureKeysIterator = privateSignatureKeys.iterator();
171 Hashtable privateKeyToCertificateTable = new Hashtable(privateSignatureKeys.size());
172 while (privateSignatureKeysIterator.hasNext()) {
173 PrivateKey privateSignatureKey = (PrivateKey) privateSignatureKeysIterator.next();
174 byte[] keyID = privateSignatureKey.getId().getByteArrayValue();
175 // this is the implementation that uses a concrete object class (X509PublicKeyCertificate) for searching
176 X509PublicKeyCertificate certificateSearchTemplate = new X509PublicKeyCertificate();
177 certificateSearchTemplate.getId().setByteArrayValue(keyID);
178 /*
179 // this is the implementation that uses GenericSearchTemplate class for searching, the same effect as above
180 GenericTemplate certificateSearchTemplate = new GenericTemplate();
181 LongAttribute objectClassAttribute = new LongAttribute(PKCS11Constants.CKA_CLASS);
182 objectClassAttribute.setLongValue(new Long(PKCS11Constants.CKO_CERTIFICATE));
183 certificateSearchTemplate.addAttribute(objectClassAttribute);
184 LongAttribute certificateTypeAttribute = new LongAttribute(PKCS11Constants.CKA_CERTIFICATE_TYPE);
185 certificateTypeAttribute.setLongValue(new Long(PKCS11Constants.CKC_X_509));
186 certificateSearchTemplate.addAttribute(certificateTypeAttribute);
187 ByteArrayAttribute idAttribute = new ByteArrayAttribute(PKCS11Constants.CKA_ID);
188 idAttribute.setByteArrayValue(keyID);
189 certificateSearchTemplate.addAttribute(idAttribute);
190 */
191
192 session.findObjectsInit(certificateSearchTemplate);
193
194 Object[] foundCertificateObjects;
195 if ((foundCertificateObjects = session.findObjects(1)).length > 0) {
196 privateKeyToCertificateTable.put(privateSignatureKey, foundCertificateObjects[0]);
197 output_.println("________________________________________________________________________________");
198 output_.println("The certificate for this private signature key");
199 output_.println(privateSignatureKey);
200 output_.println("--------------------------------------------------------------------------------");
201 output_.println("is");
202 output_.println(foundCertificateObjects[0]);
203 output_.println("________________________________________________________________________________");
204 } else {
205 output_.println("________________________________________________________________________________");
206 output_.println("There is no certificate for this private signature key");
207 output_.println(privateSignatureKey);
208 output_.println("________________________________________________________________________________");
209 }
210
211 session.findObjectsFinal();
212 }
213
214 output_.println("################################################################################");
215
216 session.closeSession();
217 pkcs11Module.finalize(null);
218
219 } catch (Throwable thr) {
220 thr.printStackTrace();
221 } finally {
222 output_.close();
223 }
224 }
225
226 public static void printUsage() {
227 output_.println("Usage: GenericFind <PKCS#11 module> [<userPIN>]");
228 output_.println(" e.g.: GenericFind pk2priv.dll password");
229 output_.println("The given DLL must be in the search path of the system.");
230 }
231
232 }