/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
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
new CK_ATTRIBUTE(CKA_TRUSTED, true);
new CK_ATTRIBUTE(CKA_PRIVATE, true);
private static final boolean NSS_TEST = false;
private static boolean CKA_TRUSTED_SUPPORTED = true;
// 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
// whether to use NSS Secmod info for trust attributes
private final boolean useSecmodTrust;
// if useSecmodTrust == true, which type of trust we are interested in
/**
* 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
* that reside on the token.
*/
private static class AliasInfo {
// CKA_CLASS - entry type
// CKA_LABEL of cert and secret key
// CKA_TRUSTED - true if cert is trusted
private boolean trusted = false;
// either end-entity cert or trusted cert depending on 'type'
// chain
// true if CKA_ID for private key and cert match up
private boolean matched = false;
// SecretKeyEntry
this.type = ATTR_CLASS_SKEY;
}
// PrivateKeyEntry
byte[] id,
boolean trusted,
this.type = ATTR_CLASS_PKEY;
}
if (type == ATTR_CLASS_PKEY) {
} else if (type == ATTR_CLASS_SKEY) {
} else if (type == ATTR_CLASS_CERT) {
}
} else {
}
} else {
"\n\t\tissuer: " +
"\n\t\tserialNum: " +
"]");
}
}
}
/**
* callback handler for passing password to Provider.login method
*/
private char[] password;
}
}
throws IOException, UnsupportedCallbackException {
}
}
}
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 {
}
}
}
/**
* 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
*/
token.ensureValid();
throw new NoSuchAlgorithmException("password must be null");
}
return null;
}
try {
null);
if (h.type == ATTR_CLASS_PKEY) {
}
} else {
null,
alias);
if (h.type == ATTR_CLASS_SKEY) {
}
}
// did not find anything
return null;
} catch (PKCS11Exception pe) {
throw new ProviderException(pe);
} catch (KeyStoreException ke) {
throw new ProviderException(ke);
} finally {
}
}
/**
* 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
*/
token.ensureValid();
return null;
}
}
/**
* 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.
*/
token.ensureValid();
return null;
}
}
/**
* 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
*/
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
*/
char[] password,
Certificate[] chain)
throws KeyStoreException {
token.ensureValid();
checkWrite();
throw new KeyStoreException("key must be PrivateKey or SecretKey");
throw new KeyStoreException
("PrivateKey must be accompanied by non-null chain");
throw new KeyStoreException
("SecretKey must be accompanied by null chain");
throw new KeyStoreException("Password must be null");
}
try {
if (key instanceof PrivateKey) {
}
} catch (NullPointerException npe) {
throw new KeyStoreException(npe);
} catch (IllegalArgumentException iae) {
throw new KeyStoreException(iae);
}
}
/**
* 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.
*/
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>,
* or created by a call to <code>setEntry</code> with a
* <code>TrustedCertificateEntry</code>,
* the trusted certificate in the existing entry
* is overridden by the given certificate.
*
* @param alias the alias name
* @param cert the certificate
*
* @exception KeyStoreException if the given alias already exists and does
* not identify an entry containing a trusted certificate,
* or this operation fails for some other reason.
*/
public synchronized void engineSetCertificateEntry
token.ensureValid();
checkWrite();
throw new KeyStoreException("invalid null certificate");
}
}
/**
* Deletes the entry identified by the given alias from this keystore.
*
* @param alias the alias name
*
* @exception KeyStoreException if the entry cannot be removed.
*/
throws KeyStoreException {
token.ensureValid();
if (token.isWriteProtected()) {
throw new KeyStoreException("token write-protected");
}
checkWrite();
}
/**
* XXX - not sure whether to keep this
*/
try {
// trusted certificate entry
// private key entry
// secret key entry
return destroySkey(alias);
} else {
throw new KeyStoreException("unexpected entry type");
}
} catch (PKCS11Exception pe) {
throw new KeyStoreException(pe);
} catch (CertificateException ce) {
throw new KeyStoreException(ce);
}
}
return false;
}
/**
* Lists all the alias names of this keystore.
*
* @return enumeration of the alias names
*/
token.ensureValid();
// don't want returned enumeration to iterate off actual keySet -
// otherwise applications that iterate and modify the keystore
// may run into concurrent modification problems
}
/**
* Checks if the given alias exists in this keystore.
*
* @param alias the alias name
*
* @return true if the alias exists, false otherwise
*/
token.ensureValid();
}
/**
* Retrieves the number of entries in this keystore.
*
* @return the number of entries in this keystore
*/
public synchronized int engineSize() {
token.ensureValid();
}
/**
* Returns true if the entry identified by the given alias
* was created by a call to <code>setKeyEntry</code>,
* or created by a call to <code>setEntry</code> with a
* <code>PrivateKeyEntry</code> or a <code>SecretKeyEntry</code>.
*
* @param alias the alias for the keystore entry to be checked
*
* @return true if the entry identified by the given alias is a
* key-related, false otherwise.
*/
token.ensureValid();
return false;
}
return true;
}
/**
* Returns true if the entry identified by the given alias
* was created by a call to <code>setCertificateEntry</code>,
* or created by a call to <code>setEntry</code> with a
* <code>TrustedCertificateEntry</code>.
*
* @param alias the alias for the keystore entry to be checked
*
* @return true if the entry identified by the given alias contains a
* trusted certificate, false otherwise.
*/
token.ensureValid();
return false;
}
return true;
}
/**
* Returns the (alias) name of the first keystore entry whose certificate
* matches the given certificate.
*
* <p>This method attempts to match the given certificate with each
* keystore entry. If the entry being considered was
* created by a call to <code>setCertificateEntry</code>,
* or created by a call to <code>setEntry</code> with a
* <code>TrustedCertificateEntry</code>,
* then the given certificate is compared to that entry's certificate.
*
* <p> If the entry being considered was
* created by a call to <code>setKeyEntry</code>,
* or created by a call to <code>setEntry</code> with a
* <code>PrivateKeyEntry</code>,
* then the given certificate is compared to the first
* element of that entry's certificate chain.
*
* @param cert the certificate to match with.
*
* @return the alias name of the first entry with matching certificate,
* or null if no such entry exists in this keystore.
*/
token.ensureValid();
while (e.hasMoreElements()) {
return alias;
}
}
return null;
}
/**
* engineStore currently is a No-op.
* Entries are stored to the token during engineSetEntry
*
* @param stream this must be <code>null</code>
* @param password this must be <code>null</code>
*/
token.ensureValid();
throw new IOException("output stream must be null");
}
throw new IOException("password must be null");
}
}
/**
* engineStore currently is a No-op.
* Entries are stored to the token during engineSetEntry
*
* @param param this must be <code>null</code>
*
* @exception IllegalArgumentException if the given
* <code>KeyStore.LoadStoreParameter</code>
* input is not <code>null</code>
*/
token.ensureValid();
throw new IllegalArgumentException
("LoadStoreParameter must be null");
}
}
/**
* Loads the keystore.
*
* @param stream the input stream, which must be <code>null</code>
* @param password the password used to unlock the keystore,
* or <code>null</code> if the token supports a
* CKF_PROTECTED_AUTHENTICATION_PATH
*
* @exception IOException if the given <code>stream</code> is not
* <code>null</code>, if the token supports a
* CKF_PROTECTED_AUTHENTICATION_PATH and a non-null
* password is given, of if the token login operation failed
*/
token.ensureValid();
if (NSS_TEST) {
}
throw new IOException("input stream must be null");
}
if (useSecmodTrust) {
}
try {
} else {
}
if (mapLabels() == true) {
// CKA_LABELs are shared by multiple certs
writeDisabled = true;
}
dumpTokenMap();
}
} catch (LoginException le) {
throw ioe;
} catch (KeyStoreException kse) {
throw ioe;
} catch (PKCS11Exception pe) {
throw ioe;
}
}
/**
* Loads the keystore using the given
* <code>KeyStore.LoadStoreParameter</code>.
*
* <p> The <code>LoadStoreParameter.getProtectionParameter()</code>
* method is expected to return a <code>KeyStore.PasswordProtection</code>
* object. The password is retrieved from that object and used
* to unlock the PKCS#11 token.
*
* <p> If the token supports a CKF_PROTECTED_AUTHENTICATION_PATH
* then the provided password must be <code>null</code>.
*
* @param param the <code>KeyStore.LoadStoreParameter</code>
*
* @exception IllegalArgumentException if the given
* <code>KeyStore.LoadStoreParameter</code> is <code>null</code>,
* or if that parameter returns a <code>null</code>
* <code>ProtectionParameter</code> object.
* input is not recognized
* @exception IOException if the token supports a
* CKF_PROTECTED_AUTHENTICATION_PATH and the provided password
* is non-null, or if the token login operation fails
*/
throws IOException, NoSuchAlgorithmException,
token.ensureValid();
if (NSS_TEST) {
}
// if caller wants to pass a NULL password,
// force it to pass a non-NULL PasswordProtection that returns
// a NULL password
throw new IllegalArgumentException
("invalid null LoadStoreParameter");
}
if (useSecmodTrust) {
} else {
}
}
if (pp instanceof PasswordProtection) {
} else {
}
} else if (pp instanceof CallbackHandlerProtection) {
} else {
throw new IllegalArgumentException
("ProtectionParameter must be either " +
"PasswordProtection or CallbackHandlerProtection");
}
try {
if (mapLabels() == true) {
// CKA_LABELs are shared by multiple certs
writeDisabled = true;
}
dumpTokenMap();
}
} catch (LoginException e) {
throw new IOException("load failed", e);
} catch (KeyStoreException e) {
throw new IOException("load failed", e);
} catch (PKCS11Exception e) {
throw new IOException("load failed", e);
}
}
} else {
// token supports protected authentication path
// (external pin-pad, for example)
throw new LoginException("can not specify password if token " +
"supports protected authentication path");
}
// must rely on application-set or default handler
// if one is necessary
}
}
/**
* Get a <code>KeyStore.Entry</code> for the specified alias
*
* @param alias get the <code>KeyStore.Entry</code> for this alias
* @param protParam this must be <code>null</code>
*
* @return the <code>KeyStore.Entry</code> for the specified alias,
* or <code>null</code> if there is no such entry
*
* @exception KeyStoreException if the operation failed
* @exception NoSuchAlgorithmException if the algorithm for recovering the
* entry cannot be found
* @exception UnrecoverableEntryException if the specified
* <code>protParam</code> were insufficient or invalid
*
* @since 1.5
*/
token.ensureValid();
throw new KeyStoreException("ProtectionParameter must be null");
}
alias +
"] in map");
}
return null;
}
try {
// trusted certificate entry
}
// secret key entry
}
if (h.type != ATTR_CLASS_SKEY) {
throw new KeyStoreException
("expected but could not find secret key");
} else {
}
} else {
// private key entry
}
if (h.type != ATTR_CLASS_PKEY) {
throw new KeyStoreException
("expected but could not find private key");
} else {
} else {
("engineGetEntry got null cert chain or private key");
}
}
}
}
return null;
} catch (PKCS11Exception pe) {
throw new KeyStoreException(pe);
} finally {
}
}
/**
* Save a <code>KeyStore.Entry</code> under the specified alias.
*
* <p> If an entry already exists for the specified alias,
* it is overridden.
*
* <p> This KeyStore implementation only supports the standard
* entry types, and only supports X509Certificates in
* TrustedCertificateEntries. Also, this implementation does not support
* protecting entries using a different password
* from the one used for token login.
*
* <p> Entries are immediately stored on the token.
*
* @param alias save the <code>KeyStore.Entry</code> under this alias
* @param entry the <code>Entry</code> to save
* @param protParam this must be <code>null</code>
*
* @exception KeyStoreException if this operation fails
*
* @since 1.5
*/
throws KeyStoreException {
token.ensureValid();
checkWrite();
throw new KeyStoreException(new UnsupportedOperationException
("ProtectionParameter must be null"));
}
if (token.isWriteProtected()) {
throw new KeyStoreException("token write-protected");
}
if (useSecmodTrust == false) {
// PKCS #11 does not allow app to modify trusted certs -
throw new KeyStoreException(new UnsupportedOperationException
("trusted certificates may only be set by " +
"token initialization application"));
}
// XXX allow TRUSTANCHOR module
throw new KeyStoreException("Trusted certificates can only be "
+ "added to the NSS KeyStore module");
}
if (cert instanceof X509Certificate == false) {
throw new KeyStoreException("Certificate must be an X509Certificate");
}
// XXX try to update
}
try {
mapLabels();
} catch (PKCS11Exception e) {
throw new KeyStoreException(e);
} catch (CertificateException e) {
throw new KeyStoreException(e);
}
} else {
!(key instanceof RSAPrivateKey) &&
!(key instanceof DSAPrivateKey) &&
!(key instanceof DHPrivateKey) &&
!(key instanceof ECPrivateKey)) {
throw new KeyStoreException("unsupported key type: " +
}
// only support X509Certificate chains
Certificate[] chain =
if (!(chain instanceof X509Certificate[])) {
throw new KeyStoreException
("unsupported certificate array type: " +
}
try {
boolean updatedAlias = false;
// see if there's an existing entry with the same info
// found existing entry -
// caller is renaming entry or updating cert chain
//
// and update certs if necessary
(X509Certificate[])chain,
updatedAlias = true;
break;
}
}
if (!updatedAlias) {
// caller adding new entry
}
} catch (PKCS11Exception pe) {
throw new KeyStoreException(pe);
} catch (CertificateException ce) {
throw new KeyStoreException(ce);
}
try {
// first check if the key already exists
}
} catch (PKCS11Exception pe) {
throw new KeyStoreException(pe);
}
} else {
throw new KeyStoreException(new UnsupportedOperationException
}
try {
// XXX NSS does not write out the CKA_ID we pass to them
//
// therefore we must re-map labels
// (can not simply update aliasMap)
mapLabels();
dumpTokenMap();
}
} catch (PKCS11Exception pe) {
throw new KeyStoreException(pe);
} catch (CertificateException ce) {
throw new KeyStoreException(ce);
}
}
("engineSetEntry added new entry for [" +
alias +
"] to token");
}
}
/**
* Determines if the keystore <code>Entry</code> for the specified
* <code>alias</code> is an instance or subclass of the specified
* <code>entryClass</code>.
*
* @param alias the alias name
* @param entryClass the entry class
*
* @return true if the keystore <code>Entry</code> for the specified
* <code>alias</code> is an instance or subclass of the
* specified <code>entryClass</code>, false otherwise
*/
public synchronized boolean engineEntryInstanceOf
token.ensureValid();
}
throws PKCS11Exception, CertificateException {
{ new CK_ATTRIBUTE(CKA_VALUE) };
throw new CertificateException
("unexpectedly retrieved null byte array");
}
(new ByteArrayInputStream(bytes));
}
throws PKCS11Exception, CertificateException {
(endCert.getIssuerX500Principal())) {
// self signed
return new X509Certificate[] { endCert };
} else {
}
// try loading remaining certs in chain by following
// issuer->subject links
while (true) {
new CK_ATTRIBUTE(CKA_SUBJECT,
// done
break;
} else {
// if more than one found, use first
" certificate entries for subject [" +
"] in token - using first entry");
}
(next.getIssuerX500Principal())) {
// self signed
break;
}
}
}
}
throws PKCS11Exception {
new CK_ATTRIBUTE(CKA_KEY_TYPE) };
int keyLength = -1;
// XXX NSS mangles the stored key type for secret key token objects
keyType = "DES";
keyLength = 64;
keyType = "DESede";
keyLength = 192;
}
} else {
keyType = "AES";
} else if (kType == CKK_BLOWFISH) {
keyType = "Blowfish";
keyType = "ARCFOUR";
} else {
kType +
"] - using 'Generic Secret'");
}
keyType = "Generic Secret";
}
// XXX NSS problem CKR_ATTRIBUTE_TYPE_INVALID?
if (NSS_TEST) {
keyLength = 128;
} else {
}
}
}
throws PKCS11Exception, KeyStoreException {
new CK_ATTRIBUTE(CKA_KEY_TYPE) };
int keyLength = 0;
keyType = "RSA";
// This check will combine our "don't care" values here
try {
} catch (InvalidKeyException e) {
throw new KeyStoreException(e.getMessage());
}
null);
keyType = "DSA";
null);
keyType = "DH";
null);
attrs = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_EC_PARAMS),
};
try {
} catch (IOException e) {
// we do not want to accept key with unsupported parameters
throw new KeyStoreException("Unsupported parameters", e);
}
} else {
}
throw new KeyStoreException("unknown key type");
}
}
/**
* XXX On ibutton, when you C_SetAttribute(CKA_ID) for a private key
* it not only changes the CKA_ID of the private key,
* it changes the CKA_ID of the corresponding cert too.
* And vice versa.
*
* XXX On ibutton, CKR_DEVICE_ERROR if you C_SetAttribute(CKA_ID)
* for a private key, and then try to delete the corresponding cert.
* So this code reverses the order.
* After the cert is first destroyed (if necessary),
* then the CKA_ID of the private key can be changed successfully.
*
* @param replaceCert if true, then caller is updating alias info for
* if false, then caller is updating cert chain
* (delete old end cert and add new chain).
*/
byte[] cka_id,
boolean replaceCert) throws
// XXX
//
// always set replaceCert to true
//
// NSS does not allow resetting of CKA_LABEL on an existing cert
// (C_SetAttribute call succeeds, but is ignored)
replaceCert = true;
try {
// first get private key object handle and hang onto it
long pKeyHandle;
if (h.type == ATTR_CLASS_PKEY) {
pKeyHandle = h.handle;
} else {
throw new KeyStoreException
("expected but could not find private key " +
"with CKA_ID " +
}
// next find existing end entity cert
if (h.type != ATTR_CLASS_CERT) {
throw new KeyStoreException
("expected but could not find certificate " +
"with CKA_ID " +
} else {
if (replaceCert) {
// replacing existing cert and chain
} else {
// renaming alias for existing cert
}
}
// add new chain
if (replaceCert) {
// add all certs in chain
} else {
// already updated alias info for existing end cert -
// just update CA certs
}
// finally update CKA_ID for private key
//
// ibutton may have already done this (that is ok)
alias +
"] for private key entry");
}
} finally {
}
}
throws PKCS11Exception {
// if token key, update alias.
// if session key, convert to token key.
try {
if (key.tokenObject == true) {
// token key - set new CKA_ID
alias +
"] for key entry");
}
} else {
// session key - convert to token key and set CKA_ID
};
}
"for [" +
alias +
"] to token entry");
}
}
} finally {
}
}
throws PKCS11Exception, CertificateException {
} else {
// ibutton requires something to be set
// - alias must be unique
}
try {
} finally {
}
}
throws PKCS11Exception, CertificateException {
// add new chain
//
// end cert has CKA_LABEL and CKA_ID set to alias.
// other certs in chain have neither set.
}
throws PKCS11Exception, CertificateException {
// do not add duplicate CA cert if already in token
//
// XXX ibutton stores duplicate CA certs, NSS does not
try {
// load certs currently on the token
}
} finally {
}
chain[i].getSubjectX500Principal() +
"]");
}
}
}
throws PKCS11Exception, KeyStoreException {
// No need to specify CKA_CLASS, CKA_KEY_TYPE, CKA_VALUE since
// they are handled in P11SecretKeyFactory.createKey() method.
};
try {
} catch (InvalidKeyException ike) {
// re-throw KeyStoreException to match javadoc
}
// update global alias map
alias + "]");
}
}
return newAttrs;
}
// If the key is a token object on this token, update it instead
// of creating a duplicate key object.
// Otherwise, treat a P11Key like any other key, if is is extractable.
return;
}
}
if (key instanceof RSAPrivateKey) {
} else if (key instanceof DSAPrivateKey) {
}
attrs = new CK_ATTRIBUTE[] {
idAttrs[0],
};
}
}
} else if (key instanceof DHPrivateKey) {
}
attrs = new CK_ATTRIBUTE[] {
idAttrs[0],
};
}
} else if (key instanceof ECPrivateKey) {
}
attrs = new CK_ATTRIBUTE[] {
idAttrs[0],
};
}
}
// sensitive/non-extractable P11Key
throw new KeyStoreException
("Cannot move sensitive keys across tokens");
}
if (useNDB) {
// Note that this currently fails due to an NSS bug.
// They do not allow the CKA_NETSCAPE_DB attribute to be
// specified during C_CopyObject() and fail with
// CKR_ATTRIBUTE_READ_ONLY.
// But if we did not specify it, they would fail with
// CKA_TEMPLATE_INCOMPLETE, so leave this code in here.
}
// Update the key object.
return;
} else {
}
try {
// create private key entry
alias +
"]");
}
} finally {
}
}
// subject is currently ignored - could be used to set CKA_SUBJECT
if (key instanceof RSAPrivateCrtKey) {
}
attrs = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_MODULUS,
rsaKey.getModulus()),
new CK_ATTRIBUTE(CKA_PRIME_1,
new CK_ATTRIBUTE(CKA_PRIME_2,
rsaKey.getCrtCoefficient()) };
} else {
}
attrs = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_MODULUS,
rsaKey.getModulus()),
rsaKey.getPrivateExponent()) };
}
return attrs;
}
/**
* used for this private key. It uses the same algorithm to calculate the
* values as NSS. The public and private keys MUST match for the result to
* be correct.
*
* It returns a 2 element array with CKA_ID at index 0 and CKA_NETSCAPE_DB
* at index 1. The boolean flags determine what is to be calculated.
* If false or if we could not calculate the value, that element is null.
*
* NOTE that we currently do not use the CKA_ID value calculated by this
* method.
*/
if ((id || netscapeDb) == false) {
return attrs;
}
// CKA_NETSCAPE_DB not needed for RSA public keys
if (id) {
}
if (netscapeDb) {
}
if (id) {
}
if (netscapeDb) {
}
if (id) {
}
if (netscapeDb) {
}
} else {
}
return attrs;
}
/**
* return true if cert destroyed
*/
throws PKCS11Exception, KeyStoreException {
try {
if (h.type != ATTR_CLASS_CERT) {
return false;
}
"]");
}
return true;
} finally {
}
}
/**
* return true if chain destroyed
*/
try {
if (h.type != ATTR_CLASS_CERT) {
"end entity cert with CKA_ID [0x" +
"]");
}
return false;
}
"with CKA_ID [" +
"]");
}
// build chain following issuer->subject links
while (true) {
(next.getIssuerX500Principal())) {
// self signed - done
break;
}
new CK_ATTRIBUTE(CKA_SUBJECT,
// done
break;
} else {
// if more than one found, use first
" certificate entries for subject [" +
"] in token - using first entry");
}
// only delete if not part of any other chain
attrs = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_ISSUER,
boolean destroyIt = false;
// no other certs with this issuer -
// destroy it
destroyIt = true;
// only cert with issuer is itself (self-signed) -
// destroy it
destroyIt = true;
}
}
if (destroyIt) {
("destroyChain destroyed cert in chain " +
"with subject [" +
}
} else {
"shared cert in chain with subject [" +
}
}
}
}
return true;
} finally {
}
}
/**
* return true if secret key destroyed
*/
throws PKCS11Exception, KeyStoreException {
try {
if (h.type != ATTR_CLASS_SKEY) {
"with CKA_LABEL [" +
alias +
"]");
}
return false;
}
return true;
} finally {
}
}
/**
* return true if private key destroyed
*/
throws PKCS11Exception, KeyStoreException {
try {
if (h.type != ATTR_CLASS_PKEY) {
("destroyPkey did not find private key with CKA_ID [" +
"]");
}
return false;
}
return true;
} finally {
}
}
/**
* build [alias + issuer + serialNumber] string from a cert
*/
return alias +
}
/**
* build CKA_ID string from bytes
*/
boolean printable = true;
printable = false;
break;
}
}
if (!printable) {
} else {
try {
} catch (UnsupportedEncodingException uee) {
}
}
}
/**
* find an object on the token
*
* @param type either ATTR_CLASS_CERT, ATTR_CLASS_PKEY, or ATTR_CLASS_SKEY
* @param cka_id the CKA_ID if type is ATTR_CLASS_CERT or ATTR_CLASS_PKEY
* @param cka_label the CKA_LABEL if type is ATTR_CLASS_SKEY
*/
byte[] cka_id,
throws PKCS11Exception, KeyStoreException {
if (type == ATTR_CLASS_SKEY) {
attrs = new CK_ATTRIBUTE[] {
type };
} else {
attrs = new CK_ATTRIBUTE[] {
type };
}
if (h.length == 0) {
if (type == ATTR_CLASS_SKEY) {
"with CKA_LABEL [" +
"]");
} else if (type == ATTR_CLASS_CERT) {
("getTokenObject did not find cert with CKA_ID [" +
"]");
} else {
"with CKA_ID [" +
"]");
}
}
} else if (h.length == 1) {
// found object handle - return it
} else {
// found multiple object handles -
// see if token ignored CKA_LABEL during search (e.g. NSS)
if (type == ATTR_CLASS_SKEY) {
for (int i = 0; i < h.length; i++) {
{ new CK_ATTRIBUTE(CKA_LABEL) };
}
}
// yes, there was only one CKA_LABEL that matched
} else {
throw new KeyStoreException("invalid KeyStore state: " +
"found " +
" secret keys sharing CKA_LABEL [" +
"]");
}
} else if (type == ATTR_CLASS_CERT) {
throw new KeyStoreException("invalid KeyStore state: " +
"found " +
h.length +
" certificates sharing CKA_ID " +
} else {
throw new KeyStoreException("invalid KeyStore state: " +
"found " +
h.length +
" private keys sharing CKA_ID " +
}
}
}
/**
* Create a mapping of all key pairs, trusted certs, and secret keys
* on the token into logical KeyStore entries unambiguously
* accessible via an alias.
*
* If the token is removed, the map may contain stale values.
* KeyStore.load should be called to re-create the map.
*
* Assume all private keys and matching certs share a unique CKA_ID.
*
* Assume all secret keys have a unique CKA_LABEL.
*
* @return true if multiple certs found sharing the same CKA_LABEL
* (if so, write capabilities are disabled)
*/
private boolean mapLabels() throws
new CK_ATTRIBUTE(CKA_TRUSTED) };
try {
// get all private key CKA_IDs
};
}
}
// Get all certificates
//
// If cert does not have a CKA_LABEL nor CKA_ID, it is ignored.
//
// Get the CKA_LABEL for each cert
// (if the cert does not have a CKA_LABEL, use the CKA_ID).
//
// Map each cert to the its CKA_LABEL
// (multiple certs may be mapped to a single CKA_LABEL)
attrs = new CK_ATTRIBUTE[] {
};
try {
// there is a CKA_LABEL
}
} catch (PKCS11Exception pe) {
throw pe;
}
// GetAttributeValue for CKA_LABEL not supported
//
// XXX SCA1000
}
// get CKA_ID
// no cka_label nor cka_id - ignore
continue;
}
} else {
// use CKA_ID as CKA_LABEL
}
}
// get CKA_TRUSTED
boolean cka_trusted = false;
if (useSecmodTrust) {
} else {
if (CKA_TRUSTED_SUPPORTED) {
try {
} catch (PKCS11Exception pe) {
// XXX NSS, ibutton, sca1000
CKA_TRUSTED_SUPPORTED = false;
("CKA_TRUSTED attribute not supported");
}
}
}
}
}
}
// initially create private key entry AliasInfo entries -
// these entries will get resolved into their true
// entry types later
cert));
}
// create list secret key CKA_LABELS -
// if there are duplicates (either between secret keys,
// or between a secret key and another object),
// throw an exception
attrs = new CK_ATTRIBUTE[] {
};
// there is a CKA_LABEL
} else {
throw new KeyStoreException("invalid KeyStore state: " +
"found multiple secret keys sharing same " +
"CKA_LABEL [" +
"]");
}
}
}
// update global aliasMap with alias mappings
return sharedLabel;
} finally {
}
}
/**
* for each private key CKA_ID, find corresponding cert with same CKA_ID.
* if found cert, see if cert CKA_LABEL is unique.
* CKA_LABEL + ALIAS_SEP + ISSUER + ALIAS_SEP + SERIAL
* if cert not found, ignore private key
* (don't support private key entries without a cert chain yet)
*
* @return a list of AliasInfo entries that represents all matches
*/
throws PKCS11Exception, CertificateException {
// reset global alias map
// list of matched certs that we will return
// try to find a matching CKA_ID in a certificate
boolean foundMatch = false;
// get cert CKA_IDs (if present) for each cert
// found private key with matching cert
// unique CKA_LABEL - use certLabel as alias
} else {
// create new alias
}
foundMatch = true;
break;
}
}
if (foundMatch) {
break;
}
}
if (!foundMatch) {
("did not find match for private key with CKA_ID [" +
"] (ignoring entry)");
}
}
}
return matchedCerts;
}
/**
* for each cert not matched with a private key but is CKA_TRUSTED:
* if CKA_LABEL unique, map cert to CKA_LABEL.
* if CKA_LABEL not unique, map cert to [label+issuer+serialNum]
*
* if CKA_TRUSTED not supported, treat all certs not part of a chain
* as trusted
*
* @return true if multiple certs found sharing the same CKA_LABEL
*/
throws PKCS11Exception, CertificateException {
// load all cert chains
try {
} finally {
}
}
// find all certs in certMap not part of a cert chain
// - these are trusted
boolean sharedLabel = false;
// already found a private key match for this cert -
// just continue
continue;
}
// cert in this aliasInfo is not matched yet
//
// if CKA_TRUSTED_SUPPORTED == true,
// then check if cert is trusted
if (CKA_TRUSTED_SUPPORTED) {
// trusted certificate
if (mapTrustedCert
sharedLabel = true;
}
}
continue;
}
// CKA_TRUSTED_SUPPORTED == false
//
// XXX treat all certs not part of a chain as trusted
// XXX
// XXX Unsupported
//
// boolean partOfChain = false;
// for (AliasInfo matchedInfo : matchedCerts) {
// for (int i = 0; i < matchedInfo.chain.length; i++) {
// if (matchedInfo.chain[i].equals(aliasInfo.cert)) {
// partOfChain = true;
// break;
// }
// }
// if (partOfChain) {
// break;
// }
// }
//
// if (!partOfChain) {
// if (mapTrustedCert(certLabel,aliasInfo,infoSet) == true){
// sharedLabel = true;
// }
// } else {
// if (debug != null) {
// "that is part of cert chain - cert subject is [" +
// aliasInfo.cert.getSubjectX500Principal().getName
// (X500Principal.CANONICAL) +
// "]");
// }
// }
}
}
return sharedLabel;
}
boolean sharedLabel = false;
// unique CKA_LABEL - use certLabel as alias
} else {
// create new alias
sharedLabel = true;
}
return sharedLabel;
}
/**
* If the secret key shares a CKA_LABEL with another entry,
* throw an exception
*/
throws KeyStoreException {
throw new KeyStoreException("invalid KeyStore state: " +
"found secret key sharing CKA_LABEL [" +
label +
"] with another token object");
}
}
}
private void dumpTokenMap() {
} else {
}
}
}
if (writeDisabled) {
throw new KeyStoreException
("This PKCS11KeyStore does not support write capabilities");
}
}
throws PKCS11Exception {
while (true) {
if (h.length == 0) {
break;
}
}
return handles;
}
}