} catch (Exception e) { // XXX throw new ProviderException(e); } } synchronized void setTrust(Token token, X509Certificate cert) { Bytes bytes = new Bytes(getDigest(cert, "SHA-1")); TrustAttributes attr = getTrust(bytes); if (attr == null) { attr = new TrustAttributes(token, cert, bytes, CKT_NETSCAPE_TRUSTED_DELEGATOR); trust.put(bytes, attr); } else { // does it already have the correct trust settings? if (attr.isTrusted(TrustType.ALL) == false) { // XXX not yet implemented throw new ProviderException("Cannot change existing trust attributes"); } } } TrustAttributes getTrust(Bytes hash) { if (trust == null) { // If provider is not set, create a temporary provider to // retrieve the trust information. This can happen if we need // to get the trust information for the trustanchor module // because we need to look for user customized settings in the // keystore module (which may not have a provider created yet). // Creating a temporary provider and then dropping it on the // floor immediately is flawed, but it's the best we can do // for now. synchronized (this) { SunPKCS11 p = provider; if (p == null) { p = newProvider(); } try { trust = Secmod.getTrust(p); } catch (PKCS11Exception e) { throw new RuntimeException(e); } } } return trust.get(hash); } public String toString() { return commonName + " (" + type + ", " + libraryName + ", slot " + slot + ")"; } } /** * Constants representing NSS trust categories. */ public static enum TrustType { /** Trusted for all purposes */ ALL, /** Trusted for SSL client authentication */ CLIENT_AUTH, /** Trusted for SSL server authentication */ SERVER_AUTH, /** Trusted for code signing */ CODE_SIGNING, /** Trusted for email protection */ EMAIL_PROTECTION, } public static enum DbMode { READ_WRITE("NSS_InitReadWrite"), READ_ONLY ("NSS_Init"), NO_DB ("NSS_NoDB_Init"); final String functionName; DbMode(String functionName) { this.functionName = functionName; } } /** * A LoadStoreParameter for use with the NSS Softtoken or * NSS TrustAnchor KeyStores. * <p> * It allows the set of trusted certificates that are returned by * the KeyStore to be specified. */ public static final class KeyStoreLoadParameter implements LoadStoreParameter { final TrustType trustType; final ProtectionParameter protection; public KeyStoreLoadParameter(TrustType trustType, char[] password) { this(trustType, new PasswordProtection(password)); } public KeyStoreLoadParameter(TrustType trustType, ProtectionParameter prot) { if (trustType == null) { throw new NullPointerException("trustType must not be null"); } this.trustType = trustType; this.protection = prot; } public ProtectionParameter getProtectionParameter() { return protection; } public TrustType getTrustType() { return trustType; } } static class TrustAttributes { final long handle; final long clientAuth, serverAuth, codeSigning, emailProtection; final byte[] shaHash; TrustAttributes(Token token, X509Certificate cert, Bytes bytes, long trustValue) { Session session = null; try { session = token.getOpSession(); // XXX use KeyStore TrustType settings to determine which // attributes to set CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_TOKEN, true), new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH, trustValue), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING, trustValue), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION, trustValue), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH, trustValue), new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH, bytes.b), new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_MD5_HASH, getDigest(cert, "MD5")), new CK_ATTRIBUTE(CKA_ISSUER, cert.getIssuerX500Principal().getEncoded()), new CK_ATTRIBUTE(CKA_SERIAL_NUMBER, cert.getSerialNumber().toByteArray()), // XXX per PKCS#11 spec, the serial number should be in ASN.1 }; handle = token.p11.C_CreateObject(session.id(), attrs); shaHash = bytes.b; clientAuth = trustValue; serverAuth = trustValue; codeSigning = trustValue; emailProtection = trustValue; } catch (PKCS11Exception e) { throw new ProviderException("Could not create trust object", e); } finally { token.releaseSession(session); } } TrustAttributes(Token token, Session session, long handle) throws PKCS11Exception { this.handle = handle; CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION), new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH), }; token.p11.C_GetAttributeValue(session.id(), handle, attrs); serverAuth = attrs[0].getLong(); codeSigning = attrs[1].getLong(); emailProtection = attrs[2].getLong(); shaHash = attrs[3].getByteArray(); attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH), }; long c; try { token.p11.C_GetAttributeValue(session.id(), handle, attrs); c = attrs[0].getLong(); } catch (PKCS11Exception e) { // trust anchor module does not support this attribute c = serverAuth; } clientAuth = c; } Bytes getHash() { return new Bytes(shaHash); } boolean isTrusted(TrustType type) { switch (type) { case CLIENT_AUTH: return isTrusted(clientAuth); case SERVER_AUTH: return isTrusted(serverAuth); case CODE_SIGNING: return isTrusted(codeSigning); case EMAIL_PROTECTION: return isTrusted(emailProtection); case ALL: return isTrusted(TrustType.CLIENT_AUTH) && isTrusted(TrustType.SERVER_AUTH) && isTrusted(TrustType.CODE_SIGNING) && isTrusted(TrustType.EMAIL_PROTECTION); default: return false; } } private boolean isTrusted(long l) { // XXX CKT_TRUSTED? return (l == CKT_NETSCAPE_TRUSTED_DELEGATOR); } } private static class Bytes { final byte[] b; Bytes(byte[] b) { this.b = b; } public int hashCode() { return Arrays.hashCode(b); } public boolean equals(Object o) { if (this == o) { return true; } if (o instanceof Bytes == false) { return false; } Bytes other = (Bytes)o; return Arrays.equals(this.b, other.b); } } private static Map<Bytes,TrustAttributes> getTrust(SunPKCS11 provider) throws PKCS11Exception { Map<Bytes,TrustAttributes> trustMap = new HashMap<Bytes,TrustAttributes>(); Token token = provider.getToken(); Session session = null; try { session = token.getOpSession(); int MAX_NUM = 8192; CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST), }; token.p11.C_FindObjectsInit(session.id(), attrs); long[] handles = token.p11.C_FindObjects(session.id(), MAX_NUM); token.p11.C_FindObjectsFinal(session.id()); if (DEBUG) System.out.println("handles: " + handles.length); for (long handle : handles) { TrustAttributes trust = new TrustAttributes(token, session, handle); trustMap.put(trust.getHash(), trust); } } finally { token.releaseSession(session); } return trustMap; } private static native long nssGetLibraryHandle(String libraryName); private static native long nssLoadLibrary(String name) throws IOException; private static native boolean nssVersionCheck(long handle, String minVersion); private static native boolean nssInit(String functionName, long handle, String configDir); private static native Object nssGetModuleList(long handle, String libDir); }Lines 501–760 of 760. Previous lines
} catch (Exception e) { // XXX throw new ProviderException(e); } } synchronized void setTrust(Token token, X509Certificate cert) { Bytes bytes = new Bytes(getDigest(cert, "SHA-1")); TrustAttributes attr = getTrust(bytes); if (attr == null) { attr = new TrustAttributes(token, cert, bytes, CKT_NETSCAPE_TRUSTED_DELEGATOR); trust.put(bytes, attr); } else { // does it already have the correct trust settings? if (attr.isTrusted(TrustType.ALL) == false) { // XXX not yet implemented throw new ProviderException("Cannot change existing trust attributes"); } } } TrustAttributes getTrust(Bytes hash) { if (trust == null) { // If provider is not set, create a temporary provider to // retrieve the trust information. This can happen if we need // to get the trust information for the trustanchor module // because we need to look for user customized settings in the // keystore module (which may not have a provider created yet). // Creating a temporary provider and then dropping it on the // floor immediately is flawed, but it's the best we can do // for now. synchronized (this) { SunPKCS11 p = provider; if (p == null) { p = newProvider(); } try { trust = Secmod.getTrust(p); } catch (PKCS11Exception e) { throw new RuntimeException(e); } } } return trust.get(hash); } public String toString() { return commonName + " (" + type + ", " + libraryName + ", slot " + slot + ")"; } } /** * Constants representing NSS trust categories. */ public static enum TrustType { /** Trusted for all purposes */ ALL, /** Trusted for SSL client authentication */ CLIENT_AUTH, /** Trusted for SSL server authentication */ SERVER_AUTH, /** Trusted for code signing */ CODE_SIGNING, /** Trusted for email protection */ EMAIL_PROTECTION, } public static enum DbMode { READ_WRITE("NSS_InitReadWrite"), READ_ONLY ("NSS_Init"), NO_DB ("NSS_NoDB_Init"); final String functionName; DbMode(String functionName) { this.functionName = functionName; } } /** * A LoadStoreParameter for use with the NSS Softtoken or * NSS TrustAnchor KeyStores. * <p> * It allows the set of trusted certificates that are returned by * the KeyStore to be specified. */ public static final class KeyStoreLoadParameter implements LoadStoreParameter { final TrustType trustType; final ProtectionParameter protection; public KeyStoreLoadParameter(TrustType trustType, char[] password) { this(trustType, new PasswordProtection(password)); } public KeyStoreLoadParameter(TrustType trustType, ProtectionParameter prot) { if (trustType == null) { throw new NullPointerException("trustType must not be null"); } this.trustType = trustType; this.protection = prot; } public ProtectionParameter getProtectionParameter() { return protection; } public TrustType getTrustType() { return trustType; } } static class TrustAttributes { final long handle; final long clientAuth, serverAuth, codeSigning, emailProtection; final byte[] shaHash; TrustAttributes(Token token, X509Certificate cert, Bytes bytes, long trustValue) { Session session = null; try { session = token.getOpSession(); // XXX use KeyStore TrustType settings to determine which // attributes to set CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_TOKEN, true), new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH, trustValue), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING, trustValue), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION, trustValue), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH, trustValue), new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH, bytes.b), new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_MD5_HASH, getDigest(cert, "MD5")), new CK_ATTRIBUTE(CKA_ISSUER, cert.getIssuerX500Principal().getEncoded()), new CK_ATTRIBUTE(CKA_SERIAL_NUMBER, cert.getSerialNumber().toByteArray()), // XXX per PKCS#11 spec, the serial number should be in ASN.1 }; handle = token.p11.C_CreateObject(session.id(), attrs); shaHash = bytes.b; clientAuth = trustValue; serverAuth = trustValue; codeSigning = trustValue; emailProtection = trustValue; } catch (PKCS11Exception e) { throw new ProviderException("Could not create trust object", e); } finally { token.releaseSession(session); } } TrustAttributes(Token token, Session session, long handle) throws PKCS11Exception { this.handle = handle; CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING), new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION), new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH), }; token.p11.C_GetAttributeValue(session.id(), handle, attrs); serverAuth = attrs[0].getLong(); codeSigning = attrs[1].getLong(); emailProtection = attrs[2].getLong(); shaHash = attrs[3].getByteArray(); attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH), }; long c; try { token.p11.C_GetAttributeValue(session.id(), handle, attrs); c = attrs[0].getLong(); } catch (PKCS11Exception e) { // trust anchor module does not support this attribute c = serverAuth; } clientAuth = c; } Bytes getHash() { return new Bytes(shaHash); } boolean isTrusted(TrustType type) { switch (type) { case CLIENT_AUTH: return isTrusted(clientAuth); case SERVER_AUTH: return isTrusted(serverAuth); case CODE_SIGNING: return isTrusted(codeSigning); case EMAIL_PROTECTION: return isTrusted(emailProtection); case ALL: return isTrusted(TrustType.CLIENT_AUTH) && isTrusted(TrustType.SERVER_AUTH) && isTrusted(TrustType.CODE_SIGNING) && isTrusted(TrustType.EMAIL_PROTECTION); default: return false; } } private boolean isTrusted(long l) { // XXX CKT_TRUSTED? return (l == CKT_NETSCAPE_TRUSTED_DELEGATOR); } } private static class Bytes { final byte[] b; Bytes(byte[] b) { this.b = b; } public int hashCode() { return Arrays.hashCode(b); } public boolean equals(Object o) { if (this == o) { return true; } if (o instanceof Bytes == false) { return false; } Bytes other = (Bytes)o; return Arrays.equals(this.b, other.b); } } private static Map<Bytes,TrustAttributes> getTrust(SunPKCS11 provider) throws PKCS11Exception { Map<Bytes,TrustAttributes> trustMap = new HashMap<Bytes,TrustAttributes>(); Token token = provider.getToken(); Session session = null; try { session = token.getOpSession(); int MAX_NUM = 8192; CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST), }; token.p11.C_FindObjectsInit(session.id(), attrs); long[] handles = token.p11.C_FindObjects(session.id(), MAX_NUM); token.p11.C_FindObjectsFinal(session.id()); if (DEBUG) System.out.println("handles: " + handles.length); for (long handle : handles) { TrustAttributes trust = new TrustAttributes(token, session, handle); trustMap.put(trust.getHash(), trust); } } finally { token.releaseSession(session); } return trustMap; } private static native long nssGetLibraryHandle(String libraryName); private static native long nssLoadLibrary(String name) throws IOException; private static native boolean nssVersionCheck(long handle, String minVersion); private static native boolean nssInit(String functionName, long handle, String configDir); private static native Object nssGetModuleList(long handle, String libDir); }