src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
changeset 47216 71c04702a3d5
parent 43248 5e15de85a1a0
child 50204 3195a713e24d
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.security.pkcs11;
       
    27 
       
    28 import java.io.*;
       
    29 import java.lang.ref.*;
       
    30 import java.math.BigInteger;
       
    31 import java.util.*;
       
    32 
       
    33 import java.security.*;
       
    34 import java.security.interfaces.*;
       
    35 import java.security.spec.*;
       
    36 
       
    37 import javax.crypto.*;
       
    38 import javax.crypto.interfaces.*;
       
    39 import javax.crypto.spec.*;
       
    40 
       
    41 import sun.security.rsa.RSAPublicKeyImpl;
       
    42 
       
    43 import sun.security.internal.interfaces.TlsMasterSecret;
       
    44 
       
    45 import sun.security.pkcs11.wrapper.*;
       
    46 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
       
    47 
       
    48 import sun.security.util.Debug;
       
    49 import sun.security.util.DerValue;
       
    50 import sun.security.util.Length;
       
    51 import sun.security.util.ECUtil;
       
    52 
       
    53 /**
       
    54  * Key implementation classes.
       
    55  *
       
    56  * In PKCS#11, the components of private and secret keys may or may not
       
    57  * be accessible. If they are, we use the algorithm specific key classes
       
    58  * (e.g. DSAPrivateKey) for compatibility with existing applications.
       
    59  * If the components are not accessible, we use a generic class that
       
    60  * only implements PrivateKey (or SecretKey). Whether the components of a
       
    61  * key are extractable is automatically determined when the key object is
       
    62  * created.
       
    63  *
       
    64  * @author  Andreas Sterbenz
       
    65  * @since   1.5
       
    66  */
       
    67 abstract class P11Key implements Key, Length {
       
    68 
       
    69     private static final long serialVersionUID = -2575874101938349339L;
       
    70 
       
    71     private final static String PUBLIC = "public";
       
    72     private final static String PRIVATE = "private";
       
    73     private final static String SECRET = "secret";
       
    74 
       
    75     // type of key, one of (PUBLIC, PRIVATE, SECRET)
       
    76     final String type;
       
    77 
       
    78     // token instance
       
    79     final Token token;
       
    80 
       
    81     // algorithm name, returned by getAlgorithm(), etc.
       
    82     final String algorithm;
       
    83 
       
    84     // key id
       
    85     final long keyID;
       
    86 
       
    87     // effective key length of the key, e.g. 56 for a DES key
       
    88     final int keyLength;
       
    89 
       
    90     // flags indicating whether the key is a token object, sensitive, extractable
       
    91     final boolean tokenObject, sensitive, extractable;
       
    92 
       
    93     // phantom reference notification clean up for session keys
       
    94     private final SessionKeyRef sessionKeyRef;
       
    95 
       
    96     P11Key(String type, Session session, long keyID, String algorithm,
       
    97             int keyLength, CK_ATTRIBUTE[] attributes) {
       
    98         this.type = type;
       
    99         this.token = session.token;
       
   100         this.keyID = keyID;
       
   101         this.algorithm = algorithm;
       
   102         this.keyLength = keyLength;
       
   103         boolean tokenObject = false;
       
   104         boolean sensitive = false;
       
   105         boolean extractable = true;
       
   106         int n = (attributes == null) ? 0 : attributes.length;
       
   107         for (int i = 0; i < n; i++) {
       
   108             CK_ATTRIBUTE attr = attributes[i];
       
   109             if (attr.type == CKA_TOKEN) {
       
   110                 tokenObject = attr.getBoolean();
       
   111             } else if (attr.type == CKA_SENSITIVE) {
       
   112                 sensitive = attr.getBoolean();
       
   113             } else if (attr.type == CKA_EXTRACTABLE) {
       
   114                 extractable = attr.getBoolean();
       
   115             }
       
   116         }
       
   117         this.tokenObject = tokenObject;
       
   118         this.sensitive = sensitive;
       
   119         this.extractable = extractable;
       
   120         if (tokenObject == false) {
       
   121             sessionKeyRef = new SessionKeyRef(this, keyID, session);
       
   122         } else {
       
   123             sessionKeyRef = null;
       
   124         }
       
   125     }
       
   126 
       
   127     // see JCA spec
       
   128     public final String getAlgorithm() {
       
   129         token.ensureValid();
       
   130         return algorithm;
       
   131     }
       
   132 
       
   133     // see JCA spec
       
   134     public final byte[] getEncoded() {
       
   135         byte[] b = getEncodedInternal();
       
   136         return (b == null) ? null : b.clone();
       
   137     }
       
   138 
       
   139     abstract byte[] getEncodedInternal();
       
   140 
       
   141     public boolean equals(Object obj) {
       
   142         if (this == obj) {
       
   143             return true;
       
   144         }
       
   145         // equals() should never throw exceptions
       
   146         if (token.isValid() == false) {
       
   147             return false;
       
   148         }
       
   149         if (obj instanceof Key == false) {
       
   150             return false;
       
   151         }
       
   152         String thisFormat = getFormat();
       
   153         if (thisFormat == null) {
       
   154             // no encoding, key only equal to itself
       
   155             // XXX getEncoded() for unextractable keys will change that
       
   156             return false;
       
   157         }
       
   158         Key other = (Key)obj;
       
   159         if (thisFormat.equals(other.getFormat()) == false) {
       
   160             return false;
       
   161         }
       
   162         byte[] thisEnc = this.getEncodedInternal();
       
   163         byte[] otherEnc;
       
   164         if (obj instanceof P11Key) {
       
   165             otherEnc = ((P11Key)other).getEncodedInternal();
       
   166         } else {
       
   167             otherEnc = other.getEncoded();
       
   168         }
       
   169         return MessageDigest.isEqual(thisEnc, otherEnc);
       
   170     }
       
   171 
       
   172     public int hashCode() {
       
   173         // hashCode() should never throw exceptions
       
   174         if (token.isValid() == false) {
       
   175             return 0;
       
   176         }
       
   177         byte[] b1 = getEncodedInternal();
       
   178         if (b1 == null) {
       
   179             return 0;
       
   180         }
       
   181         int r = b1.length;
       
   182         for (int i = 0; i < b1.length; i++) {
       
   183             r += (b1[i] & 0xff) * 37;
       
   184         }
       
   185         return r;
       
   186     }
       
   187 
       
   188     protected Object writeReplace() throws ObjectStreamException {
       
   189         KeyRep.Type type;
       
   190         String format = getFormat();
       
   191         if (isPrivate() && "PKCS#8".equals(format)) {
       
   192             type = KeyRep.Type.PRIVATE;
       
   193         } else if (isPublic() && "X.509".equals(format)) {
       
   194             type = KeyRep.Type.PUBLIC;
       
   195         } else if (isSecret() && "RAW".equals(format)) {
       
   196             type = KeyRep.Type.SECRET;
       
   197         } else {
       
   198             // XXX short term serialization for unextractable keys
       
   199             throw new NotSerializableException
       
   200                 ("Cannot serialize sensitive and unextractable keys");
       
   201         }
       
   202         return new KeyRep(type, getAlgorithm(), format, getEncoded());
       
   203     }
       
   204 
       
   205     public String toString() {
       
   206         token.ensureValid();
       
   207         String s1 = token.provider.getName() + " " + algorithm + " " + type
       
   208                 + " key, " + keyLength + " bits";
       
   209         s1 += " (id " + keyID + ", "
       
   210                 + (tokenObject ? "token" : "session") + " object";
       
   211         if (isPublic()) {
       
   212             s1 += ")";
       
   213         } else {
       
   214             s1 += ", " + (sensitive ? "" : "not ") + "sensitive";
       
   215             s1 += ", " + (extractable ? "" : "un") + "extractable)";
       
   216         }
       
   217         return s1;
       
   218     }
       
   219 
       
   220     /**
       
   221      * Return bit length of the key.
       
   222      */
       
   223     @Override
       
   224     public int length() {
       
   225         return keyLength;
       
   226     }
       
   227 
       
   228     boolean isPublic() {
       
   229         return type == PUBLIC;
       
   230     }
       
   231 
       
   232     boolean isPrivate() {
       
   233         return type == PRIVATE;
       
   234     }
       
   235 
       
   236     boolean isSecret() {
       
   237         return type == SECRET;
       
   238     }
       
   239 
       
   240     void fetchAttributes(CK_ATTRIBUTE[] attributes) {
       
   241         Session tempSession = null;
       
   242         try {
       
   243             tempSession = token.getOpSession();
       
   244             token.p11.C_GetAttributeValue(tempSession.id(), keyID, attributes);
       
   245         } catch (PKCS11Exception e) {
       
   246             throw new ProviderException(e);
       
   247         } finally {
       
   248             token.releaseSession(tempSession);
       
   249         }
       
   250     }
       
   251 
       
   252     private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
       
   253 
       
   254     private static CK_ATTRIBUTE[] getAttributes(Session session, long keyID,
       
   255             CK_ATTRIBUTE[] knownAttributes, CK_ATTRIBUTE[] desiredAttributes) {
       
   256         if (knownAttributes == null) {
       
   257             knownAttributes = A0;
       
   258         }
       
   259         for (int i = 0; i < desiredAttributes.length; i++) {
       
   260             // For each desired attribute, check to see if we have the value
       
   261             // available already. If everything is here, we save a native call.
       
   262             CK_ATTRIBUTE attr = desiredAttributes[i];
       
   263             for (CK_ATTRIBUTE known : knownAttributes) {
       
   264                 if ((attr.type == known.type) && (known.pValue != null)) {
       
   265                     attr.pValue = known.pValue;
       
   266                     break; // break inner for loop
       
   267                 }
       
   268             }
       
   269             if (attr.pValue == null) {
       
   270                 // nothing found, need to call C_GetAttributeValue()
       
   271                 for (int j = 0; j < i; j++) {
       
   272                     // clear values copied from knownAttributes
       
   273                     desiredAttributes[j].pValue = null;
       
   274                 }
       
   275                 try {
       
   276                     session.token.p11.C_GetAttributeValue
       
   277                             (session.id(), keyID, desiredAttributes);
       
   278                 } catch (PKCS11Exception e) {
       
   279                     throw new ProviderException(e);
       
   280                 }
       
   281                 break; // break loop, goto return
       
   282             }
       
   283         }
       
   284         return desiredAttributes;
       
   285     }
       
   286 
       
   287     static SecretKey secretKey(Session session, long keyID, String algorithm,
       
   288             int keyLength, CK_ATTRIBUTE[] attributes) {
       
   289         attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
       
   290             new CK_ATTRIBUTE(CKA_TOKEN),
       
   291             new CK_ATTRIBUTE(CKA_SENSITIVE),
       
   292             new CK_ATTRIBUTE(CKA_EXTRACTABLE),
       
   293         });
       
   294         return new P11SecretKey(session, keyID, algorithm, keyLength, attributes);
       
   295     }
       
   296 
       
   297     static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
       
   298             int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
       
   299         attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
       
   300             new CK_ATTRIBUTE(CKA_TOKEN),
       
   301             new CK_ATTRIBUTE(CKA_SENSITIVE),
       
   302             new CK_ATTRIBUTE(CKA_EXTRACTABLE),
       
   303         });
       
   304         return new P11TlsMasterSecretKey
       
   305                 (session, keyID, algorithm, keyLength, attributes, major, minor);
       
   306     }
       
   307 
       
   308     // we assume that all components of public keys are always accessible
       
   309     static PublicKey publicKey(Session session, long keyID, String algorithm,
       
   310             int keyLength, CK_ATTRIBUTE[] attributes) {
       
   311         switch (algorithm) {
       
   312             case "RSA":
       
   313                 return new P11RSAPublicKey
       
   314                     (session, keyID, algorithm, keyLength, attributes);
       
   315             case "DSA":
       
   316                 return new P11DSAPublicKey
       
   317                     (session, keyID, algorithm, keyLength, attributes);
       
   318             case "DH":
       
   319                 return new P11DHPublicKey
       
   320                     (session, keyID, algorithm, keyLength, attributes);
       
   321             case "EC":
       
   322                 return new P11ECPublicKey
       
   323                     (session, keyID, algorithm, keyLength, attributes);
       
   324             default:
       
   325                 throw new ProviderException
       
   326                     ("Unknown public key algorithm " + algorithm);
       
   327         }
       
   328     }
       
   329 
       
   330     static PrivateKey privateKey(Session session, long keyID, String algorithm,
       
   331             int keyLength, CK_ATTRIBUTE[] attributes) {
       
   332         attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
       
   333             new CK_ATTRIBUTE(CKA_TOKEN),
       
   334             new CK_ATTRIBUTE(CKA_SENSITIVE),
       
   335             new CK_ATTRIBUTE(CKA_EXTRACTABLE),
       
   336         });
       
   337         if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) {
       
   338             return new P11PrivateKey
       
   339                 (session, keyID, algorithm, keyLength, attributes);
       
   340         } else {
       
   341             switch (algorithm) {
       
   342                 case "RSA":
       
   343                     // In order to decide if this is RSA CRT key, we first query
       
   344                     // and see if all extra CRT attributes are available.
       
   345                     CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] {
       
   346                         new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
       
   347                         new CK_ATTRIBUTE(CKA_PRIME_1),
       
   348                         new CK_ATTRIBUTE(CKA_PRIME_2),
       
   349                         new CK_ATTRIBUTE(CKA_EXPONENT_1),
       
   350                         new CK_ATTRIBUTE(CKA_EXPONENT_2),
       
   351                         new CK_ATTRIBUTE(CKA_COEFFICIENT),
       
   352                     };
       
   353                     boolean crtKey;
       
   354                     try {
       
   355                         session.token.p11.C_GetAttributeValue
       
   356                             (session.id(), keyID, attrs2);
       
   357                         crtKey = ((attrs2[0].pValue instanceof byte[]) &&
       
   358                                   (attrs2[1].pValue instanceof byte[]) &&
       
   359                                   (attrs2[2].pValue instanceof byte[]) &&
       
   360                                   (attrs2[3].pValue instanceof byte[]) &&
       
   361                                   (attrs2[4].pValue instanceof byte[]) &&
       
   362                                   (attrs2[5].pValue instanceof byte[])) ;
       
   363                     } catch (PKCS11Exception e) {
       
   364                         // ignore, assume not available
       
   365                         crtKey = false;
       
   366                     }
       
   367                     if (crtKey) {
       
   368                         return new P11RSAPrivateKey
       
   369                                 (session, keyID, algorithm, keyLength, attributes, attrs2);
       
   370                     } else {
       
   371                         return new P11RSAPrivateNonCRTKey
       
   372                                 (session, keyID, algorithm, keyLength, attributes);
       
   373                     }
       
   374                 case "DSA":
       
   375                     return new P11DSAPrivateKey
       
   376                             (session, keyID, algorithm, keyLength, attributes);
       
   377                 case "DH":
       
   378                     return new P11DHPrivateKey
       
   379                             (session, keyID, algorithm, keyLength, attributes);
       
   380                 case "EC":
       
   381                     return new P11ECPrivateKey
       
   382                             (session, keyID, algorithm, keyLength, attributes);
       
   383                 default:
       
   384                     throw new ProviderException
       
   385                             ("Unknown private key algorithm " + algorithm);
       
   386             }
       
   387         }
       
   388     }
       
   389 
       
   390     // class for sensitive and unextractable private keys
       
   391     private static final class P11PrivateKey extends P11Key
       
   392                                                 implements PrivateKey {
       
   393         private static final long serialVersionUID = -2138581185214187615L;
       
   394 
       
   395         P11PrivateKey(Session session, long keyID, String algorithm,
       
   396                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   397             super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
       
   398         }
       
   399         // XXX temporary encoding for serialization purposes
       
   400         public String getFormat() {
       
   401             token.ensureValid();
       
   402             return null;
       
   403         }
       
   404         byte[] getEncodedInternal() {
       
   405             token.ensureValid();
       
   406             return null;
       
   407         }
       
   408     }
       
   409 
       
   410     private static class P11SecretKey extends P11Key implements SecretKey {
       
   411         private static final long serialVersionUID = -7828241727014329084L;
       
   412         private volatile byte[] encoded;
       
   413         P11SecretKey(Session session, long keyID, String algorithm,
       
   414                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   415             super(SECRET, session, keyID, algorithm, keyLength, attributes);
       
   416         }
       
   417         public String getFormat() {
       
   418             token.ensureValid();
       
   419             if (sensitive || (extractable == false)) {
       
   420                 return null;
       
   421             } else {
       
   422                 return "RAW";
       
   423             }
       
   424         }
       
   425         byte[] getEncodedInternal() {
       
   426             token.ensureValid();
       
   427             if (getFormat() == null) {
       
   428                 return null;
       
   429             }
       
   430             byte[] b = encoded;
       
   431             if (b == null) {
       
   432                 synchronized (this) {
       
   433                     b = encoded;
       
   434                     if (b == null) {
       
   435                         Session tempSession = null;
       
   436                         try {
       
   437                             tempSession = token.getOpSession();
       
   438                             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   439                                 new CK_ATTRIBUTE(CKA_VALUE),
       
   440                             };
       
   441                             token.p11.C_GetAttributeValue
       
   442                                 (tempSession.id(), keyID, attributes);
       
   443                             b = attributes[0].getByteArray();
       
   444                         } catch (PKCS11Exception e) {
       
   445                             throw new ProviderException(e);
       
   446                         } finally {
       
   447                             token.releaseSession(tempSession);
       
   448                         }
       
   449                         encoded = b;
       
   450                     }
       
   451                 }
       
   452             }
       
   453             return b;
       
   454         }
       
   455     }
       
   456 
       
   457     @SuppressWarnings("deprecation")
       
   458     private static class P11TlsMasterSecretKey extends P11SecretKey
       
   459             implements TlsMasterSecret {
       
   460         private static final long serialVersionUID = -1318560923770573441L;
       
   461 
       
   462         private final int majorVersion, minorVersion;
       
   463         P11TlsMasterSecretKey(Session session, long keyID, String algorithm,
       
   464                 int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
       
   465             super(session, keyID, algorithm, keyLength, attributes);
       
   466             this.majorVersion = major;
       
   467             this.minorVersion = minor;
       
   468         }
       
   469         public int getMajorVersion() {
       
   470             return majorVersion;
       
   471         }
       
   472 
       
   473         public int getMinorVersion() {
       
   474             return minorVersion;
       
   475         }
       
   476     }
       
   477 
       
   478     // RSA CRT private key
       
   479     private static final class P11RSAPrivateKey extends P11Key
       
   480                 implements RSAPrivateCrtKey {
       
   481         private static final long serialVersionUID = 9215872438913515220L;
       
   482 
       
   483         private BigInteger n, e, d, p, q, pe, qe, coeff;
       
   484         private byte[] encoded;
       
   485         P11RSAPrivateKey(Session session, long keyID, String algorithm,
       
   486                 int keyLength, CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE[] crtAttrs) {
       
   487             super(PRIVATE, session, keyID, algorithm, keyLength, attrs);
       
   488 
       
   489             for (CK_ATTRIBUTE a : crtAttrs) {
       
   490                 if (a.type == CKA_PUBLIC_EXPONENT) {
       
   491                     e = a.getBigInteger();
       
   492                 } else if (a.type == CKA_PRIME_1) {
       
   493                     p = a.getBigInteger();
       
   494                 } else if (a.type == CKA_PRIME_2) {
       
   495                     q = a.getBigInteger();
       
   496                 } else if (a.type == CKA_EXPONENT_1) {
       
   497                     pe = a.getBigInteger();
       
   498                 } else if (a.type == CKA_EXPONENT_2) {
       
   499                     qe = a.getBigInteger();
       
   500                 } else if (a.type == CKA_COEFFICIENT) {
       
   501                     coeff = a.getBigInteger();
       
   502                 }
       
   503             }
       
   504         }
       
   505         private synchronized void fetchValues() {
       
   506             token.ensureValid();
       
   507             if (n != null) {
       
   508                 return;
       
   509             }
       
   510             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   511                 new CK_ATTRIBUTE(CKA_MODULUS),
       
   512                 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
       
   513             };
       
   514             fetchAttributes(attributes);
       
   515             n = attributes[0].getBigInteger();
       
   516             d = attributes[1].getBigInteger();
       
   517         }
       
   518 
       
   519         public String getFormat() {
       
   520             token.ensureValid();
       
   521             return "PKCS#8";
       
   522         }
       
   523         synchronized byte[] getEncodedInternal() {
       
   524             token.ensureValid();
       
   525             if (encoded == null) {
       
   526                 fetchValues();
       
   527                 try {
       
   528                     // XXX make constructor in SunRsaSign provider public
       
   529                     // and call it directly
       
   530                     KeyFactory factory = KeyFactory.getInstance
       
   531                         ("RSA", P11Util.getSunRsaSignProvider());
       
   532                     Key newKey = factory.translateKey(this);
       
   533                     encoded = newKey.getEncoded();
       
   534                 } catch (GeneralSecurityException e) {
       
   535                     throw new ProviderException(e);
       
   536                 }
       
   537             }
       
   538             return encoded;
       
   539         }
       
   540         public BigInteger getModulus() {
       
   541             fetchValues();
       
   542             return n;
       
   543         }
       
   544         public BigInteger getPublicExponent() {
       
   545             return e;
       
   546         }
       
   547         public BigInteger getPrivateExponent() {
       
   548             fetchValues();
       
   549             return d;
       
   550         }
       
   551         public BigInteger getPrimeP() {
       
   552             return p;
       
   553         }
       
   554         public BigInteger getPrimeQ() {
       
   555             return q;
       
   556         }
       
   557         public BigInteger getPrimeExponentP() {
       
   558             return pe;
       
   559         }
       
   560         public BigInteger getPrimeExponentQ() {
       
   561             return qe;
       
   562         }
       
   563         public BigInteger getCrtCoefficient() {
       
   564             return coeff;
       
   565         }
       
   566     }
       
   567 
       
   568     // RSA non-CRT private key
       
   569     private static final class P11RSAPrivateNonCRTKey extends P11Key
       
   570                 implements RSAPrivateKey {
       
   571         private static final long serialVersionUID = 1137764983777411481L;
       
   572 
       
   573         private BigInteger n, d;
       
   574         private byte[] encoded;
       
   575         P11RSAPrivateNonCRTKey(Session session, long keyID, String algorithm,
       
   576                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   577             super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
       
   578         }
       
   579         private synchronized void fetchValues() {
       
   580             token.ensureValid();
       
   581             if (n != null) {
       
   582                 return;
       
   583             }
       
   584             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   585                 new CK_ATTRIBUTE(CKA_MODULUS),
       
   586                 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
       
   587             };
       
   588             fetchAttributes(attributes);
       
   589             n = attributes[0].getBigInteger();
       
   590             d = attributes[1].getBigInteger();
       
   591         }
       
   592         public String getFormat() {
       
   593             token.ensureValid();
       
   594             return "PKCS#8";
       
   595         }
       
   596         synchronized byte[] getEncodedInternal() {
       
   597             token.ensureValid();
       
   598             if (encoded == null) {
       
   599                 fetchValues();
       
   600                 try {
       
   601                     // XXX make constructor in SunRsaSign provider public
       
   602                     // and call it directly
       
   603                     KeyFactory factory = KeyFactory.getInstance
       
   604                         ("RSA", P11Util.getSunRsaSignProvider());
       
   605                     Key newKey = factory.translateKey(this);
       
   606                     encoded = newKey.getEncoded();
       
   607                 } catch (GeneralSecurityException e) {
       
   608                     throw new ProviderException(e);
       
   609                 }
       
   610             }
       
   611             return encoded;
       
   612         }
       
   613         public BigInteger getModulus() {
       
   614             fetchValues();
       
   615             return n;
       
   616         }
       
   617         public BigInteger getPrivateExponent() {
       
   618             fetchValues();
       
   619             return d;
       
   620         }
       
   621     }
       
   622 
       
   623     private static final class P11RSAPublicKey extends P11Key
       
   624                                                 implements RSAPublicKey {
       
   625         private static final long serialVersionUID = -826726289023854455L;
       
   626 
       
   627         private BigInteger n, e;
       
   628         private byte[] encoded;
       
   629         P11RSAPublicKey(Session session, long keyID, String algorithm,
       
   630                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   631             super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
       
   632         }
       
   633         private synchronized void fetchValues() {
       
   634             token.ensureValid();
       
   635             if (n != null) {
       
   636                 return;
       
   637             }
       
   638             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   639                 new CK_ATTRIBUTE(CKA_MODULUS),
       
   640                 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
       
   641             };
       
   642             fetchAttributes(attributes);
       
   643             n = attributes[0].getBigInteger();
       
   644             e = attributes[1].getBigInteger();
       
   645         }
       
   646         public String getFormat() {
       
   647             token.ensureValid();
       
   648             return "X.509";
       
   649         }
       
   650         synchronized byte[] getEncodedInternal() {
       
   651             token.ensureValid();
       
   652             if (encoded == null) {
       
   653                 fetchValues();
       
   654                 try {
       
   655                     encoded = new RSAPublicKeyImpl(n, e).getEncoded();
       
   656                 } catch (InvalidKeyException e) {
       
   657                     throw new ProviderException(e);
       
   658                 }
       
   659             }
       
   660             return encoded;
       
   661         }
       
   662         public BigInteger getModulus() {
       
   663             fetchValues();
       
   664             return n;
       
   665         }
       
   666         public BigInteger getPublicExponent() {
       
   667             fetchValues();
       
   668             return e;
       
   669         }
       
   670         public String toString() {
       
   671             fetchValues();
       
   672             return super.toString() +  "\n  modulus: " + n
       
   673                 + "\n  public exponent: " + e;
       
   674         }
       
   675     }
       
   676 
       
   677     private static final class P11DSAPublicKey extends P11Key
       
   678                                                 implements DSAPublicKey {
       
   679         private static final long serialVersionUID = 5989753793316396637L;
       
   680 
       
   681         private BigInteger y;
       
   682         private DSAParams params;
       
   683         private byte[] encoded;
       
   684         P11DSAPublicKey(Session session, long keyID, String algorithm,
       
   685                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   686             super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
       
   687         }
       
   688         private synchronized void fetchValues() {
       
   689             token.ensureValid();
       
   690             if (y != null) {
       
   691                 return;
       
   692             }
       
   693             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   694                 new CK_ATTRIBUTE(CKA_VALUE),
       
   695                 new CK_ATTRIBUTE(CKA_PRIME),
       
   696                 new CK_ATTRIBUTE(CKA_SUBPRIME),
       
   697                 new CK_ATTRIBUTE(CKA_BASE),
       
   698             };
       
   699             fetchAttributes(attributes);
       
   700             y = attributes[0].getBigInteger();
       
   701             params = new DSAParameterSpec(
       
   702                 attributes[1].getBigInteger(),
       
   703                 attributes[2].getBigInteger(),
       
   704                 attributes[3].getBigInteger()
       
   705             );
       
   706         }
       
   707         public String getFormat() {
       
   708             token.ensureValid();
       
   709             return "X.509";
       
   710         }
       
   711         synchronized byte[] getEncodedInternal() {
       
   712             token.ensureValid();
       
   713             if (encoded == null) {
       
   714                 fetchValues();
       
   715                 try {
       
   716                     Key key = new sun.security.provider.DSAPublicKey
       
   717                             (y, params.getP(), params.getQ(), params.getG());
       
   718                     encoded = key.getEncoded();
       
   719                 } catch (InvalidKeyException e) {
       
   720                     throw new ProviderException(e);
       
   721                 }
       
   722             }
       
   723             return encoded;
       
   724         }
       
   725         public BigInteger getY() {
       
   726             fetchValues();
       
   727             return y;
       
   728         }
       
   729         public DSAParams getParams() {
       
   730             fetchValues();
       
   731             return params;
       
   732         }
       
   733         public String toString() {
       
   734             fetchValues();
       
   735             return super.toString() +  "\n  y: " + y + "\n  p: " + params.getP()
       
   736                 + "\n  q: " + params.getQ() + "\n  g: " + params.getG();
       
   737         }
       
   738     }
       
   739 
       
   740     private static final class P11DSAPrivateKey extends P11Key
       
   741                                                 implements DSAPrivateKey {
       
   742         private static final long serialVersionUID = 3119629997181999389L;
       
   743 
       
   744         private BigInteger x;
       
   745         private DSAParams params;
       
   746         private byte[] encoded;
       
   747         P11DSAPrivateKey(Session session, long keyID, String algorithm,
       
   748                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   749             super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
       
   750         }
       
   751         private synchronized void fetchValues() {
       
   752             token.ensureValid();
       
   753             if (x != null) {
       
   754                 return;
       
   755             }
       
   756             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   757                 new CK_ATTRIBUTE(CKA_VALUE),
       
   758                 new CK_ATTRIBUTE(CKA_PRIME),
       
   759                 new CK_ATTRIBUTE(CKA_SUBPRIME),
       
   760                 new CK_ATTRIBUTE(CKA_BASE),
       
   761             };
       
   762             fetchAttributes(attributes);
       
   763             x = attributes[0].getBigInteger();
       
   764             params = new DSAParameterSpec(
       
   765                 attributes[1].getBigInteger(),
       
   766                 attributes[2].getBigInteger(),
       
   767                 attributes[3].getBigInteger()
       
   768             );
       
   769         }
       
   770         public String getFormat() {
       
   771             token.ensureValid();
       
   772             return "PKCS#8";
       
   773         }
       
   774         synchronized byte[] getEncodedInternal() {
       
   775             token.ensureValid();
       
   776             if (encoded == null) {
       
   777                 fetchValues();
       
   778                 try {
       
   779                     Key key = new sun.security.provider.DSAPrivateKey
       
   780                             (x, params.getP(), params.getQ(), params.getG());
       
   781                     encoded = key.getEncoded();
       
   782                 } catch (InvalidKeyException e) {
       
   783                     throw new ProviderException(e);
       
   784                 }
       
   785             }
       
   786             return encoded;
       
   787         }
       
   788         public BigInteger getX() {
       
   789             fetchValues();
       
   790             return x;
       
   791         }
       
   792         public DSAParams getParams() {
       
   793             fetchValues();
       
   794             return params;
       
   795         }
       
   796     }
       
   797 
       
   798     private static final class P11DHPrivateKey extends P11Key
       
   799                                                 implements DHPrivateKey {
       
   800         private static final long serialVersionUID = -1698576167364928838L;
       
   801 
       
   802         private BigInteger x;
       
   803         private DHParameterSpec params;
       
   804         private byte[] encoded;
       
   805         P11DHPrivateKey(Session session, long keyID, String algorithm,
       
   806                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   807             super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
       
   808         }
       
   809         private synchronized void fetchValues() {
       
   810             token.ensureValid();
       
   811             if (x != null) {
       
   812                 return;
       
   813             }
       
   814             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   815                 new CK_ATTRIBUTE(CKA_VALUE),
       
   816                 new CK_ATTRIBUTE(CKA_PRIME),
       
   817                 new CK_ATTRIBUTE(CKA_BASE),
       
   818             };
       
   819             fetchAttributes(attributes);
       
   820             x = attributes[0].getBigInteger();
       
   821             params = new DHParameterSpec(
       
   822                 attributes[1].getBigInteger(),
       
   823                 attributes[2].getBigInteger()
       
   824             );
       
   825         }
       
   826         public String getFormat() {
       
   827             token.ensureValid();
       
   828             return "PKCS#8";
       
   829         }
       
   830         synchronized byte[] getEncodedInternal() {
       
   831             token.ensureValid();
       
   832             if (encoded == null) {
       
   833                 fetchValues();
       
   834                 try {
       
   835                     DHPrivateKeySpec spec = new DHPrivateKeySpec
       
   836                         (x, params.getP(), params.getG());
       
   837                     KeyFactory kf = KeyFactory.getInstance
       
   838                         ("DH", P11Util.getSunJceProvider());
       
   839                     Key key = kf.generatePrivate(spec);
       
   840                     encoded = key.getEncoded();
       
   841                 } catch (GeneralSecurityException e) {
       
   842                     throw new ProviderException(e);
       
   843                 }
       
   844             }
       
   845             return encoded;
       
   846         }
       
   847         public BigInteger getX() {
       
   848             fetchValues();
       
   849             return x;
       
   850         }
       
   851         public DHParameterSpec getParams() {
       
   852             fetchValues();
       
   853             return params;
       
   854         }
       
   855         public int hashCode() {
       
   856             if (token.isValid() == false) {
       
   857                 return 0;
       
   858             }
       
   859             fetchValues();
       
   860             return Objects.hash(x, params.getP(), params.getG());
       
   861         }
       
   862         public boolean equals(Object obj) {
       
   863             if (this == obj) return true;
       
   864             // equals() should never throw exceptions
       
   865             if (token.isValid() == false) {
       
   866                 return false;
       
   867             }
       
   868             if (!(obj instanceof DHPrivateKey)) {
       
   869                 return false;
       
   870             }
       
   871             fetchValues();
       
   872             DHPrivateKey other = (DHPrivateKey) obj;
       
   873             DHParameterSpec otherParams = other.getParams();
       
   874             return ((this.x.compareTo(other.getX()) == 0) &&
       
   875                     (this.params.getP().compareTo(otherParams.getP()) == 0) &&
       
   876                     (this.params.getG().compareTo(otherParams.getG()) == 0));
       
   877         }
       
   878     }
       
   879 
       
   880     private static final class P11DHPublicKey extends P11Key
       
   881                                                 implements DHPublicKey {
       
   882         static final long serialVersionUID = -598383872153843657L;
       
   883 
       
   884         private BigInteger y;
       
   885         private DHParameterSpec params;
       
   886         private byte[] encoded;
       
   887         P11DHPublicKey(Session session, long keyID, String algorithm,
       
   888                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   889             super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
       
   890         }
       
   891         private synchronized void fetchValues() {
       
   892             token.ensureValid();
       
   893             if (y != null) {
       
   894                 return;
       
   895             }
       
   896             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   897                 new CK_ATTRIBUTE(CKA_VALUE),
       
   898                 new CK_ATTRIBUTE(CKA_PRIME),
       
   899                 new CK_ATTRIBUTE(CKA_BASE),
       
   900             };
       
   901             fetchAttributes(attributes);
       
   902             y = attributes[0].getBigInteger();
       
   903             params = new DHParameterSpec(
       
   904                 attributes[1].getBigInteger(),
       
   905                 attributes[2].getBigInteger()
       
   906             );
       
   907         }
       
   908         public String getFormat() {
       
   909             token.ensureValid();
       
   910             return "X.509";
       
   911         }
       
   912         synchronized byte[] getEncodedInternal() {
       
   913             token.ensureValid();
       
   914             if (encoded == null) {
       
   915                 fetchValues();
       
   916                 try {
       
   917                     DHPublicKeySpec spec = new DHPublicKeySpec
       
   918                         (y, params.getP(), params.getG());
       
   919                     KeyFactory kf = KeyFactory.getInstance
       
   920                         ("DH", P11Util.getSunJceProvider());
       
   921                     Key key = kf.generatePublic(spec);
       
   922                     encoded = key.getEncoded();
       
   923                 } catch (GeneralSecurityException e) {
       
   924                     throw new ProviderException(e);
       
   925                 }
       
   926             }
       
   927             return encoded;
       
   928         }
       
   929         public BigInteger getY() {
       
   930             fetchValues();
       
   931             return y;
       
   932         }
       
   933         public DHParameterSpec getParams() {
       
   934             fetchValues();
       
   935             return params;
       
   936         }
       
   937         public String toString() {
       
   938             fetchValues();
       
   939             return super.toString() +  "\n  y: " + y + "\n  p: " + params.getP()
       
   940                 + "\n  g: " + params.getG();
       
   941         }
       
   942         public int hashCode() {
       
   943             if (token.isValid() == false) {
       
   944                 return 0;
       
   945             }
       
   946             fetchValues();
       
   947             return Objects.hash(y, params.getP(), params.getG());
       
   948         }
       
   949         public boolean equals(Object obj) {
       
   950             if (this == obj) return true;
       
   951             // equals() should never throw exceptions
       
   952             if (token.isValid() == false) {
       
   953                 return false;
       
   954             }
       
   955             if (!(obj instanceof DHPublicKey)) {
       
   956                 return false;
       
   957             }
       
   958             fetchValues();
       
   959             DHPublicKey other = (DHPublicKey) obj;
       
   960             DHParameterSpec otherParams = other.getParams();
       
   961             return ((this.y.compareTo(other.getY()) == 0) &&
       
   962                     (this.params.getP().compareTo(otherParams.getP()) == 0) &&
       
   963                     (this.params.getG().compareTo(otherParams.getG()) == 0));
       
   964         }
       
   965     }
       
   966 
       
   967     private static final class P11ECPrivateKey extends P11Key
       
   968                                                 implements ECPrivateKey {
       
   969         private static final long serialVersionUID = -7786054399510515515L;
       
   970 
       
   971         private BigInteger s;
       
   972         private ECParameterSpec params;
       
   973         private byte[] encoded;
       
   974         P11ECPrivateKey(Session session, long keyID, String algorithm,
       
   975                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
   976             super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
       
   977         }
       
   978         private synchronized void fetchValues() {
       
   979             token.ensureValid();
       
   980             if (s != null) {
       
   981                 return;
       
   982             }
       
   983             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
   984                 new CK_ATTRIBUTE(CKA_VALUE),
       
   985                 new CK_ATTRIBUTE(CKA_EC_PARAMS, params),
       
   986             };
       
   987             fetchAttributes(attributes);
       
   988             s = attributes[0].getBigInteger();
       
   989             try {
       
   990                 params = P11ECKeyFactory.decodeParameters
       
   991                             (attributes[1].getByteArray());
       
   992             } catch (Exception e) {
       
   993                 throw new RuntimeException("Could not parse key values", e);
       
   994             }
       
   995         }
       
   996         public String getFormat() {
       
   997             token.ensureValid();
       
   998             return "PKCS#8";
       
   999         }
       
  1000         synchronized byte[] getEncodedInternal() {
       
  1001             token.ensureValid();
       
  1002             if (encoded == null) {
       
  1003                 fetchValues();
       
  1004                 try {
       
  1005                     Key key = ECUtil.generateECPrivateKey(s, params);
       
  1006                     encoded = key.getEncoded();
       
  1007                 } catch (InvalidKeySpecException e) {
       
  1008                     throw new ProviderException(e);
       
  1009                 }
       
  1010             }
       
  1011             return encoded;
       
  1012         }
       
  1013         public BigInteger getS() {
       
  1014             fetchValues();
       
  1015             return s;
       
  1016         }
       
  1017         public ECParameterSpec getParams() {
       
  1018             fetchValues();
       
  1019             return params;
       
  1020         }
       
  1021     }
       
  1022 
       
  1023     private static final class P11ECPublicKey extends P11Key
       
  1024                                                 implements ECPublicKey {
       
  1025         private static final long serialVersionUID = -6371481375154806089L;
       
  1026 
       
  1027         private ECPoint w;
       
  1028         private ECParameterSpec params;
       
  1029         private byte[] encoded;
       
  1030         P11ECPublicKey(Session session, long keyID, String algorithm,
       
  1031                 int keyLength, CK_ATTRIBUTE[] attributes) {
       
  1032             super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
       
  1033         }
       
  1034         private synchronized void fetchValues() {
       
  1035             token.ensureValid();
       
  1036             if (w != null) {
       
  1037                 return;
       
  1038             }
       
  1039             CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
       
  1040                 new CK_ATTRIBUTE(CKA_EC_POINT),
       
  1041                 new CK_ATTRIBUTE(CKA_EC_PARAMS),
       
  1042             };
       
  1043             fetchAttributes(attributes);
       
  1044 
       
  1045             try {
       
  1046                 params = P11ECKeyFactory.decodeParameters
       
  1047                             (attributes[1].getByteArray());
       
  1048                 byte[] ecKey = attributes[0].getByteArray();
       
  1049 
       
  1050                 // Check whether the X9.63 encoding of an EC point is wrapped
       
  1051                 // in an ASN.1 OCTET STRING
       
  1052                 if (!token.config.getUseEcX963Encoding()) {
       
  1053                     DerValue wECPoint = new DerValue(ecKey);
       
  1054 
       
  1055                     if (wECPoint.getTag() != DerValue.tag_OctetString) {
       
  1056                         throw new IOException("Could not DER decode EC point." +
       
  1057                             " Unexpected tag: " + wECPoint.getTag());
       
  1058                     }
       
  1059                     w = P11ECKeyFactory.decodePoint
       
  1060                         (wECPoint.getDataBytes(), params.getCurve());
       
  1061 
       
  1062                 } else {
       
  1063                     w = P11ECKeyFactory.decodePoint(ecKey, params.getCurve());
       
  1064                 }
       
  1065 
       
  1066             } catch (Exception e) {
       
  1067                 throw new RuntimeException("Could not parse key values", e);
       
  1068             }
       
  1069         }
       
  1070         public String getFormat() {
       
  1071             token.ensureValid();
       
  1072             return "X.509";
       
  1073         }
       
  1074         synchronized byte[] getEncodedInternal() {
       
  1075             token.ensureValid();
       
  1076             if (encoded == null) {
       
  1077                 fetchValues();
       
  1078                 try {
       
  1079                     return ECUtil.x509EncodeECPublicKey(w, params);
       
  1080                 } catch (InvalidKeySpecException e) {
       
  1081                     throw new ProviderException(e);
       
  1082                 }
       
  1083             }
       
  1084             return encoded;
       
  1085         }
       
  1086         public ECPoint getW() {
       
  1087             fetchValues();
       
  1088             return w;
       
  1089         }
       
  1090         public ECParameterSpec getParams() {
       
  1091             fetchValues();
       
  1092             return params;
       
  1093         }
       
  1094         public String toString() {
       
  1095             fetchValues();
       
  1096             return super.toString()
       
  1097                 + "\n  public x coord: " + w.getAffineX()
       
  1098                 + "\n  public y coord: " + w.getAffineY()
       
  1099                 + "\n  parameters: " + params;
       
  1100         }
       
  1101     }
       
  1102 }
       
  1103 
       
  1104 /*
       
  1105  * NOTE: Must use PhantomReference here and not WeakReference
       
  1106  * otherwise the key maybe cleared before other objects which
       
  1107  * still use these keys during finalization such as SSLSocket.
       
  1108  */
       
  1109 final class SessionKeyRef extends PhantomReference<P11Key>
       
  1110     implements Comparable<SessionKeyRef> {
       
  1111     private static ReferenceQueue<P11Key> refQueue =
       
  1112         new ReferenceQueue<P11Key>();
       
  1113     private static Set<SessionKeyRef> refList =
       
  1114         Collections.synchronizedSortedSet(new TreeSet<SessionKeyRef>());
       
  1115 
       
  1116     static ReferenceQueue<P11Key> referenceQueue() {
       
  1117         return refQueue;
       
  1118     }
       
  1119 
       
  1120     private static void drainRefQueueBounded() {
       
  1121         Session sess = null;
       
  1122         Token tkn = null;
       
  1123         while (true) {
       
  1124             SessionKeyRef next = (SessionKeyRef) refQueue.poll();
       
  1125             if (next == null) {
       
  1126                 break;
       
  1127             }
       
  1128 
       
  1129             // If the token is still valid, try to remove the object
       
  1130             if (next.session.token.isValid()) {
       
  1131                 // If this key's token is the same as the previous key, the
       
  1132                 // same session can be used for C_DestroyObject.
       
  1133                 try {
       
  1134                     if (next.session.token != tkn || sess == null) {
       
  1135                         // Release session if not using previous token
       
  1136                         if (tkn != null && sess != null) {
       
  1137                             tkn.releaseSession(sess);
       
  1138                             sess = null;
       
  1139                         }
       
  1140 
       
  1141                         tkn = next.session.token;
       
  1142                         sess = tkn.getOpSession();
       
  1143                     }
       
  1144                     next.disposeNative(sess);
       
  1145                 } catch (PKCS11Exception e) {
       
  1146                     // ignore
       
  1147                 }
       
  1148             }
       
  1149             // Regardless of native results, dispose of java references
       
  1150             next.dispose();
       
  1151         }
       
  1152 
       
  1153         if (tkn != null && sess != null) {
       
  1154             tkn.releaseSession(sess);
       
  1155         }
       
  1156     }
       
  1157 
       
  1158     // handle to the native key
       
  1159     private long keyID;
       
  1160     private Session session;
       
  1161 
       
  1162     SessionKeyRef(P11Key key , long keyID, Session session) {
       
  1163         super(key, refQueue);
       
  1164         this.keyID = keyID;
       
  1165         this.session = session;
       
  1166         this.session.addObject();
       
  1167         refList.add(this);
       
  1168         drainRefQueueBounded();
       
  1169     }
       
  1170 
       
  1171     private void disposeNative(Session s) throws PKCS11Exception {
       
  1172         session.token.p11.C_DestroyObject(s.id(), keyID);
       
  1173     }
       
  1174 
       
  1175     private void dispose() {
       
  1176         refList.remove(this);
       
  1177         this.clear();
       
  1178         session.removeObject();
       
  1179     }
       
  1180 
       
  1181     public int compareTo(SessionKeyRef other) {
       
  1182         if (this.keyID == other.keyID) {
       
  1183             return 0;
       
  1184         } else {
       
  1185             return (this.keyID < other.keyID) ? -1 : 1;
       
  1186         }
       
  1187     }
       
  1188 }