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