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/keystore/CMSKeyStore.java 29    12.02.25 17:58 Dbratko $
029// $Revision: 29 $
030//
031
032package demo.keystore;
033
034import iaik.cms.CertificateIdentifier;
035import iaik.cms.KeyIdentifier;
036import iaik.cms.SecurityProvider;
037import iaik.smime.ess.utils.KeyStoreDatabase;
038import iaik.utils.Util;
039import iaik.x509.X509Certificate;
040
041import java.io.File;
042import java.io.FileInputStream;
043import java.security.KeyStore;
044import java.security.PrivateKey;
045
046/**
047 * KeyStore repository used providing keys and certificates
048 * for the several CMS and S/MIME demos.
049 * <p>
050 * Reads and loads keys and certificates from an IaikKeyStore
051 * files and provides methods to access the keys and certificates
052 * based on algorithm name and algorithm type.
053 */
054public class CMSKeyStore implements CMSKeyStoreConstants {
055  
056  /**
057   * Certificates.
058   */
059  public static Object[][] certificates = new Object[5][12];
060  /**
061   * Keys.
062   */
063  public static PrivateKey[][] keys = new PrivateKey[5][12];
064  /**
065   * Ca certificates.
066   */
067  public static X509Certificate[] ca_certificates = new X509Certificate[3];
068  /**
069   * Ca keys.
070   */
071  public static PrivateKey[] ca_keys = new PrivateKey[3];
072  
073  /**
074   * Repository holding keys and certificates by their corresponding (certificate) ids.
075   * Used by class {@link demo.smime.DumpMessage DempMessgae} to search for recipient 
076   * keys/certificates based on their recipient key (certificate) ids.
077   * For simplicity we use the {@link iaik.smime.ess.utils.KeyStoreDatabase KeyStoreDatabase}
078   * utility.
079   */
080  private static KeyStoreDatabase recipientKeys_ = new KeyStoreDatabase(); 
081  
082  /**
083   * Adds a key and certificate by its key (certificate) ids to the given recipient keys/certs repositories.
084   * 
085   * @param recipientKey the recipient key to be added
086   * @param recipientCertChain the recipient certificate chain
087   * 
088   */
089  public static void addRecipientKey(PrivateKey recipientKey, X509Certificate[] recipientCertChain) {
090    
091    try {
092      recipientKeys_.addKey(recipientKey, recipientCertChain, null);
093    } catch (Exception e) {
094      System.err.println("Cannot add recipient key for " + recipientCertChain[0].getSubjectDN() + " " + e.toString());
095    }
096    
097  }
098  
099  /**
100   * Gets a recipient key by the given key (certificate) id.
101   * 
102   * @param keyId the key identifier
103   * 
104   * @return the recipient key or <code>null</code> if no key for the given id can be found
105   * 
106   */
107  public static PrivateKey getRecipientKey(KeyIdentifier keyId) {
108   
109    PrivateKey key = null;
110    try {
111      key = (PrivateKey)recipientKeys_.getKey(keyId);
112    } catch (Exception e) {
113      // ignore
114    }  
115    return key;
116    
117  }
118  
119  /**
120   * Gets a recipient cert by the given certificate id from the given recipient certs repository.
121   * 
122   * @param certId the certificate identifier
123   * 
124   * @return the recipient cert or <code>null</code> if no cert for the given id can be found
125   * 
126   */
127  public static X509Certificate getRecipientCert(CertificateIdentifier certId) {
128    X509Certificate cert = null;
129    try {
130      cert = recipientKeys_.getCertificate(certId);
131    } catch (Exception e) {
132      // ignore
133    }
134    return cert;
135  }
136  
137  /**
138   * Indices into the cert/key tables
139   */
140  public final static int RSA = 0;
141  public final static int DSA = 1;
142  public final static int RSAPSS = 2;
143  public final static int ESDH = 3;
144  public final static int SSDH = 4;
145  
146
147  public final static int SZ_1024_SIGN = 0;
148  public final static int SZ_2048_SIGN_1 = 1;
149  public final static int SZ_2048_SIGN_2 = 2;
150  public final static int SZ_2048_SIGN_3 = 3;
151  public final static int SZ_3072_SIGN = 4;
152  public final static int SZ_2048_CRYPT_1 = 5;
153  public final static int SZ_2048_CRYPT_2 = 6;
154  public final static int SZ_2048_CRYPT_3 = 7;
155  public final static int SZ_2048_SHA1_SIGN = 8;
156  public final static int SZ_2048_SHA256_SIGN = 9;
157  public final static int SZ_2048_SHA384_SIGN = 10;
158  public final static int SZ_2048_SHA512_SIGN = 11;
159  
160  /**
161   * Certificate chain of demo time stamp server.
162   */
163  static X509Certificate[] tsp_server_certs;
164  
165  /**
166   * Key of demo time stamp server.
167   */
168  static PrivateKey tsp_server_key;
169
170  /**
171   * Keystore.
172   */
173  static KeyStore key_store;
174  
175  /**
176   * The KeyStore file name.
177   */
178  public static String ks_filename = KS_FILENAME;
179  
180 
181  
182  /**
183   * Loads and inits keystore.
184   */
185  static {
186    System.out.println("initializing KeyStore...");
187    loadKeyStore();
188    initKeyStore();
189    System.out.println();
190  }
191  
192  /**
193   * Loads the keystore from the file ("cms.keystore").
194   */
195  private static void loadKeyStore() {
196    
197    boolean createKeyStore = false;
198    // try to locate the KeyStore
199    // first check the current working directory
200    File ks = new File(KS_DIRECTORY, ks_filename);
201    if (!ks.exists()) {
202      createKeyStore = true;
203      // called from demo batch file (try parent directory)
204      File ksDir = new File(KS_DIRECTORY);
205      if (ksDir.exists()) {
206        String parentDir = ksDir.getParent();
207        String pDir = parentDir.toLowerCase(); 
208        if ((pDir.endsWith("cms")) || (pDir.endsWith("smime")) ||
209            (pDir.endsWith("cmd")) || (pDir.endsWith("sh"))) {
210          File ksParent = new File(parentDir, ks_filename);
211          if (ksParent.exists()) {
212            ks = ksParent;
213            createKeyStore = false;
214          }
215        }
216      }
217      if (createKeyStore) {
218        // keystore does not exist ==> create new one
219        System.out.println();
220        System.out.println();
221        System.out.println("Can not find the KeyStore " + ks_filename + " in directory:");
222        System.out.println(ks.getAbsolutePath());
223        System.out.println("Generating key store!");
224        try {
225          SetupCMSKeyStore.main(new String[] {});
226        } catch (Exception ex) {
227          System.out.println("Unable to create KeyStore!");
228          ex.printStackTrace();
229          demo.DemoUtil.waitKey();
230          System.exit(1);
231        }   
232      }  
233    }
234
235    FileInputStream fis = null;
236    // now try to create and load the KeyStore
237    try {
238      fis = new FileInputStream(ks);
239      key_store = SecurityProvider.getSecurityProvider().getKeyStore("IAIKKeyStore");
240      key_store.load(fis, KS_PASSWORD);
241      fis.close(); 
242    } catch (Exception ex) {
243      System.out.println("Unable to load KeyStore!");
244      ex.printStackTrace();
245      if (fis != null) {
246        try {
247          fis.close(); 
248        } catch (Exception e) {
249          // ignore
250        }
251      }
252      demo.DemoUtil.waitKey();
253      System.exit(1);
254    } 
255
256  }
257
258  /**
259   * Initializes the keystore.
260   */
261  public static void initKeyStore() {
262
263    try {
264      ca_certificates[RSA] = Util.convertCertificateChain(key_store.getCertificateChain(CA_RSA))[0];
265      ca_keys[RSA] = (PrivateKey)key_store.getKey(CA_RSA, KS_PASSWORD);
266      ca_keys[RSAPSS] = (PrivateKey)key_store.getKey(CA_RSAPSS, KS_PASSWORD);
267      
268      // RSA for signing
269      certificates[RSA][SZ_2048_SIGN_1] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_SIGN_1));
270      keys[RSA][SZ_2048_SIGN_1] = (PrivateKey)key_store.getKey(RSA_2048_SIGN_1, KS_PASSWORD);
271      certificates[RSA][SZ_2048_SIGN_2] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_SIGN_2));
272      keys[RSA][SZ_2048_SIGN_2] = (PrivateKey)key_store.getKey(RSA_2048_SIGN_2, KS_PASSWORD);
273      certificates[RSA][SZ_2048_SIGN_3] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_SIGN_3));
274      keys[RSA][SZ_2048_SIGN_3] = (PrivateKey)key_store.getKey(RSA_2048_SIGN_3, KS_PASSWORD);
275      // RSA for encrypting
276      certificates[RSA][SZ_2048_CRYPT_1] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_CRYPT_1));
277      keys[RSA][SZ_2048_CRYPT_1] = (PrivateKey)key_store.getKey(RSA_2048_CRYPT_1, KS_PASSWORD);
278      addRecipientKey(keys[RSA][SZ_2048_CRYPT_1], ((X509Certificate[])certificates[RSA][SZ_2048_CRYPT_1]));
279      certificates[RSA][SZ_2048_CRYPT_2] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_CRYPT_2));
280      keys[RSA][SZ_2048_CRYPT_2] = (PrivateKey)key_store.getKey(RSA_2048_CRYPT_2, KS_PASSWORD);
281      addRecipientKey(keys[RSA][SZ_2048_CRYPT_2], ((X509Certificate[])certificates[RSA][SZ_2048_CRYPT_2]));
282      certificates[RSA][SZ_2048_CRYPT_3] = Util.convertCertificateChain(key_store.getCertificateChain(RSA_2048_CRYPT_3));
283      keys[RSA][SZ_2048_CRYPT_3] = (PrivateKey)key_store.getKey(RSA_2048_CRYPT_3, KS_PASSWORD);
284      addRecipientKey(keys[RSA][SZ_2048_CRYPT_3], ((X509Certificate[])certificates[RSA][SZ_2048_CRYPT_3]));
285    } catch (Exception ex) {
286      System.out.println("RSA certificates not loaded: " + ex.getMessage());
287      // ex.printStackTrace();
288    }
289
290    try {
291      ca_certificates[DSA] = Util.convertCertificateChain(key_store.getCertificateChain(CA_DSA))[0];
292      ca_keys[DSA] = (PrivateKey)key_store.getKey(CA_DSA, KS_PASSWORD);
293      certificates[DSA][SZ_1024_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_1024));
294      keys[DSA][SZ_1024_SIGN] = (PrivateKey)key_store.getKey(DSA_1024, KS_PASSWORD);
295    } catch (Exception ex) {
296      System.out.println("DSA certificates not loaded: " + ex.getMessage());
297      // ex.printStackTrace();
298    }
299    
300    try {
301      certificates[DSA][SZ_2048_SIGN_1] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_2048));
302      keys[DSA][SZ_2048_SIGN_1] = (PrivateKey)key_store.getKey(DSA_2048, KS_PASSWORD);
303      certificates[DSA][SZ_2048_SIGN_2] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_2048));
304      keys[DSA][SZ_2048_SIGN_2] = (PrivateKey)key_store.getKey(DSA_2048, KS_PASSWORD);
305      certificates[DSA][SZ_3072_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(DSA_3072));
306      keys[DSA][SZ_3072_SIGN] = (PrivateKey)key_store.getKey(DSA_3072, KS_PASSWORD);
307    } catch (Exception ex) {
308      System.out.println("Unable to get DSA SHA-2 certificate from KeyStore: " + ex.getMessage());
309    }
310
311    try {
312      certificates[ESDH][SZ_2048_CRYPT_1] = Util.convertCertificateChain(key_store.getCertificateChain(ESDH_2048_1));
313      keys[ESDH][SZ_2048_CRYPT_1] = (PrivateKey)key_store.getKey(ESDH_2048_1, KS_PASSWORD);
314      addRecipientKey(keys[ESDH][SZ_2048_CRYPT_1], ((X509Certificate[])certificates[ESDH][SZ_2048_CRYPT_1]));
315      certificates[ESDH][SZ_2048_CRYPT_2] = Util.convertCertificateChain(key_store.getCertificateChain(ESDH_2048_2));
316      keys[ESDH][SZ_2048_CRYPT_2] = (PrivateKey)key_store.getKey(ESDH_2048_2, KS_PASSWORD);
317      addRecipientKey(keys[ESDH][SZ_2048_CRYPT_2], ((X509Certificate[])certificates[ESDH][SZ_2048_CRYPT_2]));
318      certificates[SSDH][SZ_2048_CRYPT_1] = Util.convertCertificateChain(key_store.getCertificateChain(SSDH_2048_1));
319      keys[SSDH][SZ_2048_CRYPT_1] = (PrivateKey)key_store.getKey(SSDH_2048_1, KS_PASSWORD);
320      addRecipientKey(keys[SSDH][SZ_2048_CRYPT_1], ((X509Certificate[])certificates[SSDH][SZ_2048_CRYPT_1]));
321      certificates[SSDH][SZ_2048_CRYPT_2] = Util.convertCertificateChain(key_store.getCertificateChain(SSDH_2048_2));
322      keys[SSDH][SZ_2048_CRYPT_2] = (PrivateKey)key_store.getKey(SSDH_2048_2, KS_PASSWORD);
323      addRecipientKey(keys[SSDH][SZ_2048_CRYPT_2], ((X509Certificate[])certificates[SSDH][SZ_2048_CRYPT_2]));
324    } catch (Exception ex) {
325      System.out.println("Diffie-Hellman certificates not loaded: " + ex.getMessage());
326      // ex.printStackTrace();
327    }
328
329    //  TSP server cert
330    try {
331      tsp_server_certs = Util.convertCertificateChain(key_store.getCertificateChain(TSP_SERVER));
332      tsp_server_key = (PrivateKey)key_store.getKey(TSP_SERVER, KS_PASSWORD);
333    } catch (Exception ex) {
334      System.out.println("TSP server certificate not loaded: " + ex.getMessage());
335      // ex.printStackTrace();
336    }
337    
338    // RSA-PSS
339    try {
340      
341      ca_certificates[RSAPSS] = Util.convertCertificateChain(key_store.getCertificateChain(CA_RSAPSS))[0];
342      ca_keys[RSAPSS] = (PrivateKey)key_store.getKey(CA_RSAPSS, KS_PASSWORD);
343      
344      certificates[RSAPSS][SZ_2048_SHA1_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSAPSS_2048_SHA1_SIGN));
345      keys[RSAPSS][SZ_2048_SHA1_SIGN] = (PrivateKey)key_store.getKey(RSAPSS_2048_SHA1_SIGN, KS_PASSWORD);
346      certificates[RSAPSS][SZ_2048_SHA256_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSAPSS_2048_SHA256_SIGN));
347      keys[RSAPSS][SZ_2048_SHA256_SIGN] = (PrivateKey)key_store.getKey(RSAPSS_2048_SHA256_SIGN, KS_PASSWORD);
348      certificates[RSAPSS][SZ_2048_SHA384_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSAPSS_2048_SHA384_SIGN));
349      keys[RSAPSS][SZ_2048_SHA384_SIGN] = (PrivateKey)key_store.getKey(RSAPSS_2048_SHA384_SIGN, KS_PASSWORD);      
350      certificates[RSAPSS][SZ_2048_SHA512_SIGN] = Util.convertCertificateChain(key_store.getCertificateChain(RSAPSS_2048_SHA512_SIGN));
351      keys[RSAPSS][SZ_2048_SHA512_SIGN] = (PrivateKey)key_store.getKey(RSAPSS_2048_SHA512_SIGN, KS_PASSWORD);      
352
353
354    } catch (Exception ex) {
355      System.out.println("RSA-PSS certificates not loaded: " + ex.getMessage());
356      // ex.printStackTrace();
357    }
358    
359  }
360  
361  /**
362   * Returns the private key of a CA certificate.
363   *
364   * @param type {@link #RSA RSA} or {@link #DSA DSA} or {@link #ESDH ESDH}
365   * @param size the key size
366   * 
367   * @return the key
368   */
369  public static PrivateKey getPrivateKey(int type, int size) {
370    try {
371      return keys[type][size];
372    } catch (ArrayIndexOutOfBoundsException ex) {
373      throw new RuntimeException("Wrong type or size!");
374    }
375  }
376
377  /**
378   * Returns a demo user certificate.
379   *
380   * @param type {@link #RSA RSA} or {@link #DSA DSA} or {@link #ESDH ESDH} or {@link #SSDH SSDH}
381   * @param size the size of the corresponding key
382   * 
383   * @return the certificate chain
384   */
385  public static X509Certificate[] getCertificateChain(int type, int size) {
386    try {
387      return (X509Certificate[])certificates[type][size];
388    } catch (ArrayIndexOutOfBoundsException ex) {
389      throw new RuntimeException("Wrong type or size!");
390    }
391  }
392  
393  /**
394   * Returns the private key of a CA certificate.
395   *
396   * @param type {@link #RSA RSA} or {@link #DSA DSA}
397   * 
398   * @return the key
399   */
400  public static PrivateKey getCaPrivateKey(int type) {
401    try {
402      return ca_keys[type];
403    } catch (ArrayIndexOutOfBoundsException ex) {
404      throw new RuntimeException("Wrong type or size!");
405    }
406  }
407
408  /**
409   * Returns a demo CA certificate.
410   *
411   * @param type {@link #RSA RSA} or {@link #DSA DSA}
412   * 
413   * @return the ca certificate
414   */
415  public static X509Certificate getCaCertificate(int type) {
416    try {
417      return ca_certificates[type];
418    } catch (ArrayIndexOutOfBoundsException ex) {
419      throw new RuntimeException("Wrong type or size!");
420    }
421  }
422  
423  /**
424   * Returns the private key of the TSP demo server.
425   * 
426   * @return the key
427   */
428  public static PrivateKey getTspServerPrivateKey() {
429    return tsp_server_key;
430  }
431
432  /**
433   * Returns the certificate chain of the TSP demo server.
434   * 
435   * @return the tsp server certificate
436   */
437  public static X509Certificate[] getTspServerCertificate() {
438    return tsp_server_certs;
439  }
440  
441  
442}