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 }