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