/* * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.pkcs11; import java.math.BigInteger; import java.io.InputStream;import java.io.OutputStream;import java.io.IOException;import java.io.ByteArrayInputStream;import java.io.UnsupportedEncodingException; import java.util.Arrays;import java.util.Collection;import java.util.Collections;import java.util.Date;import java.util.Enumeration;import java.util.Iterator;import java.util.List;import java.util.ArrayList;import java.util.HashSet;import java.util.HashMap;import java.util.Set; import java.security.*;import java.security.KeyStore.*; import java.security.cert.CertPath;import java.security.cert.Certificate;import java.security.cert.X509Certificate;import java.security.cert.CertificateFactory;import java.security.cert.CertificateException; import java.security.interfaces.*;import java.security.spec.*; import javax.crypto.SecretKey;import javax.crypto.interfaces.*; import javax.security.auth.Subject;import javax.security.auth.x500.X500Principal;import javax.security.auth.login.LoginException;import javax.security.auth.callback.Callback;import javax.security.auth.callback.PasswordCallback;import javax.security.auth.callback.CallbackHandler;import javax.security.auth.callback.UnsupportedCallbackException; import sun.security.util.Debug;import sun.security.x509.SerialNumber;import sun.security.util.DerValue; import sun.security.ec.ECParameters; import sun.security.pkcs11.Secmod.*;import static sun.security.pkcs11.P11Util.*; import sun.security.pkcs11.wrapper.*;import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import sun.security.rsa.RSAKeyFactory; final class P11KeyStore extends KeyStoreSpi { private static final CK_ATTRIBUTE ATTR_CLASS_CERT = new CK_ATTRIBUTE(CKA_CLASS, CKO_CERTIFICATE); private static final CK_ATTRIBUTE ATTR_CLASS_PKEY = new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY); private static final CK_ATTRIBUTE ATTR_CLASS_SKEY = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY); private static final CK_ATTRIBUTE ATTR_X509_CERT_TYPE = new CK_ATTRIBUTE(CKA_CERTIFICATE_TYPE, CKC_X_509); private static final CK_ATTRIBUTE ATTR_TOKEN_TRUE = new CK_ATTRIBUTE(CKA_TOKEN, true); // XXX for testing purposes only // - NSS doesn't support persistent secret keys // (key type gets mangled if secret key is a token key) // - if debug is turned on, then this is set to false private static CK_ATTRIBUTE ATTR_SKEY_TOKEN_TRUE = ATTR_TOKEN_TRUE; private static final CK_ATTRIBUTE ATTR_TRUSTED_TRUE = new CK_ATTRIBUTE(CKA_TRUSTED, true); private static final CK_ATTRIBUTE ATTR_PRIVATE_TRUE = new CK_ATTRIBUTE(CKA_PRIVATE, true); private static final long NO_HANDLE = -1; private static final long FINDOBJECTS_MAX = 100; private static final String ALIAS_SEP = "/"; private static final boolean NSS_TEST = false; private static final Debug debug = Debug.getInstance("pkcs11keystore"); private static boolean CKA_TRUSTED_SUPPORTED = true; private final Token token; // If multiple certs are found to share the same CKA_LABEL // at load time (NSS-style keystore), then the keystore is read // and the unique keystore aliases are mapped to the entries. // However, write capabilities are disabled. private boolean writeDisabled = false; // Map of unique keystore aliases to entries in the token private HashMap<String, AliasInfo> aliasMap; // whether to use NSS Secmod info for trust attributes private final boolean useSecmodTrust; // if useSecmodTrust == true, which type of trust we are interested in private Secmod.TrustType nssTrustType; /** * The underlying token may contain multiple certs belonging to the * same "personality" (for example, a signing cert and encryption cert), * all sharing the same CKA_LABEL. These must be resolved * into unique keystore aliases. * * In addition, private keys and certs may not have a CKA_LABEL. * It is assumed that a private key and corresponding certificate * share the same CKA_ID, and that the CKA_ID is unique across the token. * The CKA_ID may not be human-readable. * These pairs must be resolved into unique keystore aliases. * * Furthermore, secret keys are assumed to have a CKA_LABEL * unique across the entire token. * * When the KeyStore is loaded, instances of this class are * created to represent the private keys/secret keys/certs * that reside on the token. */ private static class AliasInfo { // CKA_CLASS - entry type private CK_ATTRIBUTE type = null; // CKA_LABEL of cert and secret key private String label = null; // CKA_ID of the private key/cert pair private byte[] id = null; // CKA_TRUSTED - true if cert is trusted private boolean trusted = false; // either end-entity cert or trusted cert depending on 'type' private X509Certificate cert = null; // chain private X509Certificate chain[] = null; // true if CKA_ID for private key and cert match up private boolean matched = false; // SecretKeyEntry public AliasInfo(String label) { this.type = ATTR_CLASS_SKEY; this.label = label; } // PrivateKeyEntry public AliasInfo(String label, byte[] id, boolean trusted, X509Certificate cert) { this.type = ATTR_CLASS_PKEY; this.label = label; this.id = id; this.trusted = trusted; this.cert = cert; } public String toString() { StringBuilder sb = new StringBuilder(); if (type == ATTR_CLASS_PKEY) { sb.append("\ttype=[private key]\n"); } else if (type == ATTR_CLASS_SKEY) { sb.append("\ttype=[secret key]\n"); } else if (type == ATTR_CLASS_CERT) { sb.append("\ttype=[trusted cert]\n"); } sb.append("\tlabel=[" + label + "]\n"); if (id == null) { sb.append("\tid=[null]\n"); } else { sb.append("\tid=" + P11KeyStore.getID(id) + "\n"); } sb.append("\ttrusted=[" + trusted + "]\n"); sb.append("\tmatched=[" + matched + "]\n"); if (cert == null) { sb.append("\tcert=[null]\n"); } else { sb.append("\tcert=[\tsubject: " + cert.getSubjectX500Principal() + "\n\t\tissuer: " + cert.getIssuerX500Principal() + "\n\t\tserialNum: " + cert.getSerialNumber().toString() + "]"); } return sb.toString(); } } /** * callback handler for passing password to Provider.login method */ private static class PasswordCallbackHandler implements CallbackHandler { private char[] password; private PasswordCallbackHandler(char[] password) { if (password != null) { this.password = (char[])password.clone(); } } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { if (!(callbacks[0] instanceof PasswordCallback)) { throw new UnsupportedCallbackException(callbacks[0]); } PasswordCallback pc = (PasswordCallback)callbacks[0]; pc.setPassword(password); // this clones the password if not null } protected void finalize() throws Throwable { if (password != null) { Arrays.fill(password, ' '); } super.finalize(); } } /** * getTokenObject return value. * * if object is not found, type is set to null. * otherwise, type is set to the requested type. */ private static class THandle { private final long handle; // token object handle private final CK_ATTRIBUTE type; // CKA_CLASS private THandle(long handle, CK_ATTRIBUTE type) { this.handle = handle; this.type = type; } } P11KeyStore(Token token) { this.token = token; this.useSecmodTrust = token.provider.nssUseSecmodTrust; } /** * Returns the key associated with the given alias. * The key must have been associated with * the alias by a call to <code>setKeyEntry</code>, * or by a call to <code>setEntry</code> with a * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>. * * @param alias the alias name * @param password the password, which must be <code>null</code> * * @return the requested key, or null if the given alias does not exist * or does not identify a key-related entry. * * @exception NoSuchAlgorithmException if the algorithm for recovering the * key cannot be found * @exception UnrecoverableKeyException if the key cannot be recovered */ public synchronized Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { token.ensureValid(); if (password != null && !token.config.getKeyStoreCompatibilityMode()) { throw new NoSuchAlgorithmException("password must be null"); } AliasInfo aliasInfo = aliasMap.get(alias); if (aliasInfo == null || aliasInfo.type == ATTR_CLASS_CERT) { return null; } Session session = null; try { session = token.getOpSession(); if (aliasInfo.type == ATTR_CLASS_PKEY) { THandle h = getTokenObject(session, aliasInfo.type, aliasInfo.id, null); if (h.type == ATTR_CLASS_PKEY) { return loadPkey(session, h.handle); } } else { THandle h = getTokenObject(session, ATTR_CLASS_SKEY, null, alias); if (h.type == ATTR_CLASS_SKEY) { return loadSkey(session, h.handle); } } // did not find anything return null; } catch (PKCS11Exception pe) { throw new ProviderException(pe); } catch (KeyStoreException ke) { throw new ProviderException(ke); } finally { token.releaseSession(session); } } /** * Returns the certificate chain associated with the given alias. * The certificate chain must have been associated with the alias * by a call to <code>setKeyEntry</code>, * or by a call to <code>setEntry</code> with a * <code>PrivateKeyEntry</code>. * * @param alias the alias name * * @return the certificate chain (ordered with the user's certificate first * and the root certificate authority last), or null if the given alias * does not exist or does not contain a certificate chain */ public synchronized Certificate[] engineGetCertificateChain(String alias) { token.ensureValid(); AliasInfo aliasInfo = aliasMap.get(alias); if (aliasInfo == null || aliasInfo.type != ATTR_CLASS_PKEY) { return null; } return aliasInfo.chain; } /** * Returns the certificate associated with the given alias. * * <p> If the given alias name identifies an entry * created by a call to <code>setCertificateEntry</code>, * or created by a call to <code>setEntry</code> with a * <code>TrustedCertificateEntry</code>, * then the trusted certificate contained in that entry is returned. * * <p> If the given alias name identifies an entry * created by a call to <code>setKeyEntry</code>, * or created by a call to <code>setEntry</code> with a * <code>PrivateKeyEntry</code>, * then the first element of the certificate chain in that entry * (if a chain exists) is returned. * * @param alias the alias name * * @return the certificate, or null if the given alias does not exist or * does not contain a certificate. */ public synchronized Certificate engineGetCertificate(String alias) { token.ensureValid(); AliasInfo aliasInfo = aliasMap.get(alias); if (aliasInfo == null) { return null; } return aliasInfo.cert; } /** * Returns the creation date of the entry identified by the given alias. * * @param alias the alias name * * @return the creation date of this entry, or null if the given alias does * not exist */ public Date engineGetCreationDate(String alias) { token.ensureValid(); throw new ProviderException(new UnsupportedOperationException()); } /** * Assigns the given key to the given alias, protecting it with the given * password. * * <p>If the given key is of type <code>java.security.PrivateKey</code>, * it must be accompanied by a certificate chain certifying the * corresponding public key. * * <p>If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key to be associated with the alias * @param password the password to protect the key * @param chain the certificate chain for the corresponding public * key (only required if the given key is of type * <code>java.security.PrivateKey</code>). * * @exception KeyStoreException if the given key cannot be protected, or * this operation fails for some other reason */ public synchronized void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { token.ensureValid(); checkWrite(); if (!(key instanceof PrivateKey) && !(key instanceof SecretKey)) { throw new KeyStoreException("key must be PrivateKey or SecretKey"); } else if (key instanceof PrivateKey && chain == null) { throw new KeyStoreException ("PrivateKey must be accompanied by non-null chain"); } else if (key instanceof SecretKey && chain != null) { throw new KeyStoreException ("SecretKey must be accompanied by null chain"); } else if (password != null && !token.config.getKeyStoreCompatibilityMode()) { throw new KeyStoreException("Password must be null"); } KeyStore.Entry entry = null; try { if (key instanceof PrivateKey) { entry = new KeyStore.PrivateKeyEntry((PrivateKey)key, chain); } else if (key instanceof SecretKey) { entry = new KeyStore.SecretKeyEntry((SecretKey)key); } } catch (NullPointerException npe) { throw new KeyStoreException(npe); } catch (IllegalArgumentException iae) { throw new KeyStoreException(iae); } engineSetEntry(alias, entry, new KeyStore.PasswordProtection(password)); } /** * Assigns the given key (that has already been protected) to the given * alias. * * <p>If the protected key is of type * <code>java.security.PrivateKey</code>, * it must be accompanied by a certificate chain certifying the * corresponding public key. * * <p>If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key (in protected format) to be associated with the alias * @param chain the certificate chain for the corresponding public * key (only useful if the protected key is of type * <code>java.security.PrivateKey</code>). * * @exception KeyStoreException if this operation fails. */ public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { token.ensureValid(); throw new ProviderException(new UnsupportedOperationException()); } /** * Assigns the given certificate to the given alias. * * <p> If the given alias identifies an existing entry * created by a call to <code>setCertificateEntry</code>,Lines 1–500 of 2699. Load more
/* * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.pkcs11; import java.math.BigInteger; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.ArrayList; import java.util.HashSet; import java.util.HashMap; import java.util.Set; import java.security.*; import java.security.KeyStore.*; import java.security.cert.CertPath; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.cert.CertificateFactory; import java.security.cert.CertificateException; import java.security.interfaces.*; import java.security.spec.*; import javax.crypto.SecretKey; import javax.crypto.interfaces.*; import javax.security.auth.Subject; import javax.security.auth.x500.X500Principal; import javax.security.auth.login.LoginException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import sun.security.util.Debug; import sun.security.x509.SerialNumber; import sun.security.util.DerValue; import sun.security.ec.ECParameters; import sun.security.pkcs11.Secmod.*; import static sun.security.pkcs11.P11Util.*; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import sun.security.rsa.RSAKeyFactory; final class P11KeyStore extends KeyStoreSpi { private static final CK_ATTRIBUTE ATTR_CLASS_CERT = new CK_ATTRIBUTE(CKA_CLASS, CKO_CERTIFICATE); private static final CK_ATTRIBUTE ATTR_CLASS_PKEY = new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY); private static final CK_ATTRIBUTE ATTR_CLASS_SKEY = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY); private static final CK_ATTRIBUTE ATTR_X509_CERT_TYPE = new CK_ATTRIBUTE(CKA_CERTIFICATE_TYPE, CKC_X_509); private static final CK_ATTRIBUTE ATTR_TOKEN_TRUE = new CK_ATTRIBUTE(CKA_TOKEN, true); // XXX for testing purposes only // - NSS doesn't support persistent secret keys // (key type gets mangled if secret key is a token key) // - if debug is turned on, then this is set to false private static CK_ATTRIBUTE ATTR_SKEY_TOKEN_TRUE = ATTR_TOKEN_TRUE; private static final CK_ATTRIBUTE ATTR_TRUSTED_TRUE = new CK_ATTRIBUTE(CKA_TRUSTED, true); private static final CK_ATTRIBUTE ATTR_PRIVATE_TRUE = new CK_ATTRIBUTE(CKA_PRIVATE, true); private static final long NO_HANDLE = -1; private static final long FINDOBJECTS_MAX = 100; private static final String ALIAS_SEP = "/"; private static final boolean NSS_TEST = false; private static final Debug debug = Debug.getInstance("pkcs11keystore"); private static boolean CKA_TRUSTED_SUPPORTED = true; private final Token token; // If multiple certs are found to share the same CKA_LABEL // at load time (NSS-style keystore), then the keystore is read // and the unique keystore aliases are mapped to the entries. // However, write capabilities are disabled. private boolean writeDisabled = false; // Map of unique keystore aliases to entries in the token private HashMap<String, AliasInfo> aliasMap; // whether to use NSS Secmod info for trust attributes private final boolean useSecmodTrust; // if useSecmodTrust == true, which type of trust we are interested in private Secmod.TrustType nssTrustType; /** * The underlying token may contain multiple certs belonging to the * same "personality" (for example, a signing cert and encryption cert), * all sharing the same CKA_LABEL. These must be resolved * into unique keystore aliases. * * In addition, private keys and certs may not have a CKA_LABEL. * It is assumed that a private key and corresponding certificate * share the same CKA_ID, and that the CKA_ID is unique across the token. * The CKA_ID may not be human-readable. * These pairs must be resolved into unique keystore aliases. * * Furthermore, secret keys are assumed to have a CKA_LABEL * unique across the entire token. * * When the KeyStore is loaded, instances of this class are * created to represent the private keys/secret keys/certs * that reside on the token. */ private static class AliasInfo { // CKA_CLASS - entry type private CK_ATTRIBUTE type = null; // CKA_LABEL of cert and secret key private String label = null; // CKA_ID of the private key/cert pair private byte[] id = null; // CKA_TRUSTED - true if cert is trusted private boolean trusted = false; // either end-entity cert or trusted cert depending on 'type' private X509Certificate cert = null; // chain private X509Certificate chain[] = null; // true if CKA_ID for private key and cert match up private boolean matched = false; // SecretKeyEntry public AliasInfo(String label) { this.type = ATTR_CLASS_SKEY; this.label = label; } // PrivateKeyEntry public AliasInfo(String label, byte[] id, boolean trusted, X509Certificate cert) { this.type = ATTR_CLASS_PKEY; this.label = label; this.id = id; this.trusted = trusted; this.cert = cert; } public String toString() { StringBuilder sb = new StringBuilder(); if (type == ATTR_CLASS_PKEY) { sb.append("\ttype=[private key]\n"); } else if (type == ATTR_CLASS_SKEY) { sb.append("\ttype=[secret key]\n"); } else if (type == ATTR_CLASS_CERT) { sb.append("\ttype=[trusted cert]\n"); } sb.append("\tlabel=[" + label + "]\n"); if (id == null) { sb.append("\tid=[null]\n"); } else { sb.append("\tid=" + P11KeyStore.getID(id) + "\n"); } sb.append("\ttrusted=[" + trusted + "]\n"); sb.append("\tmatched=[" + matched + "]\n"); if (cert == null) { sb.append("\tcert=[null]\n"); } else { sb.append("\tcert=[\tsubject: " + cert.getSubjectX500Principal() + "\n\t\tissuer: " + cert.getIssuerX500Principal() + "\n\t\tserialNum: " + cert.getSerialNumber().toString() + "]"); } return sb.toString(); } } /** * callback handler for passing password to Provider.login method */ private static class PasswordCallbackHandler implements CallbackHandler { private char[] password; private PasswordCallbackHandler(char[] password) { if (password != null) { this.password = (char[])password.clone(); } } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { if (!(callbacks[0] instanceof PasswordCallback)) { throw new UnsupportedCallbackException(callbacks[0]); } PasswordCallback pc = (PasswordCallback)callbacks[0]; pc.setPassword(password); // this clones the password if not null } protected void finalize() throws Throwable { if (password != null) { Arrays.fill(password, ' '); } super.finalize(); } } /** * getTokenObject return value. * * if object is not found, type is set to null. * otherwise, type is set to the requested type. */ private static class THandle { private final long handle; // token object handle private final CK_ATTRIBUTE type; // CKA_CLASS private THandle(long handle, CK_ATTRIBUTE type) { this.handle = handle; this.type = type; } } P11KeyStore(Token token) { this.token = token; this.useSecmodTrust = token.provider.nssUseSecmodTrust; } /** * Returns the key associated with the given alias. * The key must have been associated with * the alias by a call to <code>setKeyEntry</code>, * or by a call to <code>setEntry</code> with a * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>. * * @param alias the alias name * @param password the password, which must be <code>null</code> * * @return the requested key, or null if the given alias does not exist * or does not identify a key-related entry. * * @exception NoSuchAlgorithmException if the algorithm for recovering the * key cannot be found * @exception UnrecoverableKeyException if the key cannot be recovered */ public synchronized Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { token.ensureValid(); if (password != null && !token.config.getKeyStoreCompatibilityMode()) { throw new NoSuchAlgorithmException("password must be null"); } AliasInfo aliasInfo = aliasMap.get(alias); if (aliasInfo == null || aliasInfo.type == ATTR_CLASS_CERT) { return null; } Session session = null; try { session = token.getOpSession(); if (aliasInfo.type == ATTR_CLASS_PKEY) { THandle h = getTokenObject(session, aliasInfo.type, aliasInfo.id, null); if (h.type == ATTR_CLASS_PKEY) { return loadPkey(session, h.handle); } } else { THandle h = getTokenObject(session, ATTR_CLASS_SKEY, null, alias); if (h.type == ATTR_CLASS_SKEY) { return loadSkey(session, h.handle); } } // did not find anything return null; } catch (PKCS11Exception pe) { throw new ProviderException(pe); } catch (KeyStoreException ke) { throw new ProviderException(ke); } finally { token.releaseSession(session); } } /** * Returns the certificate chain associated with the given alias. * The certificate chain must have been associated with the alias * by a call to <code>setKeyEntry</code>, * or by a call to <code>setEntry</code> with a * <code>PrivateKeyEntry</code>. * * @param alias the alias name * * @return the certificate chain (ordered with the user's certificate first * and the root certificate authority last), or null if the given alias * does not exist or does not contain a certificate chain */ public synchronized Certificate[] engineGetCertificateChain(String alias) { token.ensureValid(); AliasInfo aliasInfo = aliasMap.get(alias); if (aliasInfo == null || aliasInfo.type != ATTR_CLASS_PKEY) { return null; } return aliasInfo.chain; } /** * Returns the certificate associated with the given alias. * * <p> If the given alias name identifies an entry * created by a call to <code>setCertificateEntry</code>, * or created by a call to <code>setEntry</code> with a * <code>TrustedCertificateEntry</code>, * then the trusted certificate contained in that entry is returned. * * <p> If the given alias name identifies an entry * created by a call to <code>setKeyEntry</code>, * or created by a call to <code>setEntry</code> with a * <code>PrivateKeyEntry</code>, * then the first element of the certificate chain in that entry * (if a chain exists) is returned. * * @param alias the alias name * * @return the certificate, or null if the given alias does not exist or * does not contain a certificate. */ public synchronized Certificate engineGetCertificate(String alias) { token.ensureValid(); AliasInfo aliasInfo = aliasMap.get(alias); if (aliasInfo == null) { return null; } return aliasInfo.cert; } /** * Returns the creation date of the entry identified by the given alias. * * @param alias the alias name * * @return the creation date of this entry, or null if the given alias does * not exist */ public Date engineGetCreationDate(String alias) { token.ensureValid(); throw new ProviderException(new UnsupportedOperationException()); } /** * Assigns the given key to the given alias, protecting it with the given * password. * * <p>If the given key is of type <code>java.security.PrivateKey</code>, * it must be accompanied by a certificate chain certifying the * corresponding public key. * * <p>If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key to be associated with the alias * @param password the password to protect the key * @param chain the certificate chain for the corresponding public * key (only required if the given key is of type * <code>java.security.PrivateKey</code>). * * @exception KeyStoreException if the given key cannot be protected, or * this operation fails for some other reason */ public synchronized void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { token.ensureValid(); checkWrite(); if (!(key instanceof PrivateKey) && !(key instanceof SecretKey)) { throw new KeyStoreException("key must be PrivateKey or SecretKey"); } else if (key instanceof PrivateKey && chain == null) { throw new KeyStoreException ("PrivateKey must be accompanied by non-null chain"); } else if (key instanceof SecretKey && chain != null) { throw new KeyStoreException ("SecretKey must be accompanied by null chain"); } else if (password != null && !token.config.getKeyStoreCompatibilityMode()) { throw new KeyStoreException("Password must be null"); } KeyStore.Entry entry = null; try { if (key instanceof PrivateKey) { entry = new KeyStore.PrivateKeyEntry((PrivateKey)key, chain); } else if (key instanceof SecretKey) { entry = new KeyStore.SecretKeyEntry((SecretKey)key); } } catch (NullPointerException npe) { throw new KeyStoreException(npe); } catch (IllegalArgumentException iae) { throw new KeyStoreException(iae); } engineSetEntry(alias, entry, new KeyStore.PasswordProtection(password)); } /** * Assigns the given key (that has already been protected) to the given * alias. * * <p>If the protected key is of type * <code>java.security.PrivateKey</code>, * it must be accompanied by a certificate chain certifying the * corresponding public key. * * <p>If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key (in protected format) to be associated with the alias * @param chain the certificate chain for the corresponding public * key (only useful if the protected key is of type * <code>java.security.PrivateKey</code>). * * @exception KeyStoreException if this operation fails. */ public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { token.ensureValid(); throw new ProviderException(new UnsupportedOperationException()); } /** * Assigns the given certificate to the given alias. * * <p> If the given alias identifies an existing entry * created by a call to <code>setCertificateEntry</code>,