001: /*
002: * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.security.mscapi;
027:
028: import java.io.ByteArrayInputStream;
029: import java.io.IOException;
030: import java.io.InputStream;
031: import java.io.OutputStream;
032: import java.math.BigInteger;
033: import java.security.AccessController;
034: import java.security.KeyStoreSpi;
035: import java.security.KeyStoreException;
036: import java.security.UnrecoverableKeyException;
037: import java.security.NoSuchAlgorithmException;
038: import java.security.SecurityPermission;
039: import java.security.cert.X509Certificate;
040: import java.security.cert.Certificate;
041: import java.security.cert.CertificateException;
042: import java.security.cert.CertificateEncodingException;
043: import java.security.cert.CertificateFactory;
044: import java.security.interfaces.RSAPrivateCrtKey;
045: import java.util.ArrayList;
046: import java.util.Collection;
047: import java.util.Date;
048: import java.util.Enumeration;
049: import java.util.Iterator;
050: import java.util.UUID;
051:
052: import sun.security.action.GetPropertyAction;
053:
054: /**
055: * Implementation of key store for Windows using the Microsoft Crypto API.
056: *
057: * @since 1.6
058: */
059: abstract class KeyStore extends KeyStoreSpi {
060:
061: public static final class MY extends KeyStore {
062: public MY() {
063: super ("MY");
064: }
065: }
066:
067: public static final class ROOT extends KeyStore {
068: public ROOT() {
069: super ("ROOT");
070: }
071: }
072:
073: class KeyEntry {
074: private Key privateKey;
075: private X509Certificate certChain[];
076: private String alias;
077:
078: KeyEntry(Key key, X509Certificate[] chain) {
079: this (null, key, chain);
080: }
081:
082: KeyEntry(String alias, Key key, X509Certificate[] chain) {
083: this .privateKey = key;
084: this .certChain = chain;
085: /*
086: * The default alias for both entry types is derived from a
087: * hash value intrinsic to the first certificate in the chain.
088: */
089: if (alias == null) {
090: this .alias = Integer.toString(chain[0].hashCode());
091: } else {
092: this .alias = alias;
093: }
094: }
095:
096: /**
097: * Gets the alias for the keystore entry.
098: */
099: String getAlias() {
100: return alias;
101: }
102:
103: /**
104: * Sets the alias for the keystore entry.
105: */
106: void setAlias(String alias) {
107: // TODO - set friendly name prop in cert store
108: this .alias = alias;
109: }
110:
111: /**
112: * Gets the private key for the keystore entry.
113: */
114: Key getPrivateKey() {
115: return privateKey;
116: }
117:
118: /**
119: * Sets the private key for the keystore entry.
120: */
121: void setPrivateKey(RSAPrivateCrtKey key) {
122: byte[] modulusBytes = key.getModulus().toByteArray();
123:
124: // Adjust key length due to sign bit
125: int keyBitLength = (modulusBytes[0] == 0) ? (modulusBytes.length - 1) * 8
126: : modulusBytes.length * 8;
127:
128: byte[] keyBlob = generatePrivateKeyBlob(keyBitLength,
129: modulusBytes,
130: key.getPublicExponent().toByteArray(), key
131: .getPrivateExponent().toByteArray(), key
132: .getPrimeP().toByteArray(), key.getPrimeQ()
133: .toByteArray(), key.getPrimeExponentP()
134: .toByteArray(), key.getPrimeExponentQ()
135: .toByteArray(), key.getCrtCoefficient()
136: .toByteArray());
137:
138: privateKey = storePrivateKey(keyBlob, "{"
139: + UUID.randomUUID().toString() + "}", keyBitLength);
140: }
141:
142: /**
143: * Gets the certificate chain for the keystore entry.
144: */
145: X509Certificate[] getCertificateChain() {
146: return certChain;
147: }
148:
149: /**
150: * Sets the certificate chain for the keystore entry.
151: */
152: void setCertificateChain(X509Certificate[] chain)
153: throws CertificateException {
154: for (int i = 0; i < chain.length; i++) {
155: byte[] encoding = chain[i].getEncoded();
156: if (i == 0 && privateKey != null) {
157: storeCertificate(getName(), alias, encoding,
158: encoding.length, privateKey
159: .getHCryptProvider(), privateKey
160: .getHCryptKey());
161:
162: } else {
163: storeCertificate(getName(), alias, encoding,
164: encoding.length, 0L, 0L); // no private key to attach
165: }
166: }
167: certChain = chain;
168: }
169: };
170:
171: /*
172: * An X.509 certificate factory.
173: * Used to create an X.509 certificate from its DER-encoding.
174: */
175: private CertificateFactory certificateFactory = null;
176:
177: /*
178: * Compatibility mode: for applications that assume keystores are
179: * stream-based this mode tolerates (but ignores) a non-null stream
180: * or password parameter when passed to the load or store methods.
181: * The mode is enabled by default.
182: */
183: private static final String KEYSTORE_COMPATIBILITY_MODE_PROP = "sun.security.mscapi.keyStoreCompatibilityMode";
184: private final boolean keyStoreCompatibilityMode;
185:
186: /*
187: * The keystore entries.
188: */
189: private Collection<KeyEntry> entries = new ArrayList<KeyEntry>();
190:
191: /*
192: * The keystore name.
193: * Case is not significant.
194: */
195: private final String storeName;
196:
197: KeyStore(String storeName) {
198: // Get the compatibility mode
199: String prop = AccessController
200: .doPrivileged(new GetPropertyAction(
201: KEYSTORE_COMPATIBILITY_MODE_PROP));
202:
203: if ("false".equalsIgnoreCase(prop)) {
204: keyStoreCompatibilityMode = false;
205: } else {
206: keyStoreCompatibilityMode = true;
207: }
208:
209: this .storeName = storeName;
210: }
211:
212: /**
213: * Returns the key associated with the given alias.
214: * <p>
215: * A compatibility mode is supported for applications that assume
216: * a password must be supplied. It permits (but ignores) a non-null
217: * <code>password</code>. The mode is enabled by default.
218: * Set the
219: * <code>sun.security.mscapi.keyStoreCompatibilityMode</code>
220: * system property to <code>false</code> to disable compatibility mode
221: * and reject a non-null <code>password</code>.
222: *
223: * @param alias the alias name
224: * @param password the password, which should be <code>null</code>
225: *
226: * @return the requested key, or null if the given alias does not exist
227: * or does not identify a <i>key entry</i>.
228: *
229: * @exception NoSuchAlgorithmException if the algorithm for recovering the
230: * key cannot be found,
231: * or if compatibility mode is disabled and <code>password</code> is
232: * non-null.
233: * @exception UnrecoverableKeyException if the key cannot be recovered.
234: */
235: public java.security.Key engineGetKey(String alias, char[] password)
236: throws NoSuchAlgorithmException, UnrecoverableKeyException {
237: if (alias == null) {
238: return null;
239: }
240:
241: if (password != null && !keyStoreCompatibilityMode) {
242: throw new UnrecoverableKeyException("Password must be null");
243: }
244:
245: if (engineIsKeyEntry(alias) == false)
246: return null;
247:
248: for (KeyEntry entry : entries) {
249: if (alias.equals(entry.getAlias())) {
250: return entry.getPrivateKey();
251: }
252: }
253:
254: return null;
255: }
256:
257: /**
258: * Returns the certificate chain associated with the given alias.
259: *
260: * @param alias the alias name
261: *
262: * @return the certificate chain (ordered with the user's certificate first
263: * and the root certificate authority last), or null if the given alias
264: * does not exist or does not contain a certificate chain (i.e., the given
265: * alias identifies either a <i>trusted certificate entry</i> or a
266: * <i>key entry</i> without a certificate chain).
267: */
268: public Certificate[] engineGetCertificateChain(String alias) {
269: if (alias == null) {
270: return null;
271: }
272:
273: for (KeyEntry entry : entries) {
274: if (alias.equals(entry.getAlias())) {
275: X509Certificate[] certChain = entry
276: .getCertificateChain();
277:
278: return certChain.clone();
279: }
280: }
281:
282: return null;
283: }
284:
285: /**
286: * Returns the certificate associated with the given alias.
287: *
288: * <p>If the given alias name identifies a
289: * <i>trusted certificate entry</i>, the certificate associated with that
290: * entry is returned. If the given alias name identifies a
291: * <i>key entry</i>, the first element of the certificate chain of that
292: * entry is returned, or null if that entry does not have a certificate
293: * chain.
294: *
295: * @param alias the alias name
296: *
297: * @return the certificate, or null if the given alias does not exist or
298: * does not contain a certificate.
299: */
300: public Certificate engineGetCertificate(String alias) {
301: if (alias == null) {
302: return null;
303: }
304:
305: for (KeyEntry entry : entries) {
306: if (alias.equals(entry.getAlias())) {
307: X509Certificate[] certChain = entry
308: .getCertificateChain();
309: return certChain[0];
310: }
311: }
312:
313: return null;
314: }
315:
316: /**
317: * Returns the creation date of the entry identified by the given alias.
318: *
319: * @param alias the alias name
320: *
321: * @return the creation date of this entry, or null if the given alias does
322: * not exist
323: */
324: public Date engineGetCreationDate(String alias) {
325: if (alias == null) {
326: return null;
327: }
328: return new Date();
329: }
330:
331: /**
332: * Stores the given private key and associated certificate chain in the
333: * keystore.
334: *
335: * <p>The given java.security.PrivateKey <code>key</code> must
336: * be accompanied by a certificate chain certifying the
337: * corresponding public key.
338: *
339: * <p>If the given alias already exists, the keystore information
340: * associated with it is overridden by the given key and certificate
341: * chain. Otherwise, a new entry is created.
342: *
343: * <p>
344: * A compatibility mode is supported for applications that assume
345: * a password must be supplied. It permits (but ignores) a non-null
346: * <code>password</code>. The mode is enabled by default.
347: * Set the
348: * <code>sun.security.mscapi.keyStoreCompatibilityMode</code>
349: * system property to <code>false</code> to disable compatibility mode
350: * and reject a non-null <code>password</code>.
351: *
352: * @param alias the alias name
353: * @param key the private key to be associated with the alias
354: * @param password the password, which should be <code>null</code>
355: * @param chain the certificate chain for the corresponding public
356: * key (only required if the given key is of type
357: * <code>java.security.PrivateKey</code>).
358: *
359: * @exception KeyStoreException if the given key is not a private key,
360: * cannot be protected, or if compatibility mode is disabled and
361: * <code>password</code> is non-null, or if this operation fails for
362: * some other reason.
363: */
364: public void engineSetKeyEntry(String alias, java.security.Key key,
365: char[] password, Certificate[] chain)
366: throws KeyStoreException {
367: if (alias == null) {
368: throw new KeyStoreException("alias must not be null");
369: }
370:
371: if (password != null && !keyStoreCompatibilityMode) {
372: throw new KeyStoreException("Password must be null");
373: }
374:
375: if (key instanceof RSAPrivateCrtKey) {
376:
377: KeyEntry entry = null;
378: boolean found = false;
379:
380: for (KeyEntry e : entries) {
381: if (alias.equals(e.getAlias())) {
382: found = true;
383: entry = e;
384: break;
385: }
386: }
387:
388: if (!found) {
389: entry =
390: //TODO new KeyEntry(alias, key, (X509Certificate[]) chain);
391: new KeyEntry(alias, null, (X509Certificate[]) chain);
392: entries.add(entry);
393: }
394:
395: entry.setAlias(alias);
396: entry.setPrivateKey((RSAPrivateCrtKey) key);
397:
398: try {
399: entry.setCertificateChain((X509Certificate[]) chain);
400:
401: } catch (CertificateException ce) {
402: throw new KeyStoreException(ce);
403: }
404:
405: } else {
406: throw new UnsupportedOperationException(
407: "Cannot assign the key to the given alias.");
408: }
409: }
410:
411: /**
412: * Assigns the given key (that has already been protected) to the given
413: * alias.
414: *
415: * <p>If the protected key is of type
416: * <code>java.security.PrivateKey</code>, it must be accompanied by a
417: * certificate chain certifying the corresponding public key. If the
418: * underlying keystore implementation is of type <code>jks</code>,
419: * <code>key</code> must be encoded as an
420: * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
421: *
422: * <p>If the given alias already exists, the keystore information
423: * associated with it is overridden by the given key (and possibly
424: * certificate chain).
425: *
426: * @param alias the alias name
427: * @param key the key (in protected format) to be associated with the alias
428: * @param chain the certificate chain for the corresponding public
429: * key (only useful if the protected key is of type
430: * <code>java.security.PrivateKey</code>).
431: *
432: * @exception KeyStoreException if this operation fails.
433: */
434: public void engineSetKeyEntry(String alias, byte[] key,
435: Certificate[] chain) throws KeyStoreException {
436: throw new UnsupportedOperationException(
437: "Cannot assign the encoded key to the given alias.");
438: }
439:
440: /**
441: * Assigns the given certificate to the given alias.
442: *
443: * <p>If the given alias already exists in this keystore and identifies a
444: * <i>trusted certificate entry</i>, the certificate associated with it is
445: * overridden by the given certificate.
446: *
447: * @param alias the alias name
448: * @param cert the certificate
449: *
450: * @exception KeyStoreException if the given alias already exists and does
451: * not identify a <i>trusted certificate entry</i>, or this operation
452: * fails for some other reason.
453: */
454: public void engineSetCertificateEntry(String alias, Certificate cert)
455: throws KeyStoreException {
456: if (alias == null) {
457: throw new KeyStoreException("alias must not be null");
458: }
459:
460: if (cert instanceof X509Certificate) {
461:
462: // TODO - build CryptoAPI chain?
463: X509Certificate[] chain = new X509Certificate[] { (X509Certificate) cert };
464: KeyEntry entry = null;
465: boolean found = false;
466:
467: for (KeyEntry e : entries) {
468: if (alias.equals(e.getAlias())) {
469: found = true;
470: entry = e;
471: break;
472: }
473: }
474:
475: if (!found) {
476: entry = new KeyEntry(alias, null, chain);
477: entries.add(entry);
478:
479: }
480: if (entry.getPrivateKey() == null) { // trusted-cert entry
481: entry.setAlias(alias);
482:
483: try {
484: entry.setCertificateChain(chain);
485:
486: } catch (CertificateException ce) {
487: throw new KeyStoreException(ce);
488: }
489: }
490:
491: } else {
492: throw new UnsupportedOperationException(
493: "Cannot assign the certificate to the given alias.");
494: }
495: }
496:
497: /**
498: * Deletes the entry identified by the given alias from this keystore.
499: *
500: * @param alias the alias name
501: *
502: * @exception KeyStoreException if the entry cannot be removed.
503: */
504: public void engineDeleteEntry(String alias)
505: throws KeyStoreException {
506: if (alias == null) {
507: throw new KeyStoreException("alias must not be null");
508: }
509:
510: for (KeyEntry entry : entries) {
511: if (alias.equals(entry.getAlias())) {
512:
513: // Get end-entity certificate and remove from system cert store
514: X509Certificate[] certChain = entry
515: .getCertificateChain();
516: if (certChain != null) {
517:
518: try {
519:
520: byte[] encoding = certChain[0].getEncoded();
521: removeCertificate(getName(), alias, encoding,
522: encoding.length);
523:
524: } catch (CertificateEncodingException e) {
525: throw new KeyStoreException(
526: "Cannot remove entry: " + e);
527: }
528: }
529: Key privateKey = entry.getPrivateKey();
530: if (privateKey != null) {
531: destroyKeyContainer(Key.getContainerName(privateKey
532: .getHCryptProvider()));
533: }
534:
535: entries.remove(entry);
536: break;
537: }
538: }
539: }
540:
541: /**
542: * Lists all the alias names of this keystore.
543: *
544: * @return enumeration of the alias names
545: */
546: public Enumeration engineAliases() {
547:
548: final Iterator iter = entries.iterator();
549:
550: return new Enumeration() {
551: public boolean hasMoreElements() {
552: return iter.hasNext();
553: }
554:
555: public Object nextElement() {
556: KeyEntry entry = (KeyEntry) iter.next();
557: return entry.getAlias();
558: }
559: };
560: }
561:
562: /**
563: * Checks if the given alias exists in this keystore.
564: *
565: * @param alias the alias name
566: *
567: * @return true if the alias exists, false otherwise
568: */
569: public boolean engineContainsAlias(String alias) {
570: for (Enumeration enumerator = engineAliases(); enumerator
571: .hasMoreElements();) {
572: String a = (String) enumerator.nextElement();
573:
574: if (a.equals(alias))
575: return true;
576: }
577: return false;
578: }
579:
580: /**
581: * Retrieves the number of entries in this keystore.
582: *
583: * @return the number of entries in this keystore
584: */
585: public int engineSize() {
586: return entries.size();
587: }
588:
589: /**
590: * Returns true if the entry identified by the given alias is a
591: * <i>key entry</i>, and false otherwise.
592: *
593: * @return true if the entry identified by the given alias is a
594: * <i>key entry</i>, false otherwise.
595: */
596: public boolean engineIsKeyEntry(String alias) {
597:
598: if (alias == null) {
599: return false;
600: }
601:
602: for (KeyEntry entry : entries) {
603: if (alias.equals(entry.getAlias())) {
604: return entry.getPrivateKey() != null;
605: }
606: }
607:
608: return false;
609: }
610:
611: /**
612: * Returns true if the entry identified by the given alias is a
613: * <i>trusted certificate entry</i>, and false otherwise.
614: *
615: * @return true if the entry identified by the given alias is a
616: * <i>trusted certificate entry</i>, false otherwise.
617: */
618: public boolean engineIsCertificateEntry(String alias) {
619: for (KeyEntry entry : entries) {
620: if (alias.equals(entry.getAlias())) {
621: return entry.getPrivateKey() == null;
622: }
623: }
624:
625: return false;
626: }
627:
628: /**
629: * Returns the (alias) name of the first keystore entry whose certificate
630: * matches the given certificate.
631: *
632: * <p>This method attempts to match the given certificate with each
633: * keystore entry. If the entry being considered
634: * is a <i>trusted certificate entry</i>, the given certificate is
635: * compared to that entry's certificate. If the entry being considered is
636: * a <i>key entry</i>, the given certificate is compared to the first
637: * element of that entry's certificate chain (if a chain exists).
638: *
639: * @param cert the certificate to match with.
640: *
641: * @return the (alias) name of the first entry with matching certificate,
642: * or null if no such entry exists in this keystore.
643: */
644: public String engineGetCertificateAlias(Certificate cert) {
645: for (KeyEntry entry : entries) {
646: if (entry.certChain != null
647: && entry.certChain[0].equals(cert)) {
648: return entry.getAlias();
649: }
650: }
651:
652: return null;
653: }
654:
655: /**
656: * engineStore is currently a no-op.
657: * Entries are stored during engineSetEntry.
658: *
659: * A compatibility mode is supported for applications that assume
660: * keystores are stream-based. It permits (but ignores) a non-null
661: * <code>stream</code> or <code>password</code>.
662: * The mode is enabled by default.
663: * Set the
664: * <code>sun.security.mscapi.keyStoreCompatibilityMode</code>
665: * system property to <code>false</code> to disable compatibility mode
666: * and reject a non-null <code>stream</code> or <code>password</code>.
667: *
668: * @param stream the output stream, which should be <code>null</code>
669: * @param password the password, which should be <code>null</code>
670: *
671: * @exception IOException if compatibility mode is disabled and either
672: * parameter is non-null.
673: */
674: public void engineStore(OutputStream stream, char[] password)
675: throws IOException, NoSuchAlgorithmException,
676: CertificateException {
677: if (stream != null && !keyStoreCompatibilityMode) {
678: throw new IOException("Keystore output stream must be null");
679: }
680:
681: if (password != null && !keyStoreCompatibilityMode) {
682: throw new IOException("Keystore password must be null");
683: }
684: }
685:
686: /**
687: * Loads the keystore.
688: *
689: * A compatibility mode is supported for applications that assume
690: * keystores are stream-based. It permits (but ignores) a non-null
691: * <code>stream</code> or <code>password</code>.
692: * The mode is enabled by default.
693: * Set the
694: * <code>sun.security.mscapi.keyStoreCompatibilityMode</code>
695: * system property to <code>false</code> to disable compatibility mode
696: * and reject a non-null <code>stream</code> or <code>password</code>.
697: *
698: * @param stream the input stream, which should be <code>null</code>.
699: * @param password the password, which should be <code>null</code>.
700: *
701: * @exception IOException if there is an I/O or format problem with the
702: * keystore data. Or if compatibility mode is disabled and either
703: * parameter is non-null.
704: * @exception NoSuchAlgorithmException if the algorithm used to check
705: * the integrity of the keystore cannot be found
706: * @exception CertificateException if any of the certificates in the
707: * keystore could not be loaded
708: * @exception SecurityException if the security check for
709: * <code>SecurityPermission("authProvider.<i>name</i>")</code> does not
710: * pass, where <i>name</i> is the value returned by
711: * this provider's <code>getName</code> method.
712: */
713: public void engineLoad(InputStream stream, char[] password)
714: throws IOException, NoSuchAlgorithmException,
715: CertificateException {
716: if (stream != null && !keyStoreCompatibilityMode) {
717: throw new IOException("Keystore input stream must be null");
718: }
719:
720: if (password != null && !keyStoreCompatibilityMode) {
721: throw new IOException("Keystore password must be null");
722: }
723:
724: /*
725: * Use the same security check as AuthProvider.login
726: */
727: SecurityManager sm = System.getSecurityManager();
728: if (sm != null) {
729: sm.checkPermission(new SecurityPermission(
730: "authProvider.SunMSCAPI"));
731: }
732:
733: // Clear all key entries
734: entries.clear();
735:
736: // Load keys and/or certificate chains
737: loadKeysOrCertificateChains(getName(), entries);
738: }
739:
740: /**
741: * Generates a certificate chain from the collection of
742: * certificates and stores the result into a key entry.
743: */
744: private void generateCertificateChain(String alias,
745: Collection certCollection, Collection<KeyEntry> entries) {
746: try {
747: X509Certificate[] certChain = new X509Certificate[certCollection
748: .size()];
749:
750: int i = 0;
751: for (Iterator iter = certCollection.iterator(); iter
752: .hasNext(); i++) {
753: certChain[i] = (X509Certificate) iter.next();
754: }
755:
756: KeyEntry entry = new KeyEntry(alias, null, certChain);
757:
758: // Add cert chain
759: entries.add(entry);
760: } catch (Throwable e) {
761: // Ignore the exception and skip this entry
762: // TODO - throw CertificateException?
763: }
764: }
765:
766: /**
767: * Generates RSA key and certificate chain from the private key handle,
768: * collection of certificates and stores the result into key entries.
769: */
770: private void generateRSAKeyAndCertificateChain(String alias,
771: long hCryptProv, long hCryptKey, int keyLength,
772: Collection certCollection, Collection<KeyEntry> entries) {
773: try {
774: X509Certificate[] certChain = new X509Certificate[certCollection
775: .size()];
776:
777: int i = 0;
778: for (Iterator iter = certCollection.iterator(); iter
779: .hasNext(); i++) {
780: certChain[i] = (X509Certificate) iter.next();
781: }
782:
783: KeyEntry entry = new KeyEntry(alias, new RSAPrivateKey(
784: hCryptProv, hCryptKey, keyLength), certChain);
785:
786: // Add cert chain
787: entries.add(entry);
788: } catch (Throwable e) {
789: // Ignore the exception and skip this entry
790: // TODO - throw CertificateException?
791: }
792: }
793:
794: /**
795: * Generates certificates from byte data and stores into cert collection.
796: *
797: * @param data Byte data.
798: * @param certCollection Collection of certificates.
799: */
800: private void generateCertificate(byte[] data,
801: Collection certCollection) {
802: try {
803: ByteArrayInputStream bis = new ByteArrayInputStream(data);
804:
805: // Obtain certificate factory
806: if (certificateFactory == null) {
807: certificateFactory = CertificateFactory
808: .getInstance("X.509");
809: }
810:
811: // Generate certificate
812: Collection c = certificateFactory.generateCertificates(bis);
813: certCollection.addAll(c);
814: } catch (CertificateException e) {
815: // Ignore the exception and skip this certificate
816: // TODO - throw CertificateException?
817: } catch (Throwable te) {
818: // Ignore the exception and skip this certificate
819: // TODO - throw CertificateException?
820: }
821: }
822:
823: /**
824: * Returns the name of the keystore.
825: */
826: private String getName() {
827: return storeName;
828: }
829:
830: /**
831: * Load keys and/or certificates from keystore into Collection.
832: *
833: * @param name Name of keystore.
834: * @param entries Collection of key/certificate.
835: */
836: private native void loadKeysOrCertificateChains(String name,
837: Collection<KeyEntry> entries);
838:
839: /**
840: * Stores a DER-encoded certificate into the certificate store
841: *
842: * @param name Name of the keystore.
843: * @param alias Name of the certificate.
844: * @param encoding DER-encoded certificate.
845: */
846: private native void storeCertificate(String name, String alias,
847: byte[] encoding, int encodingLength, long hCryptProvider,
848: long hCryptKey);
849:
850: /**
851: * Removes the certificate from the certificate store
852: *
853: * @param name Name of the keystore.
854: * @param alias Name of the certificate.
855: * @param encoding DER-encoded certificate.
856: */
857: private native void removeCertificate(String name, String alias,
858: byte[] encoding, int encodingLength);
859:
860: /**
861: * Destroys the key container.
862: *
863: * @param keyContainerName The name of the key container.
864: */
865: private native void destroyKeyContainer(String keyContainerName);
866:
867: /**
868: * Generates a private-key BLOB from a key's components.
869: */
870: private native byte[] generatePrivateKeyBlob(int keyBitLength,
871: byte[] modulus, byte[] publicExponent,
872: byte[] privateExponent, byte[] primeP, byte[] primeQ,
873: byte[] exponentP, byte[] exponentQ, byte[] crtCoefficient);
874:
875: private native RSAPrivateKey storePrivateKey(byte[] keyBlob,
876: String keyContainerName, int keySize);
877: }
|