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 }