< prev index next >

src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java

Print this page
rev 13981 : imported patch 6483657-MSCAPI-provider-does-not-create-unique-alias-names
   1 /*
   2  * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 171     };
 172 
 173     /*
 174      * An X.509 certificate factory.
 175      * Used to create an X.509 certificate from its DER-encoding.
 176      */
 177     private CertificateFactory certificateFactory = null;
 178 
 179     /*
 180      * Compatibility mode: for applications that assume keystores are
 181      * stream-based this mode tolerates (but ignores) a non-null stream
 182      * or password parameter when passed to the load or store methods.
 183      * The mode is enabled by default.
 184      */
 185     private static final String KEYSTORE_COMPATIBILITY_MODE_PROP =
 186         "sun.security.mscapi.keyStoreCompatibilityMode";
 187     private final boolean keyStoreCompatibilityMode;
 188 
 189     /*
 190      * The keystore entries.


 191      */
 192     private Collection<KeyEntry> entries = new ArrayList<KeyEntry>();
 193 
 194     /*
 195      * The keystore name.
 196      * Case is not significant.
 197      */
 198     private final String storeName;
 199 
 200     KeyStore(String storeName) {
 201         // Get the compatibility mode
 202         String prop = AccessController.doPrivileged(
 203             (PrivilegedAction<String>) () -> System.getProperty(KEYSTORE_COMPATIBILITY_MODE_PROP));
 204 
 205         if ("false".equalsIgnoreCase(prop)) {
 206             keyStoreCompatibilityMode = false;
 207         } else {
 208             keyStoreCompatibilityMode = true;
 209         }
 210 
 211         this.storeName = storeName;
 212     }


 231      * @exception NoSuchAlgorithmException if the algorithm for recovering the
 232      * key cannot be found,
 233      * or if compatibility mode is disabled and <code>password</code> is
 234      * non-null.
 235      * @exception UnrecoverableKeyException if the key cannot be recovered.
 236      */
 237     public java.security.Key engineGetKey(String alias, char[] password)
 238         throws NoSuchAlgorithmException, UnrecoverableKeyException
 239     {
 240         if (alias == null) {
 241             return null;
 242         }
 243 
 244         if (password != null && !keyStoreCompatibilityMode) {
 245             throw new UnrecoverableKeyException("Password must be null");
 246         }
 247 
 248         if (engineIsKeyEntry(alias) == false)
 249             return null;
 250 
 251         for (KeyEntry entry : entries) {
 252             if (alias.equals(entry.getAlias())) {
 253                 return entry.getPrivateKey();
 254             }
 255         }
 256 
 257         return null;
 258     }
 259 
 260     /**
 261      * Returns the certificate chain associated with the given alias.
 262      *
 263      * @param alias the alias name
 264      *
 265      * @return the certificate chain (ordered with the user's certificate first
 266      * and the root certificate authority last), or null if the given alias
 267      * does not exist or does not contain a certificate chain (i.e., the given
 268      * alias identifies either a <i>trusted certificate entry</i> or a
 269      * <i>key entry</i> without a certificate chain).
 270      */
 271     public Certificate[] engineGetCertificateChain(String alias)
 272     {
 273         if (alias == null) {
 274             return null;
 275         }
 276 
 277         for (KeyEntry entry : entries) {
 278             if (alias.equals(entry.getAlias())) {
 279                 X509Certificate[] certChain = entry.getCertificateChain();
 280 
 281                 return certChain.clone();
 282             }
 283         }
 284 
 285         return null;
 286     }
 287 
 288     /**
 289      * Returns the certificate associated with the given alias.
 290      *
 291      * <p>If the given alias name identifies a
 292      * <i>trusted certificate entry</i>, the certificate associated with that
 293      * entry is returned. If the given alias name identifies a
 294      * <i>key entry</i>, the first element of the certificate chain of that
 295      * entry is returned, or null if that entry does not have a certificate
 296      * chain.
 297      *
 298      * @param alias the alias name
 299      *
 300      * @return the certificate, or null if the given alias does not exist or
 301      * does not contain a certificate.
 302      */
 303     public Certificate engineGetCertificate(String alias)
 304     {
 305         if (alias == null) {
 306             return null;
 307         }
 308 
 309         for (KeyEntry entry : entries) {
 310             if (alias.equals(entry.getAlias()))
 311             {
 312                 X509Certificate[] certChain = entry.getCertificateChain();
 313                 return certChain.length == 0 ? null : certChain[0];
 314             }
 315         }
 316 
 317         return null;
 318     }
 319 
 320     /**
 321      * Returns the creation date of the entry identified by the given alias.
 322      *
 323      * @param alias the alias name
 324      *
 325      * @return the creation date of this entry, or null if the given alias does
 326      * not exist
 327      */
 328     public Date engineGetCreationDate(String alias) {
 329         if (alias == null) {
 330             return null;
 331         }
 332         return new Date();
 333     }
 334 
 335     /**
 336      * Stores the given private key and associated certificate chain in the
 337      * keystore.


 361      *        <code>java.security.PrivateKey</code>).
 362      *
 363      * @exception KeyStoreException if the given key is not a private key,
 364      * cannot be protected, or if compatibility mode is disabled and
 365      * <code>password</code> is non-null, or if this operation fails for
 366      * some other reason.
 367      */
 368     public void engineSetKeyEntry(String alias, java.security.Key key,
 369         char[] password, Certificate[] chain) throws KeyStoreException
 370     {
 371         if (alias == null) {
 372             throw new KeyStoreException("alias must not be null");
 373         }
 374 
 375         if (password != null && !keyStoreCompatibilityMode) {
 376             throw new KeyStoreException("Password must be null");
 377         }
 378 
 379         if (key instanceof RSAPrivateCrtKey) {
 380 
 381             KeyEntry entry = null;
 382             boolean found = false;
 383 
 384             for (KeyEntry e : entries) {
 385                 if (alias.equals(e.getAlias())) {
 386                     found = true;
 387                     entry = e;
 388                     break;
 389                 }
 390             }
 391 
 392             X509Certificate[] xchain;
 393             if (chain != null) {
 394                 if (chain instanceof X509Certificate[]) {
 395                     xchain = (X509Certificate[]) chain;
 396                 } else {
 397                     xchain = new X509Certificate[chain.length];
 398                     System.arraycopy(chain, 0, xchain, 0, chain.length);
 399                 }
 400             } else {
 401                 xchain = null;
 402             }
 403 
 404             if (! found) {
 405                 entry =
 406                     //TODO new KeyEntry(alias, key, (X509Certificate[]) chain);
 407                     new KeyEntry(alias, null, xchain);
 408                 entries.add(entry);
 409             }
 410 
 411             entry.setAlias(alias);
 412 
 413             try {
 414                 entry.setPrivateKey((RSAPrivateCrtKey) key);
 415                 entry.setCertificateChain(xchain);
 416 
 417             } catch (CertificateException ce) {
 418                 throw new KeyStoreException(ce);
 419 
 420             } catch (InvalidKeyException ike) {
 421                 throw new KeyStoreException(ike);
 422             }
 423 
 424         } else {
 425             throw new UnsupportedOperationException(
 426                 "Cannot assign the key to the given alias.");
 427         }
 428     }


 467      *
 468      * @param alias the alias name
 469      * @param cert the certificate
 470      *
 471      * @exception KeyStoreException if the given alias already exists and does
 472      * not identify a <i>trusted certificate entry</i>, or this operation
 473      * fails for some other reason.
 474      */
 475     public void engineSetCertificateEntry(String alias, Certificate cert)
 476         throws KeyStoreException
 477     {
 478         if (alias == null) {
 479             throw new KeyStoreException("alias must not be null");
 480         }
 481 
 482         if (cert instanceof X509Certificate) {
 483 
 484             // TODO - build CryptoAPI chain?
 485             X509Certificate[] chain =
 486                 new X509Certificate[]{ (X509Certificate) cert };
 487             KeyEntry entry = null;
 488             boolean found = false;
 489 
 490             for (KeyEntry e : entries) {
 491                 if (alias.equals(e.getAlias())) {
 492                     found = true;
 493                     entry = e;
 494                     break;
 495                 }
 496             }
 497 
 498             if (! found) {
 499                 entry =
 500                     new KeyEntry(alias, null, chain);
 501                 entries.add(entry);
 502 
 503             }

 504             if (entry.getPrivateKey() == null) { // trusted-cert entry
 505                 entry.setAlias(alias);
 506 
 507                 try {
 508                     entry.setCertificateChain(chain);
 509 
 510                 } catch (CertificateException ce) {
 511                     throw new KeyStoreException(ce);
 512                 }
 513             }
 514 
 515         } else {
 516             throw new UnsupportedOperationException(
 517                 "Cannot assign the certificate to the given alias.");
 518         }
 519     }
 520 
 521     /**
 522      * Deletes the entry identified by the given alias from this keystore.
 523      *
 524      * @param alias the alias name
 525      *
 526      * @exception KeyStoreException if the entry cannot be removed.
 527      */
 528     public void engineDeleteEntry(String alias)
 529         throws KeyStoreException
 530     {
 531         if (alias == null) {
 532             throw new KeyStoreException("alias must not be null");
 533         }
 534 
 535         for (KeyEntry entry : entries) {
 536             if (alias.equals(entry.getAlias())) {
 537 
 538                 // Get end-entity certificate and remove from system cert store
 539                 X509Certificate[] certChain = entry.getCertificateChain();
 540                 if (certChain != null) {
 541 
 542                     try {
 543 
 544                         byte[] encoding = certChain[0].getEncoded();
 545                         removeCertificate(getName(), alias, encoding,
 546                             encoding.length);
 547 
 548                     } catch (CertificateException e) {
 549                         throw new KeyStoreException("Cannot remove entry: " +
 550                             e);
 551                     }
 552                 }
 553                 Key privateKey = entry.getPrivateKey();
 554                 if (privateKey != null) {
 555                     destroyKeyContainer(
 556                         Key.getContainerName(privateKey.getHCryptProvider()));
 557                 }
 558 
 559                 entries.remove(entry);
 560                 break;
 561             }
 562         }
 563     }
 564 
 565     /**
 566      * Lists all the alias names of this keystore.
 567      *
 568      * @return enumeration of the alias names
 569      */
 570     public Enumeration<String> engineAliases() {
 571 
 572         final Iterator<KeyEntry> iter = entries.iterator();
 573 
 574         return new Enumeration<String>()
 575         {
 576             public boolean hasMoreElements()
 577             {
 578                 return iter.hasNext();
 579             }
 580 
 581             public String nextElement()
 582             {
 583                 KeyEntry entry = iter.next();
 584                 return entry.getAlias();
 585             }
 586         };
 587     }
 588 
 589     /**
 590      * Checks if the given alias exists in this keystore.
 591      *
 592      * @param alias the alias name
 593      *
 594      * @return true if the alias exists, false otherwise
 595      */
 596     public boolean engineContainsAlias(String alias) {
 597         for (Enumeration<String> enumerator = engineAliases();
 598             enumerator.hasMoreElements();)
 599         {
 600             String a = enumerator.nextElement();
 601 
 602             if (a.equals(alias))
 603                 return true;
 604         }
 605         return false;
 606     }
 607 
 608     /**
 609      * Retrieves the number of entries in this keystore.
 610      *
 611      * @return the number of entries in this keystore
 612      */
 613     public int engineSize() {
 614         return entries.size();
 615     }
 616 
 617     /**
 618      * Returns true if the entry identified by the given alias is a
 619      * <i>key entry</i>, and false otherwise.
 620      *
 621      * @return true if the entry identified by the given alias is a
 622      * <i>key entry</i>, false otherwise.
 623      */
 624     public boolean engineIsKeyEntry(String alias) {
 625 
 626         if (alias == null) {
 627             return false;
 628         }
 629 
 630         for (KeyEntry entry : entries) {
 631             if (alias.equals(entry.getAlias())) {
 632                 return entry.getPrivateKey() != null;
 633             }
 634         }
 635 
 636         return false;
 637     }
 638 
 639     /**
 640      * Returns true if the entry identified by the given alias is a
 641      * <i>trusted certificate entry</i>, and false otherwise.
 642      *
 643      * @return true if the entry identified by the given alias is a
 644      * <i>trusted certificate entry</i>, false otherwise.
 645      */
 646     public boolean engineIsCertificateEntry(String alias)
 647     {
 648         for (KeyEntry entry : entries) {
 649             if (alias.equals(entry.getAlias())) {
 650                 return entry.getPrivateKey() == null;
 651             }
 652         }
 653 

 654         return false;
 655     }
 656 




 657     /**
 658      * Returns the (alias) name of the first keystore entry whose certificate
 659      * matches the given certificate.
 660      *
 661      * <p>This method attempts to match the given certificate with each
 662      * keystore entry. If the entry being considered
 663      * is a <i>trusted certificate entry</i>, the given certificate is
 664      * compared to that entry's certificate. If the entry being considered is
 665      * a <i>key entry</i>, the given certificate is compared to the first
 666      * element of that entry's certificate chain (if a chain exists).
 667      *
 668      * @param cert the certificate to match with.
 669      *
 670      * @return the (alias) name of the first entry with matching certificate,
 671      * or null if no such entry exists in this keystore.
 672      */
 673     public String engineGetCertificateAlias(Certificate cert)
 674     {
 675         for (KeyEntry entry : entries) {

 676             if (entry.certChain != null && entry.certChain[0].equals(cert)) {
 677                 return entry.getAlias();
 678             }
 679         }
 680 
 681         return null;
 682     }
 683 
 684     /**
 685      * engineStore is currently a no-op.
 686      * Entries are stored during engineSetEntry.
 687      *
 688      * A compatibility mode is supported for applications that assume
 689      * keystores are stream-based. It permits (but ignores) a non-null
 690      * <code>stream</code> or <code>password</code>.
 691      * The mode is enabled by default.
 692      * Set the
 693      * <code>sun.security.mscapi.keyStoreCompatibilityMode</code>
 694      * system property to <code>false</code> to disable compatibility mode
 695      * and reject a non-null <code>stream</code> or <code>password</code>.


 748 
 749         if (password != null && !keyStoreCompatibilityMode) {
 750             throw new IOException("Keystore password must be null");
 751         }
 752 
 753         /*
 754          * Use the same security check as AuthProvider.login
 755          */
 756         SecurityManager sm = System.getSecurityManager();
 757         if (sm != null) {
 758             sm.checkPermission(new SecurityPermission(
 759                 "authProvider.SunMSCAPI"));
 760         }
 761 
 762         // Clear all key entries
 763         entries.clear();
 764 
 765         try {
 766 
 767             // Load keys and/or certificate chains
 768             loadKeysOrCertificateChains(getName(), entries);
 769 
 770         } catch (KeyStoreException e) {
 771             throw new IOException(e);
 772         }
 773     }
 774 
 775     /**




















 776      * Generates a certificate chain from the collection of
 777      * certificates and stores the result into a key entry.
 778      */
 779     private void generateCertificateChain(String alias,
 780         Collection<? extends Certificate> certCollection,
 781         Collection<KeyEntry> entries)
 782     {
 783         try
 784         {
 785             X509Certificate[] certChain =
 786                 new X509Certificate[certCollection.size()];
 787 
 788             int i = 0;
 789             for (Iterator<? extends Certificate> iter =
 790                     certCollection.iterator(); iter.hasNext(); i++)
 791             {
 792                 certChain[i] = (X509Certificate) iter.next();
 793             }
 794 
 795             KeyEntry entry = new KeyEntry(alias, null, certChain);
 796 
 797             // Add cert chain
 798             entries.add(entry);
 799         }
 800         catch (Throwable e)
 801         {
 802             // Ignore the exception and skip this entry
 803             // TODO - throw CertificateException?
 804         }
 805     }
 806 
 807     /**
 808      * Generates RSA key and certificate chain from the private key handle,
 809      * collection of certificates and stores the result into key entries.
 810      */
 811     private void generateRSAKeyAndCertificateChain(String alias,
 812         long hCryptProv, long hCryptKey, int keyLength,
 813         Collection<? extends Certificate> certCollection,
 814         Collection<KeyEntry> entries)
 815     {
 816         try
 817         {
 818             X509Certificate[] certChain =
 819                 new X509Certificate[certCollection.size()];
 820 
 821             int i = 0;
 822             for (Iterator<? extends Certificate> iter =
 823                     certCollection.iterator(); iter.hasNext(); i++)
 824             {
 825                 certChain[i] = (X509Certificate) iter.next();
 826             }
 827 
 828             KeyEntry entry = new KeyEntry(alias, new RSAPrivateKey(hCryptProv,
 829                 hCryptKey, keyLength), certChain);
 830 
 831             // Add cert chain
 832             entries.add(entry);
 833         }
 834         catch (Throwable e)
 835         {
 836             // Ignore the exception and skip this entry
 837             // TODO - throw CertificateException?
 838         }
 839     }
 840 
 841     /**
 842      * Generates certificates from byte data and stores into cert collection.
 843      *
 844      * @param data Byte data.
 845      * @param certCollection Collection of certificates.
 846      */
 847     private void generateCertificate(byte[] data,
 848         Collection<Certificate> certCollection) {
 849         try
 850         {
 851             ByteArrayInputStream bis = new ByteArrayInputStream(data);
 852 


 869         {
 870             // Ignore the exception and skip this certificate
 871             // TODO - throw CertificateException?
 872         }
 873     }
 874 
 875     /**
 876      * Returns the name of the keystore.
 877      */
 878     private String getName()
 879     {
 880         return storeName;
 881     }
 882 
 883     /**
 884      * Load keys and/or certificates from keystore into Collection.
 885      *
 886      * @param name Name of keystore.
 887      * @param entries Collection of key/certificate.
 888      */
 889     private native void loadKeysOrCertificateChains(String name,
 890         Collection<KeyEntry> entries) throws KeyStoreException;
 891 
 892     /**
 893      * Stores a DER-encoded certificate into the certificate store
 894      *
 895      * @param name Name of the keystore.
 896      * @param alias Name of the certificate.
 897      * @param encoding DER-encoded certificate.
 898      */
 899     private native void storeCertificate(String name, String alias,
 900         byte[] encoding, int encodingLength, long hCryptProvider,
 901         long hCryptKey) throws CertificateException, KeyStoreException;
 902 
 903     /**
 904      * Removes the certificate from the certificate store
 905      *
 906      * @param name Name of the keystore.
 907      * @param alias Name of the certificate.
 908      * @param encoding DER-encoded certificate.
 909      */
 910     private native void removeCertificate(String name, String alias,


   1 /*
   2  * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 171     };
 172 
 173     /*
 174      * An X.509 certificate factory.
 175      * Used to create an X.509 certificate from its DER-encoding.
 176      */
 177     private CertificateFactory certificateFactory = null;
 178 
 179     /*
 180      * Compatibility mode: for applications that assume keystores are
 181      * stream-based this mode tolerates (but ignores) a non-null stream
 182      * or password parameter when passed to the load or store methods.
 183      * The mode is enabled by default.
 184      */
 185     private static final String KEYSTORE_COMPATIBILITY_MODE_PROP =
 186         "sun.security.mscapi.keyStoreCompatibilityMode";
 187     private final boolean keyStoreCompatibilityMode;
 188 
 189     /*
 190      * The keystore entries.
 191      * Keys in the map are unique aliases (thus can differ from
 192      * KeyEntry.getAlias())
 193      */
 194     private Map<String,KeyEntry> entries = new HashMap<>();
 195 
 196     /*
 197      * The keystore name.
 198      * Case is not significant.
 199      */
 200     private final String storeName;
 201 
 202     KeyStore(String storeName) {
 203         // Get the compatibility mode
 204         String prop = AccessController.doPrivileged(
 205             (PrivilegedAction<String>) () -> System.getProperty(KEYSTORE_COMPATIBILITY_MODE_PROP));
 206 
 207         if ("false".equalsIgnoreCase(prop)) {
 208             keyStoreCompatibilityMode = false;
 209         } else {
 210             keyStoreCompatibilityMode = true;
 211         }
 212 
 213         this.storeName = storeName;
 214     }


 233      * @exception NoSuchAlgorithmException if the algorithm for recovering the
 234      * key cannot be found,
 235      * or if compatibility mode is disabled and <code>password</code> is
 236      * non-null.
 237      * @exception UnrecoverableKeyException if the key cannot be recovered.
 238      */
 239     public java.security.Key engineGetKey(String alias, char[] password)
 240         throws NoSuchAlgorithmException, UnrecoverableKeyException
 241     {
 242         if (alias == null) {
 243             return null;
 244         }
 245 
 246         if (password != null && !keyStoreCompatibilityMode) {
 247             throw new UnrecoverableKeyException("Password must be null");
 248         }
 249 
 250         if (engineIsKeyEntry(alias) == false)
 251             return null;
 252 
 253         KeyEntry entry = entries.get(alias);
 254         return (entry == null)
 255                 ? null
 256                 : entry.getPrivateKey();



 257     }
 258 
 259     /**
 260      * Returns the certificate chain associated with the given alias.
 261      *
 262      * @param alias the alias name
 263      *
 264      * @return the certificate chain (ordered with the user's certificate first
 265      * and the root certificate authority last), or null if the given alias
 266      * does not exist or does not contain a certificate chain (i.e., the given
 267      * alias identifies either a <i>trusted certificate entry</i> or a
 268      * <i>key entry</i> without a certificate chain).
 269      */
 270     public Certificate[] engineGetCertificateChain(String alias)
 271     {
 272         if (alias == null) {
 273             return null;
 274         }
 275 
 276         KeyEntry entry = entries.get(alias);
 277         X509Certificate[] certChain = (entry == null)
 278                 ? null 
 279                 : entry.getCertificateChain();
 280         return (certChain == null)
 281                 ? null
 282                 : certChain.clone();


 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     {
 302         if (alias == null) {
 303             return null;
 304         }
 305 
 306         KeyEntry entry = entries.get(alias);
 307         X509Certificate[] certChain = (entry == null)
 308                 ? null
 309                 : entry.getCertificateChain();
 310         return (certChain == null || certChain.length == 0)
 311                 ? null
 312                 : certChain[0];


 313     }
 314 
 315     /**
 316      * Returns the creation date of the entry identified by the given alias.
 317      *
 318      * @param alias the alias name
 319      *
 320      * @return the creation date of this entry, or null if the given alias does
 321      * not exist
 322      */
 323     public Date engineGetCreationDate(String alias) {
 324         if (alias == null) {
 325             return null;
 326         }
 327         return new Date();
 328     }
 329 
 330     /**
 331      * Stores the given private key and associated certificate chain in the
 332      * keystore.


 356      *        <code>java.security.PrivateKey</code>).
 357      *
 358      * @exception KeyStoreException if the given key is not a private key,
 359      * cannot be protected, or if compatibility mode is disabled and
 360      * <code>password</code> is non-null, or if this operation fails for
 361      * some other reason.
 362      */
 363     public void engineSetKeyEntry(String alias, java.security.Key key,
 364         char[] password, Certificate[] chain) throws KeyStoreException
 365     {
 366         if (alias == null) {
 367             throw new KeyStoreException("alias must not be null");
 368         }
 369 
 370         if (password != null && !keyStoreCompatibilityMode) {
 371             throw new KeyStoreException("Password must be null");
 372         }
 373 
 374         if (key instanceof RSAPrivateCrtKey) {
 375 
 376             KeyEntry entry = entries.get(alias);









 377 
 378             X509Certificate[] xchain;
 379             if (chain != null) {
 380                 if (chain instanceof X509Certificate[]) {
 381                     xchain = (X509Certificate[]) chain;
 382                 } else {
 383                     xchain = new X509Certificate[chain.length];
 384                     System.arraycopy(chain, 0, xchain, 0, chain.length);
 385                 }
 386             } else {
 387                 xchain = null;
 388             }
 389 
 390             if (entry == null) {
 391                 entry =
 392                     //TODO new KeyEntry(alias, key, (X509Certificate[]) chain);
 393                     new KeyEntry(alias, null, xchain);
 394                 storeWithUniqueAlias(alias, entry);
 395             }
 396 
 397             entry.setAlias(alias);
 398 
 399             try {
 400                 entry.setPrivateKey((RSAPrivateCrtKey) key);
 401                 entry.setCertificateChain(xchain);
 402 
 403             } catch (CertificateException ce) {
 404                 throw new KeyStoreException(ce);
 405 
 406             } catch (InvalidKeyException ike) {
 407                 throw new KeyStoreException(ike);
 408             }
 409 
 410         } else {
 411             throw new UnsupportedOperationException(
 412                 "Cannot assign the key to the given alias.");
 413         }
 414     }


 453      *
 454      * @param alias the alias name
 455      * @param cert the certificate
 456      *
 457      * @exception KeyStoreException if the given alias already exists and does
 458      * not identify a <i>trusted certificate entry</i>, or this operation
 459      * fails for some other reason.
 460      */
 461     public void engineSetCertificateEntry(String alias, Certificate cert)
 462         throws KeyStoreException
 463     {
 464         if (alias == null) {
 465             throw new KeyStoreException("alias must not be null");
 466         }
 467 
 468         if (cert instanceof X509Certificate) {
 469 
 470             // TODO - build CryptoAPI chain?
 471             X509Certificate[] chain =
 472                 new X509Certificate[]{ (X509Certificate) cert };
 473             KeyEntry entry = entries.get(alias);









 474 
 475             if (entry == null) {
 476                 entry =
 477                     new KeyEntry(alias, null, chain);
 478                 storeWithUniqueAlias(alias, entry);

 479             }
 480 
 481             if (entry.getPrivateKey() == null) { // trusted-cert entry
 482                 entry.setAlias(alias);
 483 
 484                 try {
 485                     entry.setCertificateChain(chain);
 486 
 487                 } catch (CertificateException ce) {
 488                     throw new KeyStoreException(ce);
 489                 }
 490             }
 491 
 492         } else {
 493             throw new UnsupportedOperationException(
 494                 "Cannot assign the certificate to the given alias.");
 495         }
 496     }
 497 
 498     /**
 499      * Deletes the entry identified by the given alias from this keystore.
 500      *
 501      * @param alias the alias name
 502      *
 503      * @exception KeyStoreException if the entry cannot be removed.
 504      */
 505     public void engineDeleteEntry(String alias)
 506         throws KeyStoreException
 507     {
 508         if (alias == null) {
 509             throw new KeyStoreException("alias must not be null");
 510         }
 511 
 512         KeyEntry entry = entries.remove(alias);
 513         if (entry != null) {

 514             // Get end-entity certificate and remove from system cert store
 515             X509Certificate[] certChain = entry.getCertificateChain();
 516             if (certChain != null) {
 517 
 518                 try {
 519 
 520                     byte[] encoding = certChain[0].getEncoded();
 521                     removeCertificate(getName(), entry.getAlias(), encoding,
 522                             encoding.length);
 523 
 524                 } catch (CertificateException e) {
 525                     throw new KeyStoreException("Cannot remove entry: ", e);

 526                 }
 527             }
 528             Key privateKey = entry.getPrivateKey();
 529             if (privateKey != null) {
 530                 destroyKeyContainer(
 531                     Key.getContainerName(privateKey.getHCryptProvider()));
 532             }




 533         }
 534     }
 535 
 536     /**
 537      * Lists all the alias names of this keystore.
 538      *
 539      * @return enumeration of the alias names
 540      */
 541     public Enumeration<String> engineAliases() {
 542         final Iterator<String> iter = entries.keySet().iterator();

 543 
 544         return new Enumeration<String>()
 545         {
 546             public boolean hasMoreElements()
 547             {
 548                 return iter.hasNext();
 549             }
 550 
 551             public String nextElement()
 552             {
 553                 return iter.next();

 554             }
 555         };
 556     }
 557 
 558     /**
 559      * Checks if the given alias exists in this keystore.
 560      *
 561      * @param alias the alias name
 562      *
 563      * @return true if the alias exists, false otherwise
 564      */
 565     public boolean engineContainsAlias(String alias) {
 566         return entries.containsKey(alias);








 567     }
 568 
 569     /**
 570      * Retrieves the number of entries in this keystore.
 571      *
 572      * @return the number of entries in this keystore
 573      */
 574     public int engineSize() {
 575         return entries.size();
 576     }
 577 
 578     /**
 579      * Returns true if the entry identified by the given alias is a
 580      * <i>key entry</i>, and false otherwise.
 581      *
 582      * @return true if the entry identified by the given alias is a
 583      * <i>key entry</i>, false otherwise.
 584      */
 585     public boolean engineIsKeyEntry(String alias) {
 586 
 587         if (alias == null) {
 588             return false;
 589         }
 590 
 591         KeyEntry entry = entries.get(alias);
 592         return entry != null && entry.getPrivateKey() != null;





 593     }
 594 
 595     /**
 596      * Returns true if the entry identified by the given alias is a
 597      * <i>trusted certificate entry</i>, and false otherwise.
 598      *
 599      * @return true if the entry identified by the given alias is a
 600      * <i>trusted certificate entry</i>, false otherwise.
 601      */
 602     public boolean engineIsCertificateEntry(String alias) {






 603 
 604         if (alias == null) {
 605             return false;
 606         }
 607 
 608         KeyEntry entry = entries.get(alias);
 609         return entry != null && entry.getPrivateKey() == null;
 610     }
 611 
 612     /**
 613      * Returns the (alias) name of the first keystore entry whose certificate
 614      * matches the given certificate.
 615      *
 616      * <p>This method attempts to match the given certificate with each
 617      * keystore entry. If the entry being considered
 618      * is a <i>trusted certificate entry</i>, the given certificate is
 619      * compared to that entry's certificate. If the entry being considered is
 620      * a <i>key entry</i>, the given certificate is compared to the first
 621      * element of that entry's certificate chain (if a chain exists).
 622      *
 623      * @param cert the certificate to match with.
 624      *
 625      * @return the (alias) name of the first entry with matching certificate,
 626      * or null if no such entry exists in this keystore.
 627      */
 628     public String engineGetCertificateAlias(Certificate cert) {
 629 
 630         for (Map.Entry<String,KeyEntry> mapEntry : entries.entrySet()) {
 631             KeyEntry entry = mapEntry.getValue();
 632             if (entry.certChain != null && entry.certChain[0].equals(cert)) {
 633                 return entry.getAlias();
 634             }
 635         }
 636 
 637         return null;
 638     }
 639 
 640     /**
 641      * engineStore is currently a no-op.
 642      * Entries are stored during engineSetEntry.
 643      *
 644      * A compatibility mode is supported for applications that assume
 645      * keystores are stream-based. It permits (but ignores) a non-null
 646      * <code>stream</code> or <code>password</code>.
 647      * The mode is enabled by default.
 648      * Set the
 649      * <code>sun.security.mscapi.keyStoreCompatibilityMode</code>
 650      * system property to <code>false</code> to disable compatibility mode
 651      * and reject a non-null <code>stream</code> or <code>password</code>.


 704 
 705         if (password != null && !keyStoreCompatibilityMode) {
 706             throw new IOException("Keystore password must be null");
 707         }
 708 
 709         /*
 710          * Use the same security check as AuthProvider.login
 711          */
 712         SecurityManager sm = System.getSecurityManager();
 713         if (sm != null) {
 714             sm.checkPermission(new SecurityPermission(
 715                 "authProvider.SunMSCAPI"));
 716         }
 717 
 718         // Clear all key entries
 719         entries.clear();
 720 
 721         try {
 722 
 723             // Load keys and/or certificate chains
 724             loadKeysOrCertificateChains(getName());
 725 
 726         } catch (KeyStoreException e) {
 727             throw new IOException(e);
 728         }
 729     }
 730 
 731     /**
 732      * Stores the given entry into the map, making sure
 733      * the alias, used as the key is unique.
 734      * If the same alias already exists, it tries to append
 735      * a suffix  (1), (2), etc to it until it finds a unique
 736      * value.
 737      */
 738     private void storeWithUniqueAlias(String alias, KeyEntry entry) {
 739         String uniqAlias = alias;
 740         int uniqNum = 1;
 741 
 742         while (true) {
 743             if (entries.putIfAbsent(uniqAlias, entry) == null) {
 744                 break;
 745             }
 746             uniqAlias = alias + " (" + (uniqNum++) + ")";
 747         }
 748     }
 749 
 750 
 751     /**
 752      * Generates a certificate chain from the collection of
 753      * certificates and stores the result into a key entry.
 754      */
 755     private void generateCertificateChain(String alias,
 756         Collection<? extends Certificate> certCollection)

 757     {
 758         try
 759         {
 760             X509Certificate[] certChain =
 761                 new X509Certificate[certCollection.size()];
 762 
 763             int i = 0;
 764             for (Iterator<? extends Certificate> iter =
 765                     certCollection.iterator(); iter.hasNext(); i++)
 766             {
 767                 certChain[i] = (X509Certificate) iter.next();
 768             }
 769 
 770             storeWithUniqueAlias(alias,
 771                     new KeyEntry(alias, null, certChain));


 772         }
 773         catch (Throwable e)
 774         {
 775             // Ignore the exception and skip this entry
 776             // TODO - throw CertificateException?
 777         }
 778     }
 779 
 780     /**
 781      * Generates RSA key and certificate chain from the private key handle,
 782      * collection of certificates and stores the result into key entries.
 783      */
 784     private void generateRSAKeyAndCertificateChain(String alias,
 785         long hCryptProv, long hCryptKey, int keyLength,
 786         Collection<? extends Certificate> certCollection)

 787     {
 788         try
 789         {
 790             X509Certificate[] certChain =
 791                 new X509Certificate[certCollection.size()];
 792 
 793             int i = 0;
 794             for (Iterator<? extends Certificate> iter =
 795                     certCollection.iterator(); iter.hasNext(); i++)
 796             {
 797                 certChain[i] = (X509Certificate) iter.next();
 798             }
 799 
 800             storeWithUniqueAlias(alias, new KeyEntry(alias,
 801                     new RSAPrivateKey(hCryptProv, hCryptKey, keyLength),
 802                     certChain));


 803         }
 804         catch (Throwable e)
 805         {
 806             // Ignore the exception and skip this entry
 807             // TODO - throw CertificateException?
 808         }
 809     }
 810 
 811     /**
 812      * Generates certificates from byte data and stores into cert collection.
 813      *
 814      * @param data Byte data.
 815      * @param certCollection Collection of certificates.
 816      */
 817     private void generateCertificate(byte[] data,
 818         Collection<Certificate> certCollection) {
 819         try
 820         {
 821             ByteArrayInputStream bis = new ByteArrayInputStream(data);
 822 


 839         {
 840             // Ignore the exception and skip this certificate
 841             // TODO - throw CertificateException?
 842         }
 843     }
 844 
 845     /**
 846      * Returns the name of the keystore.
 847      */
 848     private String getName()
 849     {
 850         return storeName;
 851     }
 852 
 853     /**
 854      * Load keys and/or certificates from keystore into Collection.
 855      *
 856      * @param name Name of keystore.
 857      * @param entries Collection of key/certificate.
 858      */
 859     private native void loadKeysOrCertificateChains(String name)
 860             throws KeyStoreException;
 861 
 862     /**
 863      * Stores a DER-encoded certificate into the certificate store
 864      *
 865      * @param name Name of the keystore.
 866      * @param alias Name of the certificate.
 867      * @param encoding DER-encoded certificate.
 868      */
 869     private native void storeCertificate(String name, String alias,
 870         byte[] encoding, int encodingLength, long hCryptProvider,
 871         long hCryptKey) throws CertificateException, KeyStoreException;
 872 
 873     /**
 874      * Removes the certificate from the certificate store
 875      *
 876      * @param name Name of the keystore.
 877      * @param alias Name of the certificate.
 878      * @param encoding DER-encoded certificate.
 879      */
 880     private native void removeCertificate(String name, String alias,


< prev index next >