| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.security; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.security.cert.Certificate; |
| import java.security.cert.CertificateException; |
| import java.util.Date; |
| import java.util.Enumeration; |
| import javax.crypto.SecretKey; |
| import javax.security.auth.callback.CallbackHandler; |
| import javax.security.auth.callback.PasswordCallback; |
| |
| /** |
| * {@code KeyStoreSpi} is the Service Provider Interface (SPI) definition for |
| * {@link KeyStore}. |
| * |
| * @see KeyStore |
| */ |
| public abstract class KeyStoreSpi { |
| |
| /** |
| * Returns the key with the given alias, using the password to recover the |
| * key from the store. |
| * |
| * @param alias |
| * the alias for the entry. |
| * @param password |
| * the password used to recover the key. |
| * @return the key with the specified alias, or {@code null} if the |
| * specified alias is not bound to an entry. |
| * @throws NoSuchAlgorithmException |
| * if the algorithm for recovering the key is not available. |
| * @throws UnrecoverableKeyException |
| * if the key can not be recovered. |
| */ |
| public abstract Key engineGetKey(String alias, char[] password) |
| throws NoSuchAlgorithmException, UnrecoverableKeyException; |
| |
| /** |
| * Returns the certificate chain for the entry with the given alias. |
| * |
| * @param alias |
| * the alias for the entry |
| * @return the certificate chain for the entry with the given alias, or |
| * {@code null} if the specified alias is not bound to an entry. |
| */ |
| public abstract Certificate[] engineGetCertificateChain(String alias); |
| |
| /** |
| * Returns the trusted certificate for the entry with the given alias. |
| * |
| * @param alias |
| * the alias for the entry. |
| * @return the trusted certificate for the entry with the given alias, or |
| * {@code null} if the specified alias is not bound to an entry. |
| */ |
| public abstract Certificate engineGetCertificate(String alias); |
| |
| /** |
| * Returns the creation date of the entry with the given alias. |
| * |
| * @param alias |
| * the alias for the entry. |
| * @return the creation date, or {@code null} if the specified alias is not |
| * bound to an entry. |
| */ |
| public abstract Date engineGetCreationDate(String alias); |
| |
| /** |
| * Associates the given alias with the key, password and certificate chain. |
| * <p> |
| * If the specified alias already exists, it will be reassigned. |
| * |
| * @param alias |
| * the alias for the key. |
| * @param key |
| * the key. |
| * @param password |
| * the password. |
| * @param chain |
| * the certificate chain. |
| * @throws KeyStoreException |
| * if the specified key can not be protected, or if this |
| * operation fails for another reason. |
| * @throws IllegalArgumentException |
| * if {@code key} is a {@code PrivateKey} and {@code chain} does |
| * not contain any certificates. |
| */ |
| public abstract void engineSetKeyEntry(String alias, Key key, |
| char[] password, Certificate[] chain) throws KeyStoreException; |
| |
| /** |
| * Associates the given alias with a key and a certificate chain. |
| * <p> |
| * If the specified alias already exists, it will be reassigned. |
| * |
| * @param alias |
| * the alias for the key. |
| * @param key |
| * the key in an encoded format. |
| * @param chain |
| * the certificate chain. |
| * @throws KeyStoreException |
| * if this operation fails. |
| * @throws IllegalArgumentException |
| * if {@code key} is a {@code PrivateKey} and {@code chain} |
| * does. |
| */ |
| public abstract void engineSetKeyEntry(String alias, byte[] key, |
| Certificate[] chain) throws KeyStoreException; |
| |
| /** |
| * Associates the given alias with a certificate. |
| * <p> |
| * If the specified alias already exists, it will be reassigned. |
| * |
| * @param alias |
| * the alias for the certificate. |
| * @param cert |
| * the certificate. |
| * @throws KeyStoreException |
| * if an existing alias is not associated to an entry containing |
| * a trusted certificate, or this method fails for any other |
| * reason. |
| */ |
| public abstract void engineSetCertificateEntry(String alias, |
| Certificate cert) throws KeyStoreException; |
| |
| /** |
| * Deletes the entry identified with the given alias from this {@code |
| * KeyStoreSpi}. |
| * |
| * @param alias |
| * the alias for the entry. |
| * @throws KeyStoreException |
| * if the entry can not be deleted. |
| */ |
| public abstract void engineDeleteEntry(String alias) |
| throws KeyStoreException; |
| |
| /** |
| * Returns an {@code Enumeration} over all alias names stored in this |
| * {@code KeyStoreSpi}. |
| * |
| * @return an {@code Enumeration} over all alias names stored in this |
| * {@code KeyStoreSpi}. |
| */ |
| public abstract Enumeration<String> engineAliases(); |
| |
| /** |
| * Indicates whether the given alias is present in this {@code KeyStoreSpi}. |
| * |
| * @param alias |
| * the alias of an entry. |
| * @return {@code true} if the alias exists, {@code false} otherwise. |
| */ |
| public abstract boolean engineContainsAlias(String alias); |
| |
| /** |
| * Returns the number of entries stored in this {@code KeyStoreSpi}. |
| * |
| * @return the number of entries stored in this {@code KeyStoreSpi}. |
| */ |
| public abstract int engineSize(); |
| |
| /** |
| * Indicates whether the specified alias is associated with either a |
| * {@link KeyStore.PrivateKeyEntry} or a {@link KeyStore.SecretKeyEntry}. |
| * |
| * @param alias |
| * the alias of an entry. |
| * @return {@code true} if the given alias is associated with a key entry. |
| */ |
| public abstract boolean engineIsKeyEntry(String alias); |
| |
| /** |
| * Indicates whether the specified alias is associated with a |
| * {@link KeyStore.TrustedCertificateEntry}. |
| * |
| * @param alias |
| * the alias of an entry. |
| * @return {@code true} if the given alias is associated with a certificate |
| * entry. |
| */ |
| public abstract boolean engineIsCertificateEntry(String alias); |
| |
| /** |
| * Returns the alias associated with the first entry whose certificate |
| * matches the specified certificate. |
| * |
| * @param cert |
| * the certificate to find the associated entry's alias for. |
| * @return the alias or {@code null} if no entry with the specified |
| * certificate can be found. |
| */ |
| public abstract String engineGetCertificateAlias(Certificate cert); |
| |
| /** |
| * Writes this {@code KeyStoreSpi} to the specified {@code OutputStream}. |
| * The data written to the {@code OutputStream} is protected by the |
| * specified password. |
| * |
| * @param stream |
| * the {@code OutputStream} to write the store's data to. |
| * @param password |
| * the password to protect the data. |
| * @throws IOException |
| * if a problem occurred while writing to the stream. |
| * @throws NoSuchAlgorithmException |
| * if the required algorithm is not available. |
| * @throws CertificateException |
| * if the an exception occurred while storing the certificates |
| * of this code {@code KeyStoreSpi}. |
| */ |
| public abstract void engineStore(OutputStream stream, char[] password) |
| throws IOException, NoSuchAlgorithmException, CertificateException; |
| |
| /** |
| * Stores this {@code KeyStoreSpi} using the specified {@code |
| * LoadStoreParameter}. |
| * |
| * @param param |
| * the {@code LoadStoreParameter} that specifies how to store |
| * this {@code KeyStoreSpi}, maybe {@code null}. |
| * @throws IOException |
| * if a problem occurred while writing to the stream. |
| * @throws NoSuchAlgorithmException |
| * if the required algorithm is not available. |
| * @throws CertificateException |
| * if the an exception occurred while storing the certificates |
| * of this code {@code KeyStoreSpi}. |
| * @throws IllegalArgumentException |
| * if the given {@link KeyStore.LoadStoreParameter} is not |
| * recognized. |
| */ |
| public void engineStore(KeyStore.LoadStoreParameter param) |
| throws IOException, NoSuchAlgorithmException, CertificateException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * Loads this {@code KeyStoreSpi} from the given {@code InputStream}. |
| * Utilizes the given password to verify the stored data. |
| * |
| * @param stream |
| * the {@code InputStream} to load this {@code KeyStoreSpi}'s |
| * data from. |
| * @param password |
| * the password to verify the stored data, maybe {@code null}. |
| * @throws IOException |
| * if a problem occurred while reading from the stream. |
| * @throws NoSuchAlgorithmException |
| * if the required algorithm is not available. |
| * @throws CertificateException |
| * if the an exception occurred while loading the certificates |
| * of this code {@code KeyStoreSpi}. |
| */ |
| public abstract void engineLoad(InputStream stream, char[] password) |
| throws IOException, NoSuchAlgorithmException, CertificateException; |
| |
| /** |
| * Loads this {@code KeyStoreSpi} using the specified {@code |
| * LoadStoreParameter}. |
| * |
| * @param param |
| * the {@code LoadStoreParameter} that specifies how to load this |
| * {@code KeyStoreSpi}, maybe {@code null}. |
| * @throws IOException |
| * if a problem occurred while reading from the stream. |
| * @throws NoSuchAlgorithmException |
| * if the required algorithm is not available. |
| * @throws CertificateException |
| * if the an exception occurred while loading the certificates |
| * of this code {@code KeyStoreSpi}. |
| * @throws IllegalArgumentException |
| * if the given {@link KeyStore.LoadStoreParameter} is not |
| * recognized. |
| */ |
| public void engineLoad(KeyStore.LoadStoreParameter param) |
| throws IOException, NoSuchAlgorithmException, CertificateException { |
| if (param == null) { |
| engineLoad(null, null); |
| return; |
| } |
| char[] pwd; |
| KeyStore.ProtectionParameter pp = param.getProtectionParameter(); |
| if (pp instanceof KeyStore.PasswordProtection) { |
| try { |
| pwd = ((KeyStore.PasswordProtection) pp).getPassword(); |
| engineLoad(null, pwd); |
| return; |
| } catch (IllegalStateException e) { |
| throw new IllegalArgumentException(e); |
| } |
| } |
| if (pp instanceof KeyStore.CallbackHandlerProtection) { |
| try { |
| pwd = getPasswordFromCallBack(pp); |
| engineLoad(null, pwd); |
| return; |
| } catch (UnrecoverableEntryException e) { |
| throw new IllegalArgumentException(e); |
| } |
| } |
| throw new UnsupportedOperationException("protectionParameter is neither PasswordProtection " |
| + "nor CallbackHandlerProtection instance"); |
| } |
| |
| /** |
| * Returns the {@code Entry} with the given alias, using the specified |
| * {@code ProtectionParameter}. |
| * |
| * @param alias |
| * the alias of the requested entry. |
| * @param protParam |
| * the {@code ProtectionParameter}, used to protect the requested |
| * entry, maybe {@code null}. |
| * @return he {@code Entry} with the given alias, using the specified |
| * {@code ProtectionParameter}. |
| * @throws NoSuchAlgorithmException |
| * if the required algorithm is not available. |
| * @throws UnrecoverableEntryException |
| * if the entry can not be recovered. |
| * @throws KeyStoreException |
| * if this operation fails |
| */ |
| public KeyStore.Entry engineGetEntry(String alias, |
| KeyStore.ProtectionParameter protParam) throws KeyStoreException, |
| NoSuchAlgorithmException, UnrecoverableEntryException { |
| if (!engineContainsAlias(alias)) { |
| return null; |
| } |
| if (engineIsCertificateEntry(alias)) { |
| return new KeyStore.TrustedCertificateEntry( |
| engineGetCertificate(alias)); |
| } |
| char[] passW = null; |
| if (protParam != null) { |
| if (protParam instanceof KeyStore.PasswordProtection) { |
| try { |
| passW = ((KeyStore.PasswordProtection) protParam) |
| .getPassword(); |
| } catch (IllegalStateException ee) { |
| throw new KeyStoreException("Password was destroyed", ee); |
| } |
| } else if (protParam instanceof KeyStore.CallbackHandlerProtection) { |
| passW = getPasswordFromCallBack(protParam); |
| } else { |
| throw new UnrecoverableEntryException("ProtectionParameter object is not " |
| + "PasswordProtection: " + protParam); |
| } |
| } |
| if (engineIsKeyEntry(alias)) { |
| Key key = engineGetKey(alias, passW); |
| if (key instanceof PrivateKey) { |
| return new KeyStore.PrivateKeyEntry((PrivateKey) key, |
| engineGetCertificateChain(alias)); |
| } |
| if (key instanceof SecretKey) { |
| return new KeyStore.SecretKeyEntry((SecretKey) key); |
| } |
| } |
| throw new NoSuchAlgorithmException("Unknown KeyStore.Entry object"); |
| } |
| |
| /** |
| * Stores the given {@code Entry} in this {@code KeyStoreSpi} and associates |
| * the entry with the given {@code alias}. The entry is protected by the |
| * specified {@code ProtectionParameter}. |
| * <p> |
| * If the specified alias already exists, it will be reassigned. |
| * |
| * @param alias |
| * the alias for the entry. |
| * @param entry |
| * the entry to store. |
| * @param protParam |
| * the {@code ProtectionParameter} to protect the entry. |
| * @throws KeyStoreException |
| * if this operation fails. |
| */ |
| public void engineSetEntry(String alias, KeyStore.Entry entry, |
| KeyStore.ProtectionParameter protParam) throws KeyStoreException { |
| if (entry == null) { |
| throw new KeyStoreException("entry == null"); |
| } |
| |
| if (engineContainsAlias(alias)) { |
| engineDeleteEntry(alias); |
| } |
| |
| if (entry instanceof KeyStore.TrustedCertificateEntry) { |
| KeyStore.TrustedCertificateEntry trE = (KeyStore.TrustedCertificateEntry) entry; |
| engineSetCertificateEntry(alias, trE.getTrustedCertificate()); |
| return; |
| } |
| |
| char[] passW = null; |
| if (protParam instanceof KeyStore.PasswordProtection) { |
| try { |
| passW = ((KeyStore.PasswordProtection) protParam).getPassword(); |
| } catch (IllegalStateException ee) { |
| throw new KeyStoreException("Password was destroyed", ee); |
| } |
| } else { |
| if (protParam instanceof KeyStore.CallbackHandlerProtection) { |
| try { |
| passW = getPasswordFromCallBack(protParam); |
| } catch (Exception e) { |
| throw new KeyStoreException(e); |
| } |
| } else { |
| throw new KeyStoreException("protParam should be PasswordProtection or " |
| + "CallbackHandlerProtection"); |
| } |
| } |
| |
| if (entry instanceof KeyStore.PrivateKeyEntry) { |
| KeyStore.PrivateKeyEntry prE = (KeyStore.PrivateKeyEntry) entry; |
| engineSetKeyEntry(alias, prE.getPrivateKey(), passW, prE |
| .getCertificateChain()); |
| return; |
| } |
| |
| if (entry instanceof KeyStore.SecretKeyEntry) { |
| KeyStore.SecretKeyEntry skE = (KeyStore.SecretKeyEntry) entry; |
| engineSetKeyEntry(alias, skE.getSecretKey(), passW, null); |
| // engineSetKeyEntry(alias, skE.getSecretKey().getEncoded(), null); |
| return; |
| } |
| |
| throw new KeyStoreException("Entry object is neither PrivateKeyObject nor SecretKeyEntry " |
| + "nor TrustedCertificateEntry: " + entry); |
| } |
| |
| /** |
| * Indicates whether the entry for the given alias is assignable to the |
| * provided {@code Class}. |
| * |
| * @param alias |
| * the alias for the entry. |
| * @param entryClass |
| * the type of the entry. |
| * @return {@code true} if the {@code Entry} for the alias is assignable to |
| * the specified {@code entryClass}. |
| */ |
| public boolean engineEntryInstanceOf(String alias, |
| Class<? extends KeyStore.Entry> entryClass) { |
| if (!engineContainsAlias(alias)) { |
| return false; |
| } |
| |
| try { |
| if (engineIsCertificateEntry(alias)) { |
| return entryClass |
| .isAssignableFrom(Class |
| .forName("java.security.KeyStore$TrustedCertificateEntry")); |
| } |
| |
| if (engineIsKeyEntry(alias)) { |
| if (entryClass.isAssignableFrom(Class |
| .forName("java.security.KeyStore$PrivateKeyEntry"))) { |
| return engineGetCertificate(alias) != null; |
| } |
| |
| if (entryClass.isAssignableFrom(Class |
| .forName("java.security.KeyStore$SecretKeyEntry"))) { |
| return engineGetCertificate(alias) == null; |
| } |
| } |
| } catch (ClassNotFoundException ignore) {} |
| |
| return false; |
| } |
| |
| /* |
| * This method returns password which is encapsulated in |
| * CallbackHandlerProtection object If there is no implementation of |
| * CallbackHandler then this method returns null |
| */ |
| static char[] getPasswordFromCallBack(KeyStore.ProtectionParameter protParam) |
| throws UnrecoverableEntryException { |
| |
| if (protParam == null) { |
| return null; |
| } |
| |
| if (!(protParam instanceof KeyStore.CallbackHandlerProtection)) { |
| throw new UnrecoverableEntryException("Incorrect ProtectionParameter"); |
| } |
| |
| String clName = Security.getProperty("auth.login.defaultCallbackHandler"); |
| if (clName == null) { |
| throw new UnrecoverableEntryException("Default CallbackHandler was not defined"); |
| |
| } |
| |
| try { |
| Class<?> cl = Class.forName(clName); |
| CallbackHandler cbHand = (CallbackHandler) cl.newInstance(); |
| PasswordCallback[] pwCb = { new PasswordCallback("password: ", true) }; |
| cbHand.handle(pwCb); |
| return pwCb[0].getPassword(); |
| } catch (Exception e) { |
| throw new UnrecoverableEntryException(e.toString()); |
| } |
| } |
| } |