    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.wrapper;
    045
    046    import java.io.File;
    047    import java.io.FileInputStream;
    048    import java.io.FileOutputStream;
    049    import java.io.IOException;
    050    import java.io.InputStream;
    051    import java.security.MessageDigest;
    052    import java.util.Arrays;
    053
    054    import iaik.pkcs.pkcs11.wrapper.CK_ATTRIBUTE;
    055    import iaik.pkcs.pkcs11.wrapper.CK_INFO;
    056    import iaik.pkcs.pkcs11.wrapper.CK_MECHANISM;
    057    import iaik.pkcs.pkcs11.wrapper.CK_MECHANISM_INFO;
    058    import iaik.pkcs.pkcs11.wrapper.CK_SESSION_INFO;
    059    import iaik.pkcs.pkcs11.wrapper.CK_SLOT_INFO;
    060    import iaik.pkcs.pkcs11.wrapper.CK_TOKEN_INFO;
    061    import iaik.pkcs.pkcs11.wrapper.Functions;
    062    import iaik.pkcs.pkcs11.wrapper.PKCS11;
    063    import iaik.pkcs.pkcs11.wrapper.PKCS11Connector;
    064    import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
    065    import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
    066
    067
    068
    069    /**
    070     * This is a simple class for testing the implementation.
    071     * Notice that this is an sample that may not run as is with many tokens.
    072     * It may be required to exclude some test methods in the main method.
    073     */
    074    public class SimpleTest {
    075
    076      protected static final String CERTIFICATE_FILE = "tokenCertificate.der";
    077
    078      protected static final String SIGNATURE_FILE = "signature.bin";
    079
    080      protected static final String DIGEST_FILE = "digest.dat";
    081
    082      protected PKCS11 myPKCS11Module_;
    083
    084      protected String userPin_;
    085
    086      protected long token_ = -1L;
    087
    088      protected long session_;
    089
    090      protected long[] objects_;
    091
    092      protected long signatureKeyHandle_;
    093
    094      protected long certificateHandle_;
    095
    096      protected byte[] derEncodedCertificate_;
    097
    098      protected File file_;
    099
    100      protected CK_MECHANISM signatureMechanism_;
    101
    102      protected CK_MECHANISM digestMechanism_;
    103
    104      protected MessageDigest messageDigest_;
    105
    106      protected byte[] signature_;
    107
    108      protected byte[] digest_;
    109
    110      public SimpleTest(String pkcs11Module, String userPin, File file)
    111        throws IOException, PKCS11Exception
    112      {
    113        System.out.print("trying to connect to PKCS#11 module: " + pkcs11Module);
    114        myPKCS11Module_ = PKCS11Connector.connectToPKCS11Module(pkcs11Module);
    115        userPin_ = userPin;
    116        file_ = file;
    117        signatureMechanism_ = new CK_MECHANISM();
    118        signatureMechanism_.mechanism = PKCS11Constants.CKM_SHA1_RSA_PKCS;
    119        signatureMechanism_.pParameter = null;
    120        digestMechanism_ = new CK_MECHANISM();
    121        digestMechanism_.mechanism = PKCS11Constants.CKM_SHA_1;
    122        digestMechanism_.pParameter = null;
    123        System.out.println(" FINISHED");
    124      }
    125
    126      public static void main(String[] args) {
    127        if (args.length != 3) {
    128          printUsage();
    129          System.exit(1);
    130        }
    131
    132        try {
    133          SimpleTest test = new SimpleTest(args[0], args[1], new File(args[2]));
    134
    135          test.initialize();
    136          test.getInfo();
    137          test.getSlotInfo();
    138          test.getTokenInfo();
    139          test.getMechanismInfo();
    140          //test.initToken();
    141          test.openROSession();
    142          test.getSessionInfo();
    143          test.findAllObjects();
    144          test.printAllObjects();
    145          test.loginUser();
    146          test.getSessionInfo();
    147          test.findAllObjects();
    148          test.printAllObjects();
    149          test.findSignatureKey();
    150          test.findCertificate();
    151          test.readCertificate();
    152          test.writeCertificateToFile();
    153          test.signData();
    154          test.writeSignatureToFile();
    155          test.digestData();
    156          test.writeDigestToFile();
    157          test.logout();
    158          test.closeSession();
    159
    160        } catch (Throwable thr) {
    161          thr.printStackTrace();
    162        }
    163      }
    164
    165      public static void printUsage() {
    166        System.out.println("Usage: SimepleTest <PKCS#11 module> <userPIN> <file to be signed>");
    167        System.out.println(" e.g.: SimpleTest pk2priv.dll password data.dat");
    168        System.out.println("The given DLL must be in the search path of the system.");
    169      }
    170
    171      public void initialize()
    172          throws PKCS11Exception
    173      {
    174        System.out.print("initializing... ");
    175        myPKCS11Module_.C_Initialize(null);
    176        System.out.println("FINISHED\n");
    177      }
    178
    179      public void getInfo()
    180          throws PKCS11Exception
    181      {
    182        System.out.println("getting info");
    183        CK_INFO moduleInfo = myPKCS11Module_.C_GetInfo();
    184        System.out.println("Module Info: ");
    185        System.out.println(moduleInfo);
    186        System.out.println("FINISHED\n");
    187      }
    188
    189      public void getSlotInfo()
    190          throws PKCS11Exception
    191      {
    192        System.out.println("getting slot list");
    193        long[] slotIDs = myPKCS11Module_.C_GetSlotList(false);
    194        CK_SLOT_INFO slotInfo;
    195        for (int i=0; i < slotIDs.length; i++) {
    196          System.out.println("Slot Info: ");
    197          slotInfo = myPKCS11Module_.C_GetSlotInfo(slotIDs[i]);
    198          System.out.println(slotInfo);
    199        }
    200        System.out.println("FINISHED\n");
    201      }
    202
    203      public void getTokenInfo()
    204          throws PKCS11Exception
    205      {
    206        System.out.println("getting token list");
    207        long[] tokenIDs = myPKCS11Module_.C_GetSlotList(true);
    208        CK_TOKEN_INFO tokenInfo;
    209        for (int i=0; i < tokenIDs.length; i++) {
    210          System.out.println("Token Info: ");
    211          tokenInfo = myPKCS11Module_.C_GetTokenInfo(tokenIDs[i]);
    212          System.out.println(tokenInfo);
    213          if (token_ == -1L) {
    214            token_ = tokenIDs[i];
    215          }
    216        }
    217        System.out.println("FINISHED\n");
    218      }
    219
    220      public void getMechanismInfo()
    221          throws PKCS11Exception
    222      {
    223        CK_MECHANISM_INFO mechanismInfo;
    224
    225        System.out.println("getting mechanism list");
    226        System.out.println("getting slot list");
    227        long[] slotIDs = myPKCS11Module_.C_GetSlotList(true);
    228        for (int i=0; i < slotIDs.length; i++) {
    229          System.out.println("getting mechanism list for slot " + slotIDs[i]);
    230          long[] mechanismIDs = myPKCS11Module_.C_GetMechanismList(slotIDs[i]);
    231          for (int j=0; j < mechanismIDs.length; j++) {
    232            System.out.println("mechanism info for mechanism " + Functions.mechanismCodeToString(mechanismIDs[j]) +
    233             ": ");
    234            mechanismInfo = myPKCS11Module_.C_GetMechanismInfo(slotIDs[i],
    235                     mechanismIDs[j]);
    236            System.out.println(mechanismInfo);
    237          }
    238        }
    239        System.out.println("FINISHED\n");
    240      }
    241
    242      public void initToken()
    243          throws PKCS11Exception
    244      {
    245        String label = "The Label!                      ";
    246        String pin = "password";
    247
    248        System.out.println("init token");
    249        long[] slotIDs = myPKCS11Module_.C_GetSlotList(false);
    250        myPKCS11Module_.C_InitToken(slotIDs[0], pin.toCharArray(), label.toCharArray());
    251        System.out.println("FINISHED");
    252      }
    253
    254      public void openROSession()
    255          throws PKCS11Exception
    256      {
    257        System.out.println("open RO session");
    258        session_ = myPKCS11Module_.C_OpenSession(token_, PKCS11Constants.CKF_SERIAL_SESSION, null, null);
    259        System.out.println("FINISHED\n");
    260      }
    261
    262      public void getSessionInfo()
    263          throws PKCS11Exception
    264      {
    265        System.out.println("get session info");
    266        CK_SESSION_INFO sessionInfo;
    267        System.out.println("Session Info: ");
    268        sessionInfo = myPKCS11Module_.C_GetSessionInfo(session_);
    269        System.out.println(sessionInfo);
    270        System.out.println("FINISHED\n");
    271      }
    272
    273      public void findAllObjects()
    274          throws PKCS11Exception
    275      {
    276        System.out.println("find all objects");
    277        myPKCS11Module_.C_FindObjectsInit(session_, null);
    278        objects_ = myPKCS11Module_.C_FindObjects(session_, 100); //maximum of 100 at once
    279        if (objects_ == null) {
    280          System.out.println("null returned - no objects found");
    281        } else {
    282          System.out.println("found " + objects_.length + " objects");
    283        }
    284        myPKCS11Module_.C_FindObjectsFinal(session_);
    285        System.out.println("FINISHED\n");
    286      }
    287
    288      public void printAllObjects()
    289          throws PKCS11Exception
    290      {
    291        System.out.println("print all objects");
    292
    293        for (int i = 0; i < objects_.length; i++) {
    294          System.out.println("object No. " + i);
    295          CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[1];
    296          template[0] = new CK_ATTRIBUTE();
    297          template[0].type = PKCS11Constants.CKA_CLASS;
    298          myPKCS11Module_.C_GetAttributeValue(session_, objects_[i], template);
    299          System.out.println("CKA_CLASS: " + Functions.classTypeToString(((Long) template[0].pValue).longValue()));
    300        }
    301
    302        System.out.println("FINISHED\n");
    303      }
    304
    305      public void loginUser()
    306          throws PKCS11Exception
    307      {
    308        System.out.println("login user to session with password \"" + userPin_ + "\"");
    309        myPKCS11Module_.C_Login(session_, PKCS11Constants.CKU_USER, userPin_.toCharArray());
    310        System.out.println("FINISHED\n");
    311      }
    312
    313      public void findSignatureKey()
    314          throws PKCS11Exception
    315      {
    316        System.out.println("find signature key");
    317        CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[2];
    318
    319        attributeTemplateList[0] = new CK_ATTRIBUTE();
    320        attributeTemplateList[0].type = PKCS11Constants.CKA_CLASS;
    321        attributeTemplateList[0].pValue = new Long(PKCS11Constants.CKO_PRIVATE_KEY);
    322        attributeTemplateList[1] = new CK_ATTRIBUTE();
    323        attributeTemplateList[1].type = PKCS11Constants.CKA_SIGN;
    324        attributeTemplateList[1].pValue = new Boolean(PKCS11Constants.TRUE);
    325
    326        myPKCS11Module_.C_FindObjectsInit(session_, attributeTemplateList);
    327        long[] availableSignatureKeys = myPKCS11Module_.C_FindObjects(session_, 100); //maximum of 100 at once
    328        if (availableSignatureKeys == null) {
    329          System.out.println("null returned - no signature key found");
    330        } else {
    331          System.out.println("found " + availableSignatureKeys.length + " signature keys");
    332          for (int i=0; i < availableSignatureKeys.length; i++) {
    333            if (i == 0) { // the first we find, we take as our signature key
    334              signatureKeyHandle_ = availableSignatureKeys[i];
    335              System.out.print("for signing we use ");
    336            }
    337            System.out.println("signature key " + i);
    338          }
    339        }
    340        myPKCS11Module_.C_FindObjectsFinal(session_);
    341        System.out.println("FINISHED\n");
    342      }
    343
    344      public void findCertificate()
    345          throws PKCS11Exception
    346      {
    347        System.out.println("find certificate");
    348
    349        // first get the ID of the signature key
    350        CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[1];
    351        attributeTemplateList[0] = new CK_ATTRIBUTE();
    352        attributeTemplateList[0].type = PKCS11Constants.CKA_ID;
    353
    354        myPKCS11Module_.C_GetAttributeValue(session_, signatureKeyHandle_ , attributeTemplateList);
    355        byte[] keyAndCertificateID = (byte[]) attributeTemplateList[0].pValue;
    356        System.out.println("ID of siganture key: " + Functions.toHexString(keyAndCertificateID));
    357
    358        // now get the certificate with the same ID as the signature key
    359        attributeTemplateList = new CK_ATTRIBUTE[2];
    360
    361        attributeTemplateList[0] = new CK_ATTRIBUTE();
    362        attributeTemplateList[0].type = PKCS11Constants.CKA_CLASS;
    363        attributeTemplateList[0].pValue = new Long(PKCS11Constants.CKO_CERTIFICATE);
    364        attributeTemplateList[1] = new CK_ATTRIBUTE();
    365        attributeTemplateList[1].type = PKCS11Constants.CKA_ID;
    366        attributeTemplateList[1].pValue = keyAndCertificateID;
    367
    368        myPKCS11Module_.C_FindObjectsInit(session_, attributeTemplateList);
    369        long[] availableCertificates = myPKCS11Module_.C_FindObjects(session_, 100); //maximum of 100 at once
    370        if (availableCertificates == null) {
    371          System.out.println("null returned - no certificate found");
    372        } else {
    373          System.out.println("found " + availableCertificates.length + " certificates with matching ID");
    374          for (int i=0; i < availableCertificates.length; i++) {
    375            if (i == 0) { // the first we find, we take as our certificate
    376              certificateHandle_ = availableCertificates[i];
    377              System.out.print("for verification we use ");
    378            }
    379            System.out.println("certificate " + i);
    380          }
    381        }
    382        myPKCS11Module_.C_FindObjectsFinal(session_);
    383        System.out.println("FINISHED\n");
    384      }
    385
    386      public void readCertificate()
    387          throws PKCS11Exception
    388      {
    389        System.out.println("read certificate");
    390
    391        CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[1];
    392        template[0] = new CK_ATTRIBUTE();
    393        template[0].type = PKCS11Constants.CKA_VALUE;
    394        myPKCS11Module_.C_GetAttributeValue(session_, certificateHandle_ , template);
    395        derEncodedCertificate_ = (byte[]) template[0].pValue;
    396        System.out.println("DER encoded certificate (" + derEncodedCertificate_.length + " bytes):");
    397        System.out.println(Functions.toHexString(derEncodedCertificate_));
    398
    399        System.out.println("FINISHED\n");
    400      }
    401
    402      public void writeCertificateToFile()
    403          throws IOException, PKCS11Exception
    404      {
    405        System.out.println("write certificate to file: " + CERTIFICATE_FILE);
    406
    407        FileOutputStream fos = new FileOutputStream(CERTIFICATE_FILE);
    408        fos.write(derEncodedCertificate_);
    409        fos.flush();
    410        fos.close();
    411
    412        System.out.println("FINISHED\n");
    413      }
    414
    415      public void signData()
    416          throws IOException, PKCS11Exception
    417      {
    418        byte[] buffer = new byte[1024];
    419        byte[] helpBuffer;
    420        int bytesRead;
    421
    422        InputStream dataInput = new FileInputStream(file_);
    423        myPKCS11Module_.C_SignInit(session_, signatureMechanism_, signatureKeyHandle_);
    424        while ((bytesRead = dataInput.read(buffer, 0, buffer.length)) >= 0) {
    425          helpBuffer = new byte[bytesRead]; // we need a buffer that only holds what to send for signing
    426          System.arraycopy(buffer, 0, helpBuffer, 0, bytesRead);
    427          myPKCS11Module_.C_SignUpdate(session_, helpBuffer);
    428          Arrays.fill(helpBuffer, (byte) 0);
    429        }
    430        Arrays.fill(buffer, (byte) 0);
    431        signature_ = myPKCS11Module_.C_SignFinal(session_);
    432      }
    433
    434      public void writeSignatureToFile()
    435          throws IOException, PKCS11Exception
    436      {
    437        System.out.println("write signature to file: " + SIGNATURE_FILE);
    438
    439        FileOutputStream fos = new FileOutputStream(SIGNATURE_FILE);
    440        fos.write(signature_);
    441        fos.flush();
    442        fos.close();
    443
    444        System.out.println("FINISHED");
    445      }
    446
    447      public void digestData()
    448          throws IOException, PKCS11Exception
    449      {
    450        byte[] buffer = new byte[1024];
    451        byte[] helpBuffer, testDigest;
    452        int bytesRead;
    453
    454        System.out.println("Digest Data");
    455        myPKCS11Module_.C_DigestInit(session_, digestMechanism_);
    456        try {
    457          messageDigest_ = MessageDigest.getInstance("SHA-1");
    458        } catch (Exception e) {
    459          System.out.println(e);
    460        }
    461        InputStream dataInput = new FileInputStream(file_);
    462       while ((bytesRead = dataInput.read(buffer, 0, buffer.length)) >= 0) {
    463          helpBuffer = new byte[bytesRead]; // we need a buffer that only holds what to send for digesting
    464          System.arraycopy(buffer, 0, helpBuffer, 0, bytesRead);
    465          myPKCS11Module_.C_DigestUpdate(session_, helpBuffer);
    466          messageDigest_.update(helpBuffer);
    467          Arrays.fill(helpBuffer, (byte) 0);
    468        }
    469        Arrays.fill(buffer, (byte) 0);
    470        digest_ = myPKCS11Module_.C_DigestFinal(session_);
    471        testDigest = messageDigest_.digest();
    472        System.out.println("PKCS11digest:"+Functions.toHexString(digest_));
    473        System.out.println("TestDigest  :"+Functions.toHexString(testDigest));
    474        System.out.println("FINISHED\n");
    475      }
    476
    477      public void writeDigestToFile()
    478          throws IOException, PKCS11Exception
    479      {
    480        System.out.println("write digest to file: " + DIGEST_FILE);
    481
    482        FileOutputStream fos = new FileOutputStream(DIGEST_FILE);
    483        fos.write(digest_);
    484        fos.flush();
    485        fos.close();
    486
    487        System.out.println("FINISHED\n");
    488      }
    489
    490      public void logout()
    491          throws PKCS11Exception
    492      {
    493        System.out.println("logout session");
    494        myPKCS11Module_.C_Logout(session_);
    495        System.out.println("FINISHED\n");
    496      }
    497
    498      public void closeSession()
    499          throws PKCS11Exception
    500      {
    501        System.out.println("close session");
    502        myPKCS11Module_.C_CloseSession(session_);
    503        System.out.println("FINISHED\n");
    504      }
    505
    506
    507    }