001    // Copyright (C) 2002 IAIK
002    // https://jce.iaik.tugraz.at
003    //
004    // Copyright (C) 2003 - 2025 Stiftung Secure Information and
005    //                           Communication Technologies SIC
006    // https://sic.tech
007    //
008    // All rights reserved.
009    //
010    // Redistribution and use in source and binary forms, with or without
011    // modification, are permitted provided that the following conditions
012    // are met:
013    // 1. Redistributions of source code must retain the above copyright
014    //    notice, this list of conditions and the following disclaimer.
015    // 2. Redistributions in binary form must reproduce the above copyright
016    //    notice, this list of conditions and the following disclaimer in the
017    //    documentation and/or other materials provided with the distribution.
018    //
019    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
020    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
023    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
024    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
025    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
027    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
028    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
029    // SUCH DAMAGE.
030    
031    // Copyright (C) 2002 IAIK
032    // https://sic.tech/
033    //
034    // Copyright (C) 2003 - 2025 Stiftung Secure Information and 
035    //                           Communication Technologies SIC
036    // https://sic.tech/
037    //
038    // All rights reserved.
039    //
040    // This source is provided for inspection purposes and recompilation only,
041    // unless specified differently in a contract with IAIK. This source has to
042    // be kept in strict confidence and must not be disclosed to any third party
043    // under any circumstances. Redistribution in source and binary forms, with
044    // or without modification, are <not> permitted in any case!
045    //
046    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
047    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
048    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
049    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
050    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
051    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
052    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
053    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
054    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
055    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
056    // SUCH DAMAGE.
057    //
058    // $Header: /IAIK-CMS/current/src/demo/cms/pkcs11/PKCS11Demo.java 11    12.02.25 17:58 Dbratko $
059    // $Revision: 11 $
060    
061    package demo.cms.pkcs11;
062    
063    import iaik.cms.SecurityProvider;
064    import iaik.pkcs.pkcs11.provider.Constants;
065    import iaik.pkcs.pkcs11.provider.IAIKPkcs11;
066    import iaik.security.provider.IAIK;
067    
068    import java.io.IOException;
069    import java.security.GeneralSecurityException;
070    import java.security.KeyStore;
071    import java.security.NoSuchAlgorithmException;
072    import java.security.NoSuchProviderException;
073    import java.security.Provider;
074    import java.security.Security;
075    import java.util.Properties;
076    
077    /**
078     * Base class for PKCS#11 Demos.
079     */
080    public abstract class PKCS11Demo {
081      
082      /**
083       * Module name (native PKCS#11 module of the cryptographic hardware.
084       * It may be necessary to provide the file with the full path, if the
085       * module is not in the search path of the system).
086       */
087      protected String moduleName_ ;
088      
089      /**
090       * The user pin for the token key store.
091       */
092      protected char[] userPin_;
093    
094      /**
095       * The PKCS#11 JCE provider.
096       */
097      protected IAIKPkcs11 iaikPkcs11Provider_;
098    
099      /**
100       * The IAIK JCE software provider.
101       */
102      protected IAIK iaikSoftwareProvider_;
103      
104      /**
105       * The key store that represents the token (smart card) contents.
106       */
107      protected KeyStore tokenKeyStore_;
108      
109      /**
110       * Creates a PKCS11Demo object that has to be explicitly 
111       * {@link #init(String, char[]) initialized} with a module name.
112       */
113      protected PKCS11Demo() {
114      
115      }
116      
117      /**
118       * Creates a PKCS11Demo object for the given module name.
119       * 
120       * @param moduleName the name of the module
121       * @param userPin the user-pin (password) for the TokenKeyStore
122       *                (may be <code>null</code> to pop-up a dialog asking for the pin)
123       */
124      public PKCS11Demo(String moduleName,
125                        char[] userPin) {
126        
127        init(moduleName, userPin);
128      }
129      
130      /**
131       * Inits this PKCS11Demo object for the given module name.
132       * 
133       * @param moduleName the name of the module
134       * @param userPin the user-pin (password) for the TokenKeyStore
135       *                (may be <code>null</code> to pou-up a dialog asking for the pin)
136       */
137      public void init(String moduleName,
138                       char[] userPin) {
139        
140        if (moduleName == null) {
141          throw new NullPointerException("moduleName must not be null!");
142        }
143        
144        moduleName_ = moduleName;
145        userPin_ = userPin;
146        
147        
148        // check if we already have an installed provider for the requested module
149        int count = IAIKPkcs11.getProviderInstanceCount();
150        for (int i = 1; i <= count; i++) {
151          IAIKPkcs11 pkcs11Prov = IAIKPkcs11.getProviderInstance(i);
152          if (pkcs11Prov != null) {
153            String module = pkcs11Prov.getProperties().getProperty(Constants.PKCS11_NATIVE_MODULE);
154            if ((module != null) && (moduleName.equalsIgnoreCase(module))) {
155              iaikPkcs11Provider_ = pkcs11Prov;
156              break;
157            }
158          }  
159        }
160        
161        if (iaikPkcs11Provider_ == null) {      
162          // install IAIK PKCS#11 Provider
163          Properties pkcs11ProviderConfig = new Properties();
164          pkcs11ProviderConfig.put(Constants.PKCS11_NATIVE_MODULE, moduleName_);
165          iaikPkcs11Provider_ = new IAIKPkcs11(pkcs11ProviderConfig);
166        }  
167    
168        //IAIKPkcs11.insertProviderAtForJDK14(iaikPkcs11Provider__, 1); // add IAIK PKCS#11 JCE provider as first, use JDK 1.4 bug workaround
169        Security.addProvider(iaikPkcs11Provider_);
170        
171        // set CMS security provider
172        IaikPkcs11SecurityProvider pkcs11CmsSecurityProvider = new IaikPkcs11SecurityProvider(iaikPkcs11Provider_);
173        SecurityProvider.setSecurityProvider(pkcs11CmsSecurityProvider);
174    
175        System.out.println("Installed crypto providers:");
176        System.out.println();
177        Provider[] providers = Security.getProviders();
178        for (int i = 0; i < providers.length; i++) {
179          Provider provider = providers[i];
180          System.out.println("Provider " + (i  +1) + ": " + provider.getName() + "  version: " + provider.getVersion());
181        }
182      }
183      
184      /**
185       * This method gets the key store of the PKCS#11 provider and stores
186       * a reference at<code>pkcs11ClientKeystore_</code>.
187       *
188       * @throws GeneralSecurityException If anything with the provider fails.
189       * @throws IOException If loading the key store fails.
190       */
191      public void getKeyStore() throws GeneralSecurityException, IOException
192      {
193        // with this call we just get an uninitialized PKCS#11 key store, it is not bound to a
194        // specific IAIKPkcs11 provider instance after this call, even if you specify the provider
195        // at this call. this is a limitation of JCA KeyStore concept. the KeyStoreSPI object
196        // has no chance to get its own provider instance.
197        KeyStore tokenKeyStore = null;
198        try {
199          tokenKeyStore = KeyStore.getInstance("PKCS11KeyStore", iaikPkcs11Provider_.getName());
200        } catch (NoSuchProviderException ex) {
201          throw new GeneralSecurityException(ex.toString());
202        }
203    
204        if (tokenKeyStore == null) {
205          System.out.println("Got no key store. Ensure that the provider is properly configured and installed.");
206          System.exit(0);
207        }
208        try {
209          tokenKeyStore.load(null, userPin_); // this call binds the keystore to the first instance of the IAIKPkcs11 provider
210        } catch (NoSuchAlgorithmException ex) {
211          throw new GeneralSecurityException(ex.toString());
212        }
213    
214    
215        tokenKeyStore_ = tokenKeyStore;
216      }
217    
218    }
219    
220