--- old/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Key.java 2017-01-18 23:06:45.703886733 -0800 +++ /dev/null 2017-01-18 09:30:05.425422781 -0800 @@ -1,1188 +0,0 @@ -/* - * Copyright (c) 2003, 2016, 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.io.*; -import java.lang.ref.*; -import java.math.BigInteger; -import java.util.*; - -import java.security.*; -import java.security.interfaces.*; -import java.security.spec.*; - -import javax.crypto.*; -import javax.crypto.interfaces.*; -import javax.crypto.spec.*; - -import sun.security.rsa.RSAPublicKeyImpl; - -import sun.security.internal.interfaces.TlsMasterSecret; - -import sun.security.pkcs11.wrapper.*; -import static sun.security.pkcs11.wrapper.PKCS11Constants.*; - -import sun.security.util.Debug; -import sun.security.util.DerValue; -import sun.security.util.Length; -import sun.security.util.ECUtil; - -/** - * Key implementation classes. - * - * In PKCS#11, the components of private and secret keys may or may not - * be accessible. If they are, we use the algorithm specific key classes - * (e.g. DSAPrivateKey) for compatibility with existing applications. - * If the components are not accessible, we use a generic class that - * only implements PrivateKey (or SecretKey). Whether the components of a - * key are extractable is automatically determined when the key object is - * created. - * - * @author Andreas Sterbenz - * @since 1.5 - */ -abstract class P11Key implements Key, Length { - - private static final long serialVersionUID = -2575874101938349339L; - - private final static String PUBLIC = "public"; - private final static String PRIVATE = "private"; - private final static String SECRET = "secret"; - - // type of key, one of (PUBLIC, PRIVATE, SECRET) - final String type; - - // token instance - final Token token; - - // algorithm name, returned by getAlgorithm(), etc. - final String algorithm; - - // key id - final long keyID; - - // effective key length of the key, e.g. 56 for a DES key - final int keyLength; - - // flags indicating whether the key is a token object, sensitive, extractable - final boolean tokenObject, sensitive, extractable; - - // phantom reference notification clean up for session keys - private final SessionKeyRef sessionKeyRef; - - P11Key(String type, Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - this.type = type; - this.token = session.token; - this.keyID = keyID; - this.algorithm = algorithm; - this.keyLength = keyLength; - boolean tokenObject = false; - boolean sensitive = false; - boolean extractable = true; - int n = (attributes == null) ? 0 : attributes.length; - for (int i = 0; i < n; i++) { - CK_ATTRIBUTE attr = attributes[i]; - if (attr.type == CKA_TOKEN) { - tokenObject = attr.getBoolean(); - } else if (attr.type == CKA_SENSITIVE) { - sensitive = attr.getBoolean(); - } else if (attr.type == CKA_EXTRACTABLE) { - extractable = attr.getBoolean(); - } - } - this.tokenObject = tokenObject; - this.sensitive = sensitive; - this.extractable = extractable; - if (tokenObject == false) { - sessionKeyRef = new SessionKeyRef(this, keyID, session); - } else { - sessionKeyRef = null; - } - } - - // see JCA spec - public final String getAlgorithm() { - token.ensureValid(); - return algorithm; - } - - // see JCA spec - public final byte[] getEncoded() { - byte[] b = getEncodedInternal(); - return (b == null) ? null : b.clone(); - } - - abstract byte[] getEncodedInternal(); - - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - // equals() should never throw exceptions - if (token.isValid() == false) { - return false; - } - if (obj instanceof Key == false) { - return false; - } - String thisFormat = getFormat(); - if (thisFormat == null) { - // no encoding, key only equal to itself - // XXX getEncoded() for unextractable keys will change that - return false; - } - Key other = (Key)obj; - if (thisFormat.equals(other.getFormat()) == false) { - return false; - } - byte[] thisEnc = this.getEncodedInternal(); - byte[] otherEnc; - if (obj instanceof P11Key) { - otherEnc = ((P11Key)other).getEncodedInternal(); - } else { - otherEnc = other.getEncoded(); - } - return MessageDigest.isEqual(thisEnc, otherEnc); - } - - public int hashCode() { - // hashCode() should never throw exceptions - if (token.isValid() == false) { - return 0; - } - byte[] b1 = getEncodedInternal(); - if (b1 == null) { - return 0; - } - int r = b1.length; - for (int i = 0; i < b1.length; i++) { - r += (b1[i] & 0xff) * 37; - } - return r; - } - - protected Object writeReplace() throws ObjectStreamException { - KeyRep.Type type; - String format = getFormat(); - if (isPrivate() && "PKCS#8".equals(format)) { - type = KeyRep.Type.PRIVATE; - } else if (isPublic() && "X.509".equals(format)) { - type = KeyRep.Type.PUBLIC; - } else if (isSecret() && "RAW".equals(format)) { - type = KeyRep.Type.SECRET; - } else { - // XXX short term serialization for unextractable keys - throw new NotSerializableException - ("Cannot serialize sensitive and unextractable keys"); - } - return new KeyRep(type, getAlgorithm(), format, getEncoded()); - } - - public String toString() { - token.ensureValid(); - String s1 = token.provider.getName() + " " + algorithm + " " + type - + " key, " + keyLength + " bits"; - s1 += " (id " + keyID + ", " - + (tokenObject ? "token" : "session") + " object"; - if (isPublic()) { - s1 += ")"; - } else { - s1 += ", " + (sensitive ? "" : "not ") + "sensitive"; - s1 += ", " + (extractable ? "" : "un") + "extractable)"; - } - return s1; - } - - /** - * Return bit length of the key. - */ - @Override - public int length() { - return keyLength; - } - - boolean isPublic() { - return type == PUBLIC; - } - - boolean isPrivate() { - return type == PRIVATE; - } - - boolean isSecret() { - return type == SECRET; - } - - void fetchAttributes(CK_ATTRIBUTE[] attributes) { - Session tempSession = null; - try { - tempSession = token.getOpSession(); - token.p11.C_GetAttributeValue(tempSession.id(), keyID, attributes); - } catch (PKCS11Exception e) { - throw new ProviderException(e); - } finally { - token.releaseSession(tempSession); - } - } - - private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0]; - - private static CK_ATTRIBUTE[] getAttributes(Session session, long keyID, - CK_ATTRIBUTE[] knownAttributes, CK_ATTRIBUTE[] desiredAttributes) { - if (knownAttributes == null) { - knownAttributes = A0; - } - for (int i = 0; i < desiredAttributes.length; i++) { - // For each desired attribute, check to see if we have the value - // available already. If everything is here, we save a native call. - CK_ATTRIBUTE attr = desiredAttributes[i]; - for (CK_ATTRIBUTE known : knownAttributes) { - if ((attr.type == known.type) && (known.pValue != null)) { - attr.pValue = known.pValue; - break; // break inner for loop - } - } - if (attr.pValue == null) { - // nothing found, need to call C_GetAttributeValue() - for (int j = 0; j < i; j++) { - // clear values copied from knownAttributes - desiredAttributes[j].pValue = null; - } - try { - session.token.p11.C_GetAttributeValue - (session.id(), keyID, desiredAttributes); - } catch (PKCS11Exception e) { - throw new ProviderException(e); - } - break; // break loop, goto return - } - } - return desiredAttributes; - } - - static SecretKey secretKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_TOKEN), - new CK_ATTRIBUTE(CKA_SENSITIVE), - new CK_ATTRIBUTE(CKA_EXTRACTABLE), - }); - return new P11SecretKey(session, keyID, algorithm, keyLength, attributes); - } - - static SecretKey masterSecretKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) { - attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_TOKEN), - new CK_ATTRIBUTE(CKA_SENSITIVE), - new CK_ATTRIBUTE(CKA_EXTRACTABLE), - }); - return new P11TlsMasterSecretKey - (session, keyID, algorithm, keyLength, attributes, major, minor); - } - - // we assume that all components of public keys are always accessible - static PublicKey publicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - switch (algorithm) { - case "RSA": - return new P11RSAPublicKey - (session, keyID, algorithm, keyLength, attributes); - case "DSA": - return new P11DSAPublicKey - (session, keyID, algorithm, keyLength, attributes); - case "DH": - return new P11DHPublicKey - (session, keyID, algorithm, keyLength, attributes); - case "EC": - return new P11ECPublicKey - (session, keyID, algorithm, keyLength, attributes); - default: - throw new ProviderException - ("Unknown public key algorithm " + algorithm); - } - } - - static PrivateKey privateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_TOKEN), - new CK_ATTRIBUTE(CKA_SENSITIVE), - new CK_ATTRIBUTE(CKA_EXTRACTABLE), - }); - if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) { - return new P11PrivateKey - (session, keyID, algorithm, keyLength, attributes); - } else { - switch (algorithm) { - case "RSA": - // In order to decide if this is RSA CRT key, we first query - // and see if all extra CRT attributes are available. - CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT), - new CK_ATTRIBUTE(CKA_PRIME_1), - new CK_ATTRIBUTE(CKA_PRIME_2), - new CK_ATTRIBUTE(CKA_EXPONENT_1), - new CK_ATTRIBUTE(CKA_EXPONENT_2), - new CK_ATTRIBUTE(CKA_COEFFICIENT), - }; - boolean crtKey; - try { - session.token.p11.C_GetAttributeValue - (session.id(), keyID, attrs2); - crtKey = ((attrs2[0].pValue instanceof byte[]) && - (attrs2[1].pValue instanceof byte[]) && - (attrs2[2].pValue instanceof byte[]) && - (attrs2[3].pValue instanceof byte[]) && - (attrs2[4].pValue instanceof byte[]) && - (attrs2[5].pValue instanceof byte[])) ; - } catch (PKCS11Exception e) { - // ignore, assume not available - crtKey = false; - } - if (crtKey) { - return new P11RSAPrivateKey - (session, keyID, algorithm, keyLength, attributes, attrs2); - } else { - return new P11RSAPrivateNonCRTKey - (session, keyID, algorithm, keyLength, attributes); - } - case "DSA": - return new P11DSAPrivateKey - (session, keyID, algorithm, keyLength, attributes); - case "DH": - return new P11DHPrivateKey - (session, keyID, algorithm, keyLength, attributes); - case "EC": - return new P11ECPrivateKey - (session, keyID, algorithm, keyLength, attributes); - default: - throw new ProviderException - ("Unknown private key algorithm " + algorithm); - } - } - } - - // class for sensitive and unextractable private keys - private static final class P11PrivateKey extends P11Key - implements PrivateKey { - private static final long serialVersionUID = -2138581185214187615L; - - P11PrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); - } - // XXX temporary encoding for serialization purposes - public String getFormat() { - token.ensureValid(); - return null; - } - byte[] getEncodedInternal() { - token.ensureValid(); - return null; - } - } - - private static class P11SecretKey extends P11Key implements SecretKey { - private static final long serialVersionUID = -7828241727014329084L; - private volatile byte[] encoded; - P11SecretKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(SECRET, session, keyID, algorithm, keyLength, attributes); - } - public String getFormat() { - token.ensureValid(); - if (sensitive || (extractable == false)) { - return null; - } else { - return "RAW"; - } - } - byte[] getEncodedInternal() { - token.ensureValid(); - if (getFormat() == null) { - return null; - } - byte[] b = encoded; - if (b == null) { - synchronized (this) { - b = encoded; - if (b == null) { - Session tempSession = null; - try { - tempSession = token.getOpSession(); - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - }; - token.p11.C_GetAttributeValue - (tempSession.id(), keyID, attributes); - b = attributes[0].getByteArray(); - } catch (PKCS11Exception e) { - throw new ProviderException(e); - } finally { - token.releaseSession(tempSession); - } - encoded = b; - } - } - } - return b; - } - } - - @SuppressWarnings("deprecation") - private static class P11TlsMasterSecretKey extends P11SecretKey - implements TlsMasterSecret { - private static final long serialVersionUID = -1318560923770573441L; - - private final int majorVersion, minorVersion; - P11TlsMasterSecretKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) { - super(session, keyID, algorithm, keyLength, attributes); - this.majorVersion = major; - this.minorVersion = minor; - } - public int getMajorVersion() { - return majorVersion; - } - - public int getMinorVersion() { - return minorVersion; - } - } - - // RSA CRT private key - private static final class P11RSAPrivateKey extends P11Key - implements RSAPrivateCrtKey { - private static final long serialVersionUID = 9215872438913515220L; - - private BigInteger n, e, d, p, q, pe, qe, coeff; - private byte[] encoded; - P11RSAPrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE[] crtAttrs) { - super(PRIVATE, session, keyID, algorithm, keyLength, attrs); - - for (CK_ATTRIBUTE a : crtAttrs) { - if (a.type == CKA_PUBLIC_EXPONENT) { - e = a.getBigInteger(); - } else if (a.type == CKA_PRIME_1) { - p = a.getBigInteger(); - } else if (a.type == CKA_PRIME_2) { - q = a.getBigInteger(); - } else if (a.type == CKA_EXPONENT_1) { - pe = a.getBigInteger(); - } else if (a.type == CKA_EXPONENT_2) { - qe = a.getBigInteger(); - } else if (a.type == CKA_COEFFICIENT) { - coeff = a.getBigInteger(); - } - } - } - private synchronized void fetchValues() { - token.ensureValid(); - if (n != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_MODULUS), - new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), - }; - fetchAttributes(attributes); - n = attributes[0].getBigInteger(); - d = attributes[1].getBigInteger(); - } - - public String getFormat() { - token.ensureValid(); - return "PKCS#8"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - // XXX make constructor in SunRsaSign provider public - // and call it directly - KeyFactory factory = KeyFactory.getInstance - ("RSA", P11Util.getSunRsaSignProvider()); - Key newKey = factory.translateKey(this); - encoded = newKey.getEncoded(); - } catch (GeneralSecurityException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public BigInteger getModulus() { - fetchValues(); - return n; - } - public BigInteger getPublicExponent() { - return e; - } - public BigInteger getPrivateExponent() { - fetchValues(); - return d; - } - public BigInteger getPrimeP() { - return p; - } - public BigInteger getPrimeQ() { - return q; - } - public BigInteger getPrimeExponentP() { - return pe; - } - public BigInteger getPrimeExponentQ() { - return qe; - } - public BigInteger getCrtCoefficient() { - return coeff; - } - } - - // RSA non-CRT private key - private static final class P11RSAPrivateNonCRTKey extends P11Key - implements RSAPrivateKey { - private static final long serialVersionUID = 1137764983777411481L; - - private BigInteger n, d; - private byte[] encoded; - P11RSAPrivateNonCRTKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (n != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_MODULUS), - new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), - }; - fetchAttributes(attributes); - n = attributes[0].getBigInteger(); - d = attributes[1].getBigInteger(); - } - public String getFormat() { - token.ensureValid(); - return "PKCS#8"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - // XXX make constructor in SunRsaSign provider public - // and call it directly - KeyFactory factory = KeyFactory.getInstance - ("RSA", P11Util.getSunRsaSignProvider()); - Key newKey = factory.translateKey(this); - encoded = newKey.getEncoded(); - } catch (GeneralSecurityException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public BigInteger getModulus() { - fetchValues(); - return n; - } - public BigInteger getPrivateExponent() { - fetchValues(); - return d; - } - } - - private static final class P11RSAPublicKey extends P11Key - implements RSAPublicKey { - private static final long serialVersionUID = -826726289023854455L; - - private BigInteger n, e; - private byte[] encoded; - P11RSAPublicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PUBLIC, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (n != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_MODULUS), - new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT), - }; - fetchAttributes(attributes); - n = attributes[0].getBigInteger(); - e = attributes[1].getBigInteger(); - } - public String getFormat() { - token.ensureValid(); - return "X.509"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - encoded = new RSAPublicKeyImpl(n, e).getEncoded(); - } catch (InvalidKeyException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public BigInteger getModulus() { - fetchValues(); - return n; - } - public BigInteger getPublicExponent() { - fetchValues(); - return e; - } - public String toString() { - fetchValues(); - return super.toString() + "\n modulus: " + n - + "\n public exponent: " + e; - } - } - - private static final class P11DSAPublicKey extends P11Key - implements DSAPublicKey { - private static final long serialVersionUID = 5989753793316396637L; - - private BigInteger y; - private DSAParams params; - private byte[] encoded; - P11DSAPublicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PUBLIC, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (y != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_PRIME), - new CK_ATTRIBUTE(CKA_SUBPRIME), - new CK_ATTRIBUTE(CKA_BASE), - }; - fetchAttributes(attributes); - y = attributes[0].getBigInteger(); - params = new DSAParameterSpec( - attributes[1].getBigInteger(), - attributes[2].getBigInteger(), - attributes[3].getBigInteger() - ); - } - public String getFormat() { - token.ensureValid(); - return "X.509"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - Key key = new sun.security.provider.DSAPublicKey - (y, params.getP(), params.getQ(), params.getG()); - encoded = key.getEncoded(); - } catch (InvalidKeyException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public BigInteger getY() { - fetchValues(); - return y; - } - public DSAParams getParams() { - fetchValues(); - return params; - } - public String toString() { - fetchValues(); - return super.toString() + "\n y: " + y + "\n p: " + params.getP() - + "\n q: " + params.getQ() + "\n g: " + params.getG(); - } - } - - private static final class P11DSAPrivateKey extends P11Key - implements DSAPrivateKey { - private static final long serialVersionUID = 3119629997181999389L; - - private BigInteger x; - private DSAParams params; - private byte[] encoded; - P11DSAPrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (x != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_PRIME), - new CK_ATTRIBUTE(CKA_SUBPRIME), - new CK_ATTRIBUTE(CKA_BASE), - }; - fetchAttributes(attributes); - x = attributes[0].getBigInteger(); - params = new DSAParameterSpec( - attributes[1].getBigInteger(), - attributes[2].getBigInteger(), - attributes[3].getBigInteger() - ); - } - public String getFormat() { - token.ensureValid(); - return "PKCS#8"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - Key key = new sun.security.provider.DSAPrivateKey - (x, params.getP(), params.getQ(), params.getG()); - encoded = key.getEncoded(); - } catch (InvalidKeyException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public BigInteger getX() { - fetchValues(); - return x; - } - public DSAParams getParams() { - fetchValues(); - return params; - } - } - - private static final class P11DHPrivateKey extends P11Key - implements DHPrivateKey { - private static final long serialVersionUID = -1698576167364928838L; - - private BigInteger x; - private DHParameterSpec params; - private byte[] encoded; - P11DHPrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (x != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_PRIME), - new CK_ATTRIBUTE(CKA_BASE), - }; - fetchAttributes(attributes); - x = attributes[0].getBigInteger(); - params = new DHParameterSpec( - attributes[1].getBigInteger(), - attributes[2].getBigInteger() - ); - } - public String getFormat() { - token.ensureValid(); - return "PKCS#8"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - DHPrivateKeySpec spec = new DHPrivateKeySpec - (x, params.getP(), params.getG()); - KeyFactory kf = KeyFactory.getInstance - ("DH", P11Util.getSunJceProvider()); - Key key = kf.generatePrivate(spec); - encoded = key.getEncoded(); - } catch (GeneralSecurityException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public BigInteger getX() { - fetchValues(); - return x; - } - public DHParameterSpec getParams() { - fetchValues(); - return params; - } - public int hashCode() { - if (token.isValid() == false) { - return 0; - } - fetchValues(); - return Objects.hash(x, params.getP(), params.getG()); - } - public boolean equals(Object obj) { - if (this == obj) return true; - // equals() should never throw exceptions - if (token.isValid() == false) { - return false; - } - if (!(obj instanceof DHPrivateKey)) { - return false; - } - fetchValues(); - DHPrivateKey other = (DHPrivateKey) obj; - DHParameterSpec otherParams = other.getParams(); - return ((this.x.compareTo(other.getX()) == 0) && - (this.params.getP().compareTo(otherParams.getP()) == 0) && - (this.params.getG().compareTo(otherParams.getG()) == 0)); - } - } - - private static final class P11DHPublicKey extends P11Key - implements DHPublicKey { - static final long serialVersionUID = -598383872153843657L; - - private BigInteger y; - private DHParameterSpec params; - private byte[] encoded; - P11DHPublicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PUBLIC, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (y != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_PRIME), - new CK_ATTRIBUTE(CKA_BASE), - }; - fetchAttributes(attributes); - y = attributes[0].getBigInteger(); - params = new DHParameterSpec( - attributes[1].getBigInteger(), - attributes[2].getBigInteger() - ); - } - public String getFormat() { - token.ensureValid(); - return "X.509"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - DHPublicKeySpec spec = new DHPublicKeySpec - (y, params.getP(), params.getG()); - KeyFactory kf = KeyFactory.getInstance - ("DH", P11Util.getSunJceProvider()); - Key key = kf.generatePublic(spec); - encoded = key.getEncoded(); - } catch (GeneralSecurityException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public BigInteger getY() { - fetchValues(); - return y; - } - public DHParameterSpec getParams() { - fetchValues(); - return params; - } - public String toString() { - fetchValues(); - return super.toString() + "\n y: " + y + "\n p: " + params.getP() - + "\n g: " + params.getG(); - } - public int hashCode() { - if (token.isValid() == false) { - return 0; - } - fetchValues(); - return Objects.hash(y, params.getP(), params.getG()); - } - public boolean equals(Object obj) { - if (this == obj) return true; - // equals() should never throw exceptions - if (token.isValid() == false) { - return false; - } - if (!(obj instanceof DHPublicKey)) { - return false; - } - fetchValues(); - DHPublicKey other = (DHPublicKey) obj; - DHParameterSpec otherParams = other.getParams(); - return ((this.y.compareTo(other.getY()) == 0) && - (this.params.getP().compareTo(otherParams.getP()) == 0) && - (this.params.getG().compareTo(otherParams.getG()) == 0)); - } - } - - private static final class P11ECPrivateKey extends P11Key - implements ECPrivateKey { - private static final long serialVersionUID = -7786054399510515515L; - - private BigInteger s; - private ECParameterSpec params; - private byte[] encoded; - P11ECPrivateKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PRIVATE, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (s != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_VALUE), - new CK_ATTRIBUTE(CKA_EC_PARAMS, params), - }; - fetchAttributes(attributes); - s = attributes[0].getBigInteger(); - try { - params = P11ECKeyFactory.decodeParameters - (attributes[1].getByteArray()); - } catch (Exception e) { - throw new RuntimeException("Could not parse key values", e); - } - } - public String getFormat() { - token.ensureValid(); - return "PKCS#8"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - Key key = ECUtil.generateECPrivateKey(s, params); - encoded = key.getEncoded(); - } catch (InvalidKeySpecException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public BigInteger getS() { - fetchValues(); - return s; - } - public ECParameterSpec getParams() { - fetchValues(); - return params; - } - } - - private static final class P11ECPublicKey extends P11Key - implements ECPublicKey { - private static final long serialVersionUID = -6371481375154806089L; - - private ECPoint w; - private ECParameterSpec params; - private byte[] encoded; - P11ECPublicKey(Session session, long keyID, String algorithm, - int keyLength, CK_ATTRIBUTE[] attributes) { - super(PUBLIC, session, keyID, algorithm, keyLength, attributes); - } - private synchronized void fetchValues() { - token.ensureValid(); - if (w != null) { - return; - } - CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { - new CK_ATTRIBUTE(CKA_EC_POINT), - new CK_ATTRIBUTE(CKA_EC_PARAMS), - }; - fetchAttributes(attributes); - - try { - params = P11ECKeyFactory.decodeParameters - (attributes[1].getByteArray()); - byte[] ecKey = attributes[0].getByteArray(); - - // Check whether the X9.63 encoding of an EC point is wrapped - // in an ASN.1 OCTET STRING - if (!token.config.getUseEcX963Encoding()) { - DerValue wECPoint = new DerValue(ecKey); - - if (wECPoint.getTag() != DerValue.tag_OctetString) { - throw new IOException("Could not DER decode EC point." + - " Unexpected tag: " + wECPoint.getTag()); - } - w = P11ECKeyFactory.decodePoint - (wECPoint.getDataBytes(), params.getCurve()); - - } else { - w = P11ECKeyFactory.decodePoint(ecKey, params.getCurve()); - } - - } catch (Exception e) { - throw new RuntimeException("Could not parse key values", e); - } - } - public String getFormat() { - token.ensureValid(); - return "X.509"; - } - synchronized byte[] getEncodedInternal() { - token.ensureValid(); - if (encoded == null) { - fetchValues(); - try { - return ECUtil.x509EncodeECPublicKey(w, params); - } catch (InvalidKeySpecException e) { - throw new ProviderException(e); - } - } - return encoded; - } - public ECPoint getW() { - fetchValues(); - return w; - } - public ECParameterSpec getParams() { - fetchValues(); - return params; - } - public String toString() { - fetchValues(); - return super.toString() - + "\n public x coord: " + w.getAffineX() - + "\n public y coord: " + w.getAffineY() - + "\n parameters: " + params; - } - } -} - -/* - * NOTE: Must use PhantomReference here and not WeakReference - * otherwise the key maybe cleared before other objects which - * still use these keys during finalization such as SSLSocket. - */ -final class SessionKeyRef extends PhantomReference - implements Comparable { - private static ReferenceQueue refQueue = - new ReferenceQueue(); - private static Set refList = - Collections.synchronizedSortedSet(new TreeSet()); - - static ReferenceQueue referenceQueue() { - return refQueue; - } - - private static void drainRefQueueBounded() { - Session sess = null; - Token tkn = null; - while (true) { - SessionKeyRef next = (SessionKeyRef) refQueue.poll(); - if (next == null) { - break; - } - - // If the token is still valid, try to remove the object - if (next.session.token.isValid()) { - // If this key's token is the same as the previous key, the - // same session can be used for C_DestroyObject. - try { - if (next.session.token != tkn || sess == null) { - // Release session if not using previous token - if (tkn != null && sess != null) { - tkn.releaseSession(sess); - sess = null; - } - - tkn = next.session.token; - sess = tkn.getOpSession(); - } - next.disposeNative(sess); - } catch (PKCS11Exception e) { - // ignore - } - } - // Regardless of native results, dispose of java references - next.dispose(); - } - - if (tkn != null && sess != null) { - tkn.releaseSession(sess); - } - } - - // handle to the native key - private long keyID; - private Session session; - - SessionKeyRef(P11Key key , long keyID, Session session) { - super(key, refQueue); - this.keyID = keyID; - this.session = session; - this.session.addObject(); - refList.add(this); - drainRefQueueBounded(); - } - - private void disposeNative(Session s) throws PKCS11Exception { - session.token.p11.C_DestroyObject(s.id(), keyID); - } - - private void dispose() { - refList.remove(this); - this.clear(); - session.removeObject(); - } - - public int compareTo(SessionKeyRef other) { - if (this.keyID == other.keyID) { - return 0; - } else { - return (this.keyID < other.keyID) ? -1 : 1; - } - } -}