    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    }