0N/A/*
4589N/A * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.pkcs11;
0N/A
0N/Aimport java.io.*;
936N/Aimport java.lang.ref.*;
0N/Aimport java.math.BigInteger;
0N/Aimport java.util.*;
0N/A
0N/Aimport java.security.*;
0N/Aimport java.security.interfaces.*;
0N/Aimport java.security.spec.*;
0N/A
0N/Aimport javax.crypto.*;
0N/Aimport javax.crypto.interfaces.*;
0N/Aimport javax.crypto.spec.*;
0N/A
0N/Aimport sun.security.rsa.RSAPublicKeyImpl;
0N/A
0N/Aimport sun.security.internal.interfaces.TlsMasterSecret;
0N/A
0N/Aimport sun.security.pkcs11.wrapper.*;
0N/Aimport static sun.security.pkcs11.wrapper.PKCS11Constants.*;
0N/A
2107N/Aimport sun.security.util.DerValue;
4589N/Aimport sun.security.util.Length;
2107N/A
0N/A/**
0N/A * Key implementation classes.
0N/A *
0N/A * In PKCS#11, the components of private and secret keys may or may not
0N/A * be accessible. If they are, we use the algorithm specific key classes
0N/A * (e.g. DSAPrivateKey) for compatibility with existing applications.
0N/A * If the components are not accessible, we use a generic class that
0N/A * only implements PrivateKey (or SecretKey). Whether the components of a
0N/A * key are extractable is automatically determined when the key object is
0N/A * created.
0N/A *
0N/A * @author Andreas Sterbenz
0N/A * @since 1.5
0N/A */
4589N/Aabstract class P11Key implements Key, Length {
0N/A
0N/A private final static String PUBLIC = "public";
0N/A private final static String PRIVATE = "private";
0N/A private final static String SECRET = "secret";
0N/A
0N/A // type of key, one of (PUBLIC, PRIVATE, SECRET)
0N/A final String type;
0N/A
0N/A // token instance
0N/A final Token token;
0N/A
0N/A // algorithm name, returned by getAlgorithm(), etc.
0N/A final String algorithm;
0N/A
0N/A // key id
0N/A final long keyID;
0N/A
0N/A // effective key length of the key, e.g. 56 for a DES key
0N/A final int keyLength;
0N/A
0N/A // flags indicating whether the key is a token object, sensitive, extractable
0N/A final boolean tokenObject, sensitive, extractable;
0N/A
2301N/A // phantom reference notification clean up for session keys
936N/A private final SessionKeyRef sessionKeyRef;
936N/A
0N/A P11Key(String type, Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A this.type = type;
0N/A this.token = session.token;
0N/A this.keyID = keyID;
0N/A this.algorithm = algorithm;
0N/A this.keyLength = keyLength;
0N/A boolean tokenObject = false;
0N/A boolean sensitive = false;
0N/A boolean extractable = true;
0N/A int n = (attributes == null) ? 0 : attributes.length;
0N/A for (int i = 0; i < n; i++) {
0N/A CK_ATTRIBUTE attr = attributes[i];
0N/A if (attr.type == CKA_TOKEN) {
0N/A tokenObject = attr.getBoolean();
0N/A } else if (attr.type == CKA_SENSITIVE) {
0N/A sensitive = attr.getBoolean();
0N/A } else if (attr.type == CKA_EXTRACTABLE) {
0N/A extractable = attr.getBoolean();
0N/A }
0N/A }
0N/A this.tokenObject = tokenObject;
0N/A this.sensitive = sensitive;
0N/A this.extractable = extractable;
0N/A if (tokenObject == false) {
936N/A sessionKeyRef = new SessionKeyRef(this, keyID, session);
936N/A } else {
936N/A sessionKeyRef = null;
0N/A }
0N/A }
0N/A
0N/A // see JCA spec
0N/A public final String getAlgorithm() {
0N/A token.ensureValid();
0N/A return algorithm;
0N/A }
0N/A
0N/A // see JCA spec
0N/A public final byte[] getEncoded() {
0N/A byte[] b = getEncodedInternal();
0N/A return (b == null) ? null : (byte[])b.clone();
0N/A }
0N/A
0N/A abstract byte[] getEncodedInternal();
0N/A
0N/A public boolean equals(Object obj) {
0N/A if (this == obj) {
0N/A return true;
0N/A }
0N/A // equals() should never throw exceptions
0N/A if (token.isValid() == false) {
0N/A return false;
0N/A }
0N/A if (obj instanceof Key == false) {
0N/A return false;
0N/A }
0N/A String thisFormat = getFormat();
0N/A if (thisFormat == null) {
0N/A // no encoding, key only equal to itself
0N/A // XXX getEncoded() for unextractable keys will change that
0N/A return false;
0N/A }
0N/A Key other = (Key)obj;
0N/A if (thisFormat.equals(other.getFormat()) == false) {
0N/A return false;
0N/A }
0N/A byte[] thisEnc = this.getEncodedInternal();
0N/A byte[] otherEnc;
0N/A if (obj instanceof P11Key) {
0N/A otherEnc = ((P11Key)other).getEncodedInternal();
0N/A } else {
0N/A otherEnc = other.getEncoded();
0N/A }
0N/A return Arrays.equals(thisEnc, otherEnc);
0N/A }
0N/A
0N/A public int hashCode() {
0N/A // hashCode() should never throw exceptions
0N/A if (token.isValid() == false) {
0N/A return 0;
0N/A }
0N/A byte[] b1 = getEncodedInternal();
0N/A if (b1 == null) {
0N/A return 0;
0N/A }
0N/A int r = b1.length;
0N/A for (int i = 0; i < b1.length; i++) {
0N/A r += (b1[i] & 0xff) * 37;
0N/A }
0N/A return r;
0N/A }
0N/A
0N/A protected Object writeReplace() throws ObjectStreamException {
0N/A KeyRep.Type type;
0N/A String format = getFormat();
0N/A if (isPrivate() && "PKCS#8".equals(format)) {
0N/A type = KeyRep.Type.PRIVATE;
0N/A } else if (isPublic() && "X.509".equals(format)) {
0N/A type = KeyRep.Type.PUBLIC;
0N/A } else if (isSecret() && "RAW".equals(format)) {
0N/A type = KeyRep.Type.SECRET;
0N/A } else {
0N/A // XXX short term serialization for unextractable keys
0N/A throw new NotSerializableException
0N/A ("Cannot serialize sensitive and unextractable keys");
0N/A }
0N/A return new KeyRep(type, getAlgorithm(), format, getEncoded());
0N/A }
0N/A
0N/A public String toString() {
0N/A token.ensureValid();
0N/A String s1 = token.provider.getName() + " " + algorithm + " " + type
0N/A + " key, " + keyLength + " bits";
0N/A s1 += " (id " + keyID + ", "
0N/A + (tokenObject ? "token" : "session") + " object";
0N/A if (isPublic()) {
0N/A s1 += ")";
0N/A } else {
0N/A s1 += ", " + (sensitive ? "" : "not ") + "sensitive";
0N/A s1 += ", " + (extractable ? "" : "un") + "extractable)";
0N/A }
0N/A return s1;
0N/A }
0N/A
4589N/A /**
4589N/A * Return bit length of the key.
4589N/A */
4589N/A @Override
4589N/A public int length() {
0N/A return keyLength;
0N/A }
0N/A
0N/A boolean isPublic() {
0N/A return type == PUBLIC;
0N/A }
0N/A
0N/A boolean isPrivate() {
0N/A return type == PRIVATE;
0N/A }
0N/A
0N/A boolean isSecret() {
0N/A return type == SECRET;
0N/A }
0N/A
0N/A void fetchAttributes(CK_ATTRIBUTE[] attributes) {
0N/A Session tempSession = null;
0N/A try {
0N/A tempSession = token.getOpSession();
0N/A token.p11.C_GetAttributeValue(tempSession.id(), keyID, attributes);
0N/A } catch (PKCS11Exception e) {
0N/A throw new ProviderException(e);
0N/A } finally {
0N/A token.releaseSession(tempSession);
0N/A }
0N/A }
0N/A
0N/A private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
0N/A
0N/A private static CK_ATTRIBUTE[] getAttributes(Session session, long keyID,
0N/A CK_ATTRIBUTE[] knownAttributes, CK_ATTRIBUTE[] desiredAttributes) {
0N/A if (knownAttributes == null) {
0N/A knownAttributes = A0;
0N/A }
0N/A for (int i = 0; i < desiredAttributes.length; i++) {
0N/A // For each desired attribute, check to see if we have the value
0N/A // available already. If everything is here, we save a native call.
0N/A CK_ATTRIBUTE attr = desiredAttributes[i];
0N/A for (CK_ATTRIBUTE known : knownAttributes) {
0N/A if ((attr.type == known.type) && (known.pValue != null)) {
0N/A attr.pValue = known.pValue;
0N/A break; // break inner for loop
0N/A }
0N/A }
0N/A if (attr.pValue == null) {
0N/A // nothing found, need to call C_GetAttributeValue()
0N/A for (int j = 0; j < i; j++) {
0N/A // clear values copied from knownAttributes
0N/A desiredAttributes[j].pValue = null;
0N/A }
0N/A try {
0N/A session.token.p11.C_GetAttributeValue
0N/A (session.id(), keyID, desiredAttributes);
0N/A } catch (PKCS11Exception e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A break; // break loop, goto return
0N/A }
0N/A }
0N/A return desiredAttributes;
0N/A }
0N/A
0N/A static SecretKey secretKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_TOKEN),
0N/A new CK_ATTRIBUTE(CKA_SENSITIVE),
0N/A new CK_ATTRIBUTE(CKA_EXTRACTABLE),
0N/A });
0N/A return new P11SecretKey(session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A
0N/A static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
0N/A attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_TOKEN),
0N/A new CK_ATTRIBUTE(CKA_SENSITIVE),
0N/A new CK_ATTRIBUTE(CKA_EXTRACTABLE),
0N/A });
0N/A return new P11TlsMasterSecretKey
0N/A (session, keyID, algorithm, keyLength, attributes, major, minor);
0N/A }
0N/A
0N/A // we assume that all components of public keys are always accessible
0N/A static PublicKey publicKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A if (algorithm.equals("RSA")) {
0N/A return new P11RSAPublicKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else if (algorithm.equals("DSA")) {
0N/A return new P11DSAPublicKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else if (algorithm.equals("DH")) {
0N/A return new P11DHPublicKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else if (algorithm.equals("EC")) {
0N/A return new P11ECPublicKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else {
0N/A throw new ProviderException
0N/A ("Unknown public key algorithm " + algorithm);
0N/A }
0N/A }
0N/A
0N/A static PrivateKey privateKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_TOKEN),
0N/A new CK_ATTRIBUTE(CKA_SENSITIVE),
0N/A new CK_ATTRIBUTE(CKA_EXTRACTABLE),
0N/A });
0N/A if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) {
0N/A return new P11PrivateKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else {
0N/A if (algorithm.equals("RSA")) {
0N/A // XXX better test for RSA CRT keys (single getAttributes() call)
0N/A // we need to determine whether this is a CRT key
0N/A // see if we can obtain the public exponent
0N/A // this should also be readable for sensitive/extractable keys
0N/A CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
0N/A };
0N/A boolean crtKey;
0N/A try {
0N/A session.token.p11.C_GetAttributeValue
0N/A (session.id(), keyID, attrs2);
0N/A crtKey = (attrs2[0].pValue instanceof byte[]);
0N/A } catch (PKCS11Exception e) {
0N/A // ignore, assume not available
0N/A crtKey = false;
0N/A }
0N/A if (crtKey) {
0N/A return new P11RSAPrivateKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else {
0N/A return new P11RSAPrivateNonCRTKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A } else if (algorithm.equals("DSA")) {
0N/A return new P11DSAPrivateKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else if (algorithm.equals("DH")) {
0N/A return new P11DHPrivateKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else if (algorithm.equals("EC")) {
0N/A return new P11ECPrivateKey
0N/A (session, keyID, algorithm, keyLength, attributes);
0N/A } else {
0N/A throw new ProviderException
0N/A ("Unknown private key algorithm " + algorithm);
0N/A }
0N/A }
0N/A }
0N/A
0N/A // class for sensitive and unextractable private keys
0N/A private static final class P11PrivateKey extends P11Key
0N/A implements PrivateKey {
0N/A P11PrivateKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A // XXX temporary encoding for serialization purposes
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return null;
0N/A }
0N/A byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A private static class P11SecretKey extends P11Key implements SecretKey {
0N/A private volatile byte[] encoded;
0N/A P11SecretKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(SECRET, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A if (sensitive || (extractable == false)) {
0N/A return null;
0N/A } else {
0N/A return "RAW";
0N/A }
0N/A }
0N/A byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (getFormat() == null) {
0N/A return null;
0N/A }
0N/A byte[] b = encoded;
0N/A if (b == null) {
0N/A synchronized (this) {
0N/A b = encoded;
0N/A if (b == null) {
0N/A Session tempSession = null;
0N/A try {
0N/A tempSession = token.getOpSession();
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_VALUE),
0N/A };
0N/A token.p11.C_GetAttributeValue
0N/A (tempSession.id(), keyID, attributes);
0N/A b = attributes[0].getByteArray();
0N/A } catch (PKCS11Exception e) {
0N/A throw new ProviderException(e);
0N/A } finally {
0N/A token.releaseSession(tempSession);
0N/A }
0N/A encoded = b;
0N/A }
0N/A }
0N/A }
0N/A return b;
0N/A }
0N/A }
0N/A
0N/A private static class P11TlsMasterSecretKey extends P11SecretKey
0N/A implements TlsMasterSecret {
0N/A private final int majorVersion, minorVersion;
0N/A P11TlsMasterSecretKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
0N/A super(session, keyID, algorithm, keyLength, attributes);
0N/A this.majorVersion = major;
0N/A this.minorVersion = minor;
0N/A }
0N/A public int getMajorVersion() {
0N/A return majorVersion;
0N/A }
0N/A
0N/A public int getMinorVersion() {
0N/A return minorVersion;
0N/A }
0N/A }
0N/A
0N/A // RSA CRT private key
0N/A private static final class P11RSAPrivateKey extends P11Key
0N/A implements RSAPrivateCrtKey {
0N/A private BigInteger n, e, d, p, q, pe, qe, coeff;
0N/A private byte[] encoded;
0N/A P11RSAPrivateKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (n != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_MODULUS),
0N/A new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
0N/A new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
0N/A new CK_ATTRIBUTE(CKA_PRIME_1),
0N/A new CK_ATTRIBUTE(CKA_PRIME_2),
0N/A new CK_ATTRIBUTE(CKA_EXPONENT_1),
0N/A new CK_ATTRIBUTE(CKA_EXPONENT_2),
0N/A new CK_ATTRIBUTE(CKA_COEFFICIENT),
0N/A };
0N/A fetchAttributes(attributes);
0N/A n = attributes[0].getBigInteger();
0N/A e = attributes[1].getBigInteger();
0N/A d = attributes[2].getBigInteger();
0N/A p = attributes[3].getBigInteger();
0N/A q = attributes[4].getBigInteger();
0N/A pe = attributes[5].getBigInteger();
0N/A qe = attributes[6].getBigInteger();
0N/A coeff = attributes[7].getBigInteger();
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "PKCS#8";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A // XXX make constructor in SunRsaSign provider public
0N/A // and call it directly
0N/A KeyFactory factory = KeyFactory.getInstance
0N/A ("RSA", P11Util.getSunRsaSignProvider());
0N/A Key newKey = factory.translateKey(this);
0N/A encoded = newKey.getEncoded();
0N/A } catch (GeneralSecurityException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public BigInteger getModulus() {
0N/A fetchValues();
0N/A return n;
0N/A }
0N/A public BigInteger getPublicExponent() {
0N/A fetchValues();
0N/A return e;
0N/A }
0N/A public BigInteger getPrivateExponent() {
0N/A fetchValues();
0N/A return d;
0N/A }
0N/A public BigInteger getPrimeP() {
0N/A fetchValues();
0N/A return p;
0N/A }
0N/A public BigInteger getPrimeQ() {
0N/A fetchValues();
0N/A return q;
0N/A }
0N/A public BigInteger getPrimeExponentP() {
0N/A fetchValues();
0N/A return pe;
0N/A }
0N/A public BigInteger getPrimeExponentQ() {
0N/A fetchValues();
0N/A return qe;
0N/A }
0N/A public BigInteger getCrtCoefficient() {
0N/A fetchValues();
0N/A return coeff;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A StringBuilder sb = new StringBuilder(super.toString());
0N/A sb.append("\n modulus: ");
0N/A sb.append(n);
0N/A sb.append("\n public exponent: ");
0N/A sb.append(e);
0N/A sb.append("\n private exponent: ");
0N/A sb.append(d);
0N/A sb.append("\n prime p: ");
0N/A sb.append(p);
0N/A sb.append("\n prime q: ");
0N/A sb.append(q);
0N/A sb.append("\n prime exponent p: ");
0N/A sb.append(pe);
0N/A sb.append("\n prime exponent q: ");
0N/A sb.append(qe);
0N/A sb.append("\n crt coefficient: ");
0N/A sb.append(coeff);
0N/A return sb.toString();
0N/A }
0N/A }
0N/A
0N/A // RSA non-CRT private key
0N/A private static final class P11RSAPrivateNonCRTKey extends P11Key
0N/A implements RSAPrivateKey {
0N/A private BigInteger n, d;
0N/A private byte[] encoded;
0N/A P11RSAPrivateNonCRTKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (n != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_MODULUS),
0N/A new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
0N/A };
0N/A fetchAttributes(attributes);
0N/A n = attributes[0].getBigInteger();
0N/A d = attributes[1].getBigInteger();
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "PKCS#8";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A // XXX make constructor in SunRsaSign provider public
0N/A // and call it directly
0N/A KeyFactory factory = KeyFactory.getInstance
0N/A ("RSA", P11Util.getSunRsaSignProvider());
0N/A Key newKey = factory.translateKey(this);
0N/A encoded = newKey.getEncoded();
0N/A } catch (GeneralSecurityException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public BigInteger getModulus() {
0N/A fetchValues();
0N/A return n;
0N/A }
0N/A public BigInteger getPrivateExponent() {
0N/A fetchValues();
0N/A return d;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A StringBuilder sb = new StringBuilder(super.toString());
0N/A sb.append("\n modulus: ");
0N/A sb.append(n);
0N/A sb.append("\n private exponent: ");
0N/A sb.append(d);
0N/A return sb.toString();
0N/A }
0N/A }
0N/A
0N/A private static final class P11RSAPublicKey extends P11Key
0N/A implements RSAPublicKey {
0N/A private BigInteger n, e;
0N/A private byte[] encoded;
0N/A P11RSAPublicKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (n != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_MODULUS),
0N/A new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
0N/A };
0N/A fetchAttributes(attributes);
0N/A n = attributes[0].getBigInteger();
0N/A e = attributes[1].getBigInteger();
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "X.509";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A encoded = new RSAPublicKeyImpl(n, e).getEncoded();
0N/A } catch (InvalidKeyException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public BigInteger getModulus() {
0N/A fetchValues();
0N/A return n;
0N/A }
0N/A public BigInteger getPublicExponent() {
0N/A fetchValues();
0N/A return e;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A return super.toString() + "\n modulus: " + n
0N/A + "\n public exponent: " + e;
0N/A }
0N/A }
0N/A
0N/A private static final class P11DSAPublicKey extends P11Key
0N/A implements DSAPublicKey {
0N/A private BigInteger y;
0N/A private DSAParams params;
0N/A private byte[] encoded;
0N/A P11DSAPublicKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (y != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_VALUE),
0N/A new CK_ATTRIBUTE(CKA_PRIME),
0N/A new CK_ATTRIBUTE(CKA_SUBPRIME),
0N/A new CK_ATTRIBUTE(CKA_BASE),
0N/A };
0N/A fetchAttributes(attributes);
0N/A y = attributes[0].getBigInteger();
0N/A params = new DSAParameterSpec(
0N/A attributes[1].getBigInteger(),
0N/A attributes[2].getBigInteger(),
0N/A attributes[3].getBigInteger()
0N/A );
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "X.509";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A Key key = new sun.security.provider.DSAPublicKey
0N/A (y, params.getP(), params.getQ(), params.getG());
0N/A encoded = key.getEncoded();
0N/A } catch (InvalidKeyException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public BigInteger getY() {
0N/A fetchValues();
0N/A return y;
0N/A }
0N/A public DSAParams getParams() {
0N/A fetchValues();
0N/A return params;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A return super.toString() + "\n y: " + y + "\n p: " + params.getP()
0N/A + "\n q: " + params.getQ() + "\n g: " + params.getG();
0N/A }
0N/A }
0N/A
0N/A private static final class P11DSAPrivateKey extends P11Key
0N/A implements DSAPrivateKey {
0N/A private BigInteger x;
0N/A private DSAParams params;
0N/A private byte[] encoded;
0N/A P11DSAPrivateKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (x != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_VALUE),
0N/A new CK_ATTRIBUTE(CKA_PRIME),
0N/A new CK_ATTRIBUTE(CKA_SUBPRIME),
0N/A new CK_ATTRIBUTE(CKA_BASE),
0N/A };
0N/A fetchAttributes(attributes);
0N/A x = attributes[0].getBigInteger();
0N/A params = new DSAParameterSpec(
0N/A attributes[1].getBigInteger(),
0N/A attributes[2].getBigInteger(),
0N/A attributes[3].getBigInteger()
0N/A );
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "PKCS#8";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A Key key = new sun.security.provider.DSAPrivateKey
0N/A (x, params.getP(), params.getQ(), params.getG());
0N/A encoded = key.getEncoded();
0N/A } catch (InvalidKeyException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public BigInteger getX() {
0N/A fetchValues();
0N/A return x;
0N/A }
0N/A public DSAParams getParams() {
0N/A fetchValues();
0N/A return params;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A return super.toString() + "\n x: " + x + "\n p: " + params.getP()
0N/A + "\n q: " + params.getQ() + "\n g: " + params.getG();
0N/A }
0N/A }
0N/A
0N/A private static final class P11DHPrivateKey extends P11Key
0N/A implements DHPrivateKey {
0N/A private BigInteger x;
0N/A private DHParameterSpec params;
0N/A private byte[] encoded;
0N/A P11DHPrivateKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (x != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_VALUE),
0N/A new CK_ATTRIBUTE(CKA_PRIME),
0N/A new CK_ATTRIBUTE(CKA_BASE),
0N/A };
0N/A fetchAttributes(attributes);
0N/A x = attributes[0].getBigInteger();
0N/A params = new DHParameterSpec(
0N/A attributes[1].getBigInteger(),
0N/A attributes[2].getBigInteger()
0N/A );
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "PKCS#8";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A DHPrivateKeySpec spec = new DHPrivateKeySpec
0N/A (x, params.getP(), params.getG());
0N/A KeyFactory kf = KeyFactory.getInstance
0N/A ("DH", P11Util.getSunJceProvider());
0N/A Key key = kf.generatePrivate(spec);
0N/A encoded = key.getEncoded();
0N/A } catch (GeneralSecurityException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public BigInteger getX() {
0N/A fetchValues();
0N/A return x;
0N/A }
0N/A public DHParameterSpec getParams() {
0N/A fetchValues();
0N/A return params;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A return super.toString() + "\n x: " + x + "\n p: " + params.getP()
0N/A + "\n g: " + params.getG();
0N/A }
0N/A }
0N/A
0N/A private static final class P11DHPublicKey extends P11Key
0N/A implements DHPublicKey {
0N/A private BigInteger y;
0N/A private DHParameterSpec params;
0N/A private byte[] encoded;
0N/A P11DHPublicKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (y != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_VALUE),
0N/A new CK_ATTRIBUTE(CKA_PRIME),
0N/A new CK_ATTRIBUTE(CKA_BASE),
0N/A };
0N/A fetchAttributes(attributes);
0N/A y = attributes[0].getBigInteger();
0N/A params = new DHParameterSpec(
0N/A attributes[1].getBigInteger(),
0N/A attributes[2].getBigInteger()
0N/A );
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "X.509";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A DHPublicKeySpec spec = new DHPublicKeySpec
0N/A (y, params.getP(), params.getG());
0N/A KeyFactory kf = KeyFactory.getInstance
0N/A ("DH", P11Util.getSunJceProvider());
0N/A Key key = kf.generatePublic(spec);
0N/A encoded = key.getEncoded();
0N/A } catch (GeneralSecurityException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public BigInteger getY() {
0N/A fetchValues();
0N/A return y;
0N/A }
0N/A public DHParameterSpec getParams() {
0N/A fetchValues();
0N/A return params;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A return super.toString() + "\n y: " + y + "\n p: " + params.getP()
0N/A + "\n g: " + params.getG();
0N/A }
0N/A }
0N/A
0N/A private static final class P11ECPrivateKey extends P11Key
0N/A implements ECPrivateKey {
0N/A private BigInteger s;
0N/A private ECParameterSpec params;
0N/A private byte[] encoded;
0N/A P11ECPrivateKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (s != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_VALUE),
0N/A new CK_ATTRIBUTE(CKA_EC_PARAMS, params),
0N/A };
0N/A fetchAttributes(attributes);
0N/A s = attributes[0].getBigInteger();
0N/A try {
0N/A params = P11ECKeyFactory.decodeParameters
0N/A (attributes[1].getByteArray());
0N/A } catch (Exception e) {
0N/A throw new RuntimeException("Could not parse key values", e);
0N/A }
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "PKCS#8";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A Key key = new sun.security.ec.ECPrivateKeyImpl(s, params);
0N/A encoded = key.getEncoded();
0N/A } catch (InvalidKeyException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public BigInteger getS() {
0N/A fetchValues();
0N/A return s;
0N/A }
0N/A public ECParameterSpec getParams() {
0N/A fetchValues();
0N/A return params;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A return super.toString()
0N/A + "\n private value: " + s
0N/A + "\n parameters: " + params;
0N/A }
0N/A }
0N/A
0N/A private static final class P11ECPublicKey extends P11Key
0N/A implements ECPublicKey {
0N/A private ECPoint w;
0N/A private ECParameterSpec params;
0N/A private byte[] encoded;
0N/A P11ECPublicKey(Session session, long keyID, String algorithm,
0N/A int keyLength, CK_ATTRIBUTE[] attributes) {
0N/A super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
0N/A }
0N/A private synchronized void fetchValues() {
0N/A token.ensureValid();
0N/A if (w != null) {
0N/A return;
0N/A }
0N/A CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_EC_POINT),
0N/A new CK_ATTRIBUTE(CKA_EC_PARAMS),
0N/A };
0N/A fetchAttributes(attributes);
3744N/A
0N/A try {
0N/A params = P11ECKeyFactory.decodeParameters
0N/A (attributes[1].getByteArray());
3744N/A byte[] ecKey = attributes[0].getByteArray();
2107N/A
4426N/A // Check whether the X9.63 encoding of an EC point is wrapped
4426N/A // in an ASN.1 OCTET STRING
4426N/A if (!token.config.getUseEcX963Encoding()) {
3744N/A DerValue wECPoint = new DerValue(ecKey);
3744N/A
4426N/A if (wECPoint.getTag() != DerValue.tag_OctetString) {
4426N/A throw new IOException("Could not DER decode EC point." +
4426N/A " Unexpected tag: " + wECPoint.getTag());
4426N/A }
3744N/A w = P11ECKeyFactory.decodePoint
3744N/A (wECPoint.getDataBytes(), params.getCurve());
3744N/A
4426N/A } else {
3744N/A w = P11ECKeyFactory.decodePoint(ecKey, params.getCurve());
3744N/A }
2107N/A
0N/A } catch (Exception e) {
0N/A throw new RuntimeException("Could not parse key values", e);
0N/A }
0N/A }
0N/A public String getFormat() {
0N/A token.ensureValid();
0N/A return "X.509";
0N/A }
0N/A synchronized byte[] getEncodedInternal() {
0N/A token.ensureValid();
0N/A if (encoded == null) {
0N/A fetchValues();
0N/A try {
0N/A Key key = new sun.security.ec.ECPublicKeyImpl(w, params);
0N/A encoded = key.getEncoded();
0N/A } catch (InvalidKeyException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A return encoded;
0N/A }
0N/A public ECPoint getW() {
0N/A fetchValues();
0N/A return w;
0N/A }
0N/A public ECParameterSpec getParams() {
0N/A fetchValues();
0N/A return params;
0N/A }
0N/A public String toString() {
0N/A fetchValues();
0N/A return super.toString()
0N/A + "\n public x coord: " + w.getAffineX()
0N/A + "\n public y coord: " + w.getAffineY()
0N/A + "\n parameters: " + params;
0N/A }
0N/A }
936N/A}
0N/A
2301N/A/*
2301N/A * NOTE: Must use PhantomReference here and not WeakReference
2301N/A * otherwise the key maybe cleared before other objects which
2301N/A * still use these keys during finalization such as SSLSocket.
2301N/A */
2301N/Afinal class SessionKeyRef extends PhantomReference<P11Key>
936N/A implements Comparable<SessionKeyRef> {
936N/A private static ReferenceQueue<P11Key> refQueue =
936N/A new ReferenceQueue<P11Key>();
936N/A private static Set<SessionKeyRef> refList =
936N/A Collections.synchronizedSortedSet(new TreeSet<SessionKeyRef>());
936N/A
936N/A static ReferenceQueue<P11Key> referenceQueue() {
936N/A return refQueue;
936N/A }
936N/A
936N/A private static void drainRefQueueBounded() {
2301N/A while (true) {
936N/A SessionKeyRef next = (SessionKeyRef) refQueue.poll();
2301N/A if (next == null) break;
2301N/A next.dispose();
936N/A }
936N/A }
936N/A
936N/A // handle to the native key
936N/A private long keyID;
936N/A private Session session;
936N/A
936N/A SessionKeyRef(P11Key key , long keyID, Session session) {
936N/A super(key, refQueue);
936N/A this.keyID = keyID;
936N/A this.session = session;
936N/A this.session.addObject();
936N/A refList.add(this);
936N/A // TBD: run at some interval and not every time?
936N/A drainRefQueueBounded();
936N/A }
936N/A
2301N/A private void dispose() {
936N/A refList.remove(this);
936N/A if (session.token.isValid()) {
936N/A Session newSession = null;
936N/A try {
936N/A newSession = session.token.getOpSession();
936N/A session.token.p11.C_DestroyObject(newSession.id(), keyID);
936N/A } catch (PKCS11Exception e) {
936N/A // ignore
936N/A } finally {
2301N/A this.clear();
936N/A session.token.releaseSession(newSession);
936N/A session.removeObject();
936N/A }
936N/A }
936N/A }
936N/A
936N/A public int compareTo(SessionKeyRef other) {
936N/A if (this.keyID == other.keyID) {
936N/A return 0;
936N/A } else {
936N/A return (this.keyID < other.keyID) ? -1 : 1;
936N/A }
936N/A }
0N/A}