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.FileInputStream;
047    import java.io.InputStream;
048    import java.math.BigInteger;
049    import java.security.MessageDigest;
050    import java.util.Arrays;
051    
052    import iaik.pkcs.pkcs11.Mechanism;
053    import iaik.pkcs.pkcs11.Module;
054    import iaik.pkcs.pkcs11.Session;
055    import iaik.pkcs.pkcs11.Slot;
056    import iaik.pkcs.pkcs11.Token;
057    
058    
059    
060    /**
061     * This demo program connects to two different modules and calculates hash
062     * values with both of them. This program uses SHA-1. It demonstrates that it is
063     * possible to work with two independent module at the same time. By now, I did
064     * not conduct any real multi-threaded tests.
065     *
066     * @author <a href="mailto:Karl.Scheibelhofer@iaik.at"> Karl Scheibelhofer </a>
067     * @version 0.1
068     * @invariants
069     */
070    public class ConcurrentHash {
071    
072      public static void main(String[] args) {
073        if (args.length == 3){
074          try {
075            System.out.println("################################################################################");
076            System.out.println("load and initialize module: " + args[0]);
077            Module pkcs11Module1 = Module.getInstance(args[0]);
078            pkcs11Module1.initialize(null);
079            System.out.println("load and initialize module: " + args[1]);
080            Module pkcs11Module2 = Module.getInstance(args[1]);
081            pkcs11Module2.initialize(null);
082            System.out.println("################################################################################");
083    
084    
085            System.out.println("################################################################################");
086            System.out.println("getting tokens");
087    
088            Slot[] slotsWithToken1 = pkcs11Module1.getSlotList(Module.SlotRequirement.TOKEN_PRESENT);
089            if (slotsWithToken1.length < 1) {
090              System.err.println("No token present for module: " + pkcs11Module1.getInfo());
091              System.exit(1);
092            }
093            Token token1 = slotsWithToken1[0].getToken();
094            System.out.println("________________________________________________________________________________");
095            System.out.println("token #1:");
096            System.out.println(token1.getTokenInfo());
097            System.out.println("________________________________________________________________________________");
098    
099            Slot[] slotsWithToken2 = pkcs11Module2.getSlotList(Module.SlotRequirement.TOKEN_PRESENT);
100            if (slotsWithToken2.length < 1) {
101              System.err.println("No token present for module: " + pkcs11Module2.getInfo());
102              System.exit(1);
103            }
104            Token token2 = slotsWithToken2[0].getToken();
105            System.out.println("________________________________________________________________________________");
106            System.out.println("token #2:");
107            System.out.println(token2.getTokenInfo());
108            System.out.println("________________________________________________________________________________");
109            System.out.println("################################################################################");
110    
111    
112            System.out.println("################################################################################");
113            System.out.println("opening sessions");
114            Session session1 = token1.
115                openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RO_SESSION, null, null);
116            Session session2 = token2.
117                openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RO_SESSION, null, null);
118    
119            System.out.println("opening data file: " + args[2]);
120            InputStream dataInputStream = new FileInputStream(args[2]);
121    
122            //be sure that your token can process the specified mechanism
123            Mechanism digestMechanism = Mechanism.SHA_1;
124            // initialize for digesting
125            System.out.println("initializing sessions for hashing");
126            session1.digestInit(digestMechanism);
127            session2.digestInit(digestMechanism);
128    
129            byte[] dataBuffer = new byte[1024];
130            byte[] helpBuffer;
131            int bytesRead;
132    
133            // feed in all data from the input stream
134            while ((bytesRead = dataInputStream.read(dataBuffer)) >= 0) {
135              helpBuffer = new byte[bytesRead]; // we need a buffer that only holds what to send for digesting
136              System.arraycopy(dataBuffer, 0, helpBuffer, 0, bytesRead);
137              session1.digestUpdate(helpBuffer);
138              session2.digestUpdate(helpBuffer);
139              Arrays.fill(helpBuffer, (byte) 0); // ensure that no data is left in the memory
140            }
141            Arrays.fill(dataBuffer, (byte) 0); // ensure that no data is left in the memory
142    
143            byte[] digestValue1 = session1.digestFinal();
144            byte[] digestValue2 = session2.digestFinal();
145    
146            System.out.println("The SHA-1 hash value #1 is: " + new BigInteger(1, digestValue1).toString(16));
147            System.out.println("The SHA-1 hash value #2 is: " + new BigInteger(1, digestValue2).toString(16));
148    
149            if (Arrays.equals(digestValue1, digestValue2)) {
150              System.out.println("The hash values are equal.");
151            } else {
152              System.out.println("The hash values are different. Test failed");
153            }
154    
155            System.out.println("closing sessions");
156            session1.closeSession();
157            session2.closeSession();
158            System.out.println("################################################################################");
159    
160    
161            System.out.println("################################################################################");
162            System.out.println("verifying hash with software digest");
163    
164            MessageDigest softwareDigestEngine = MessageDigest.getInstance("SHA-1");
165    
166            dataInputStream = new FileInputStream(args[2]);
167    
168            // feed in all data from the input stream
169            while ((bytesRead = dataInputStream.read(dataBuffer)) >= 0) {
170              softwareDigestEngine.update(dataBuffer, 0, bytesRead);
171            }
172            dataInputStream.close();
173            byte[] softwareDigestValue = softwareDigestEngine.digest();
174    
175            Arrays.fill(dataBuffer, (byte) 0); // ensure that no data is left in the memory
176    
177            System.out.println("The software digest value is: " + new BigInteger(1, softwareDigestValue).toString(16));
178    
179            if (Arrays.equals(digestValue1, softwareDigestValue) && Arrays.equals(digestValue2, softwareDigestValue)) {
180              System.out.println("All SHA-1 hash values are equal. Test passed successfully.");
181            } else {
182              System.out.println("Verification of hash value FAILED!");
183            }
184    
185            System.out.println("################################################################################");
186    
187          } catch (Throwable ex) {
188            ex.printStackTrace();
189          }
190        } else {
191          printUsage();
192        }
193        System.gc(); // to finalize and disconnect the modules
194      }
195    
196      protected static void printUsage() {
197        System.out.println("ConcurrentHash <PKCS#11 module name #1> <PKCS#11 module name #2> <data>");
198        System.out.println("e.g.: ConcurrentHash pk2priv.dll softtoken.dll data.dat");
199        System.out.println("Both modules must support hashing without the user being logged in.");
200      }
201    
202    }