jdk/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
changeset 43248 5e15de85a1a0
parent 42693 6645de32a866
child 44545 83b611b88ac8
equal deleted inserted replaced
43247:8d242299a219 43248:5e15de85a1a0
       
     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.util.*;
       
    30 
       
    31 import java.security.*;
       
    32 import java.security.interfaces.*;
       
    33 
       
    34 import javax.crypto.interfaces.*;
       
    35 
       
    36 import javax.security.auth.Subject;
       
    37 import javax.security.auth.login.LoginException;
       
    38 import javax.security.auth.login.FailedLoginException;
       
    39 import javax.security.auth.callback.Callback;
       
    40 import javax.security.auth.callback.CallbackHandler;
       
    41 import javax.security.auth.callback.ConfirmationCallback;
       
    42 import javax.security.auth.callback.PasswordCallback;
       
    43 import javax.security.auth.callback.TextOutputCallback;
       
    44 
       
    45 import sun.security.util.Debug;
       
    46 import sun.security.util.ResourcesMgr;
       
    47 import static sun.security.util.SecurityConstants.PROVIDER_VER;
       
    48 
       
    49 import sun.security.pkcs11.Secmod.*;
       
    50 
       
    51 import sun.security.pkcs11.wrapper.*;
       
    52 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
       
    53 
       
    54 /**
       
    55  * PKCS#11 provider main class.
       
    56  *
       
    57  * @author  Andreas Sterbenz
       
    58  * @since   1.5
       
    59  */
       
    60 public final class SunPKCS11 extends AuthProvider {
       
    61 
       
    62     private static final long serialVersionUID = -1354835039035306505L;
       
    63 
       
    64     static final Debug debug = Debug.getInstance("sunpkcs11");
       
    65 
       
    66     // the PKCS11 object through which we make the native calls
       
    67     final PKCS11 p11;
       
    68 
       
    69     // configuration information
       
    70     final Config config;
       
    71 
       
    72     // id of the PKCS#11 slot we are using
       
    73     final long slotID;
       
    74 
       
    75     private CallbackHandler pHandler;
       
    76     private final Object LOCK_HANDLER = new Object();
       
    77 
       
    78     final boolean removable;
       
    79 
       
    80     final Module nssModule;
       
    81 
       
    82     final boolean nssUseSecmodTrust;
       
    83 
       
    84     private volatile Token token;
       
    85 
       
    86     private TokenPoller poller;
       
    87 
       
    88     Token getToken() {
       
    89         return token;
       
    90     }
       
    91 
       
    92     public SunPKCS11() {
       
    93         super("SunPKCS11", PROVIDER_VER,
       
    94             "Unconfigured and unusable PKCS11 provider");
       
    95         p11 = null;
       
    96         config = null;
       
    97         slotID = 0;
       
    98         pHandler = null;
       
    99         removable = false;
       
   100         nssModule = null;
       
   101         nssUseSecmodTrust = false;
       
   102         token = null;
       
   103         poller = null;
       
   104     }
       
   105 
       
   106     @Override
       
   107     public Provider configure(String configArg) throws InvalidParameterException {
       
   108         final String newConfigName = checkNull(configArg);
       
   109         try {
       
   110             return AccessController.doPrivileged(new PrivilegedExceptionAction<>() {
       
   111                 @Override
       
   112                 public SunPKCS11 run() throws Exception {
       
   113                     return new SunPKCS11(new Config(newConfigName));
       
   114                 }
       
   115             });
       
   116         } catch (PrivilegedActionException pae) {
       
   117             InvalidParameterException ipe =
       
   118                 new InvalidParameterException("Error configuring SunPKCS11 provider");
       
   119             throw (InvalidParameterException) ipe.initCause(pae.getException());
       
   120         }
       
   121     }
       
   122 
       
   123     @Override
       
   124     public boolean isConfigured() {
       
   125         return (config != null);
       
   126     }
       
   127 
       
   128     private static <T> T checkNull(T obj) {
       
   129         if (obj == null) {
       
   130             throw new NullPointerException();
       
   131         }
       
   132         return obj;
       
   133     }
       
   134 
       
   135     // Used by Secmod
       
   136     SunPKCS11(Config c) {
       
   137         super("SunPKCS11-" + c.getName(), PROVIDER_VER, c.getDescription());
       
   138         this.config = c;
       
   139 
       
   140         if (debug != null) {
       
   141             System.out.println("SunPKCS11 loading " + config.getFileName());
       
   142         }
       
   143 
       
   144         String library = config.getLibrary();
       
   145         String functionList = config.getFunctionList();
       
   146         long slotID = config.getSlotID();
       
   147         int slotListIndex = config.getSlotListIndex();
       
   148 
       
   149         boolean useSecmod = config.getNssUseSecmod();
       
   150         boolean nssUseSecmodTrust = config.getNssUseSecmodTrust();
       
   151         Module nssModule = null;
       
   152 
       
   153         //
       
   154         // Initialization via Secmod. The way this works is as follows:
       
   155         // SunPKCS11 is either in normal mode or in NSS Secmod mode.
       
   156         // Secmod is activated by specifying one or more of the following
       
   157         // options in the config file:
       
   158         // nssUseSecmod, nssSecmodDirectory, nssLibrary, nssModule
       
   159         //
       
   160         // XXX add more explanation here
       
   161         //
       
   162         // If we are in Secmod mode and configured to use either the
       
   163         // nssKeyStore or the nssTrustAnchors module, we automatically
       
   164         // switch to using the NSS trust attributes for trusted certs
       
   165         // (KeyStore).
       
   166         //
       
   167 
       
   168         if (useSecmod) {
       
   169             // note: Config ensures library/slot/slotListIndex not specified
       
   170             // in secmod mode.
       
   171             Secmod secmod = Secmod.getInstance();
       
   172             DbMode nssDbMode = config.getNssDbMode();
       
   173             try {
       
   174                 String nssLibraryDirectory = config.getNssLibraryDirectory();
       
   175                 String nssSecmodDirectory = config.getNssSecmodDirectory();
       
   176                 boolean nssOptimizeSpace = config.getNssOptimizeSpace();
       
   177 
       
   178                 if (secmod.isInitialized()) {
       
   179                     if (nssSecmodDirectory != null) {
       
   180                         String s = secmod.getConfigDir();
       
   181                         if ((s != null) &&
       
   182                                 (s.equals(nssSecmodDirectory) == false)) {
       
   183                             throw new ProviderException("Secmod directory "
       
   184                                 + nssSecmodDirectory
       
   185                                 + " invalid, NSS already initialized with "
       
   186                                 + s);
       
   187                         }
       
   188                     }
       
   189                     if (nssLibraryDirectory != null) {
       
   190                         String s = secmod.getLibDir();
       
   191                         if ((s != null) &&
       
   192                                 (s.equals(nssLibraryDirectory) == false)) {
       
   193                             throw new ProviderException("NSS library directory "
       
   194                                 + nssLibraryDirectory
       
   195                                 + " invalid, NSS already initialized with "
       
   196                                 + s);
       
   197                         }
       
   198                     }
       
   199                 } else {
       
   200                     if (nssDbMode != DbMode.NO_DB) {
       
   201                         if (nssSecmodDirectory == null) {
       
   202                             throw new ProviderException(
       
   203                                 "Secmod not initialized and "
       
   204                                  + "nssSecmodDirectory not specified");
       
   205                         }
       
   206                     } else {
       
   207                         if (nssSecmodDirectory != null) {
       
   208                             throw new ProviderException(
       
   209                                 "nssSecmodDirectory must not be "
       
   210                                 + "specified in noDb mode");
       
   211                         }
       
   212                     }
       
   213                     secmod.initialize(nssDbMode, nssSecmodDirectory,
       
   214                         nssLibraryDirectory, nssOptimizeSpace);
       
   215                 }
       
   216             } catch (IOException e) {
       
   217                 // XXX which exception to throw
       
   218                 throw new ProviderException("Could not initialize NSS", e);
       
   219             }
       
   220             List<Module> modules = secmod.getModules();
       
   221             if (config.getShowInfo()) {
       
   222                 System.out.println("NSS modules: " + modules);
       
   223             }
       
   224 
       
   225             String moduleName = config.getNssModule();
       
   226             if (moduleName == null) {
       
   227                 nssModule = secmod.getModule(ModuleType.FIPS);
       
   228                 if (nssModule != null) {
       
   229                     moduleName = "fips";
       
   230                 } else {
       
   231                     moduleName = (nssDbMode == DbMode.NO_DB) ?
       
   232                         "crypto" : "keystore";
       
   233                 }
       
   234             }
       
   235             if (moduleName.equals("fips")) {
       
   236                 nssModule = secmod.getModule(ModuleType.FIPS);
       
   237                 nssUseSecmodTrust = true;
       
   238                 functionList = "FC_GetFunctionList";
       
   239             } else if (moduleName.equals("keystore")) {
       
   240                 nssModule = secmod.getModule(ModuleType.KEYSTORE);
       
   241                 nssUseSecmodTrust = true;
       
   242             } else if (moduleName.equals("crypto")) {
       
   243                 nssModule = secmod.getModule(ModuleType.CRYPTO);
       
   244             } else if (moduleName.equals("trustanchors")) {
       
   245                 // XXX should the option be called trustanchor or trustanchors??
       
   246                 nssModule = secmod.getModule(ModuleType.TRUSTANCHOR);
       
   247                 nssUseSecmodTrust = true;
       
   248             } else if (moduleName.startsWith("external-")) {
       
   249                 int moduleIndex;
       
   250                 try {
       
   251                     moduleIndex = Integer.parseInt
       
   252                             (moduleName.substring("external-".length()));
       
   253                 } catch (NumberFormatException e) {
       
   254                     moduleIndex = -1;
       
   255                 }
       
   256                 if (moduleIndex < 1) {
       
   257                     throw new ProviderException
       
   258                             ("Invalid external module: " + moduleName);
       
   259                 }
       
   260                 int k = 0;
       
   261                 for (Module module : modules) {
       
   262                     if (module.getType() == ModuleType.EXTERNAL) {
       
   263                         if (++k == moduleIndex) {
       
   264                             nssModule = module;
       
   265                             break;
       
   266                         }
       
   267                     }
       
   268                 }
       
   269                 if (nssModule == null) {
       
   270                     throw new ProviderException("Invalid module " + moduleName
       
   271                         + ": only " + k + " external NSS modules available");
       
   272                 }
       
   273             } else {
       
   274                 throw new ProviderException(
       
   275                     "Unknown NSS module: " + moduleName);
       
   276             }
       
   277             if (nssModule == null) {
       
   278                 throw new ProviderException(
       
   279                     "NSS module not available: " + moduleName);
       
   280             }
       
   281             if (nssModule.hasInitializedProvider()) {
       
   282                 throw new ProviderException("Secmod module already configured");
       
   283             }
       
   284             library = nssModule.libraryName;
       
   285             slotListIndex = nssModule.slot;
       
   286         }
       
   287         this.nssUseSecmodTrust = nssUseSecmodTrust;
       
   288         this.nssModule = nssModule;
       
   289 
       
   290         File libraryFile = new File(library);
       
   291         // if the filename is a simple filename without path
       
   292         // (e.g. "libpkcs11.so"), it may refer to a library somewhere on the
       
   293         // OS library search path. Omit the test for file existance as that
       
   294         // only looks in the current directory.
       
   295         if (libraryFile.getName().equals(library) == false) {
       
   296             if (new File(library).isFile() == false) {
       
   297                 String msg = "Library " + library + " does not exist";
       
   298                 if (config.getHandleStartupErrors() == Config.ERR_HALT) {
       
   299                     throw new ProviderException(msg);
       
   300                 } else {
       
   301                     throw new UnsupportedOperationException(msg);
       
   302                 }
       
   303             }
       
   304         }
       
   305 
       
   306         try {
       
   307             if (debug != null) {
       
   308                 debug.println("Initializing PKCS#11 library " + library);
       
   309             }
       
   310             CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();
       
   311             String nssArgs = config.getNssArgs();
       
   312             if (nssArgs != null) {
       
   313                 initArgs.pReserved = nssArgs;
       
   314             }
       
   315             // request multithreaded access first
       
   316             initArgs.flags = CKF_OS_LOCKING_OK;
       
   317             PKCS11 tmpPKCS11;
       
   318             try {
       
   319                 tmpPKCS11 = PKCS11.getInstance(
       
   320                     library, functionList, initArgs,
       
   321                     config.getOmitInitialize());
       
   322             } catch (PKCS11Exception e) {
       
   323                 if (debug != null) {
       
   324                     debug.println("Multi-threaded initialization failed: " + e);
       
   325                 }
       
   326                 if (config.getAllowSingleThreadedModules() == false) {
       
   327                     throw e;
       
   328                 }
       
   329                 // fall back to single threaded access
       
   330                 if (nssArgs == null) {
       
   331                     // if possible, use null initArgs for better compatibility
       
   332                     initArgs = null;
       
   333                 } else {
       
   334                     initArgs.flags = 0;
       
   335                 }
       
   336                 tmpPKCS11 = PKCS11.getInstance(library,
       
   337                     functionList, initArgs, config.getOmitInitialize());
       
   338             }
       
   339             p11 = tmpPKCS11;
       
   340 
       
   341             CK_INFO p11Info = p11.C_GetInfo();
       
   342             if (p11Info.cryptokiVersion.major < 2) {
       
   343                 throw new ProviderException("Only PKCS#11 v2.0 and later "
       
   344                 + "supported, library version is v" + p11Info.cryptokiVersion);
       
   345             }
       
   346             boolean showInfo = config.getShowInfo();
       
   347             if (showInfo) {
       
   348                 System.out.println("Information for provider " + getName());
       
   349                 System.out.println("Library info:");
       
   350                 System.out.println(p11Info);
       
   351             }
       
   352 
       
   353             if ((slotID < 0) || showInfo) {
       
   354                 long[] slots = p11.C_GetSlotList(false);
       
   355                 if (showInfo) {
       
   356                     System.out.println("All slots: " + toString(slots));
       
   357                     slots = p11.C_GetSlotList(true);
       
   358                     System.out.println("Slots with tokens: " + toString(slots));
       
   359                 }
       
   360                 if (slotID < 0) {
       
   361                     if ((slotListIndex < 0)
       
   362                             || (slotListIndex >= slots.length)) {
       
   363                         throw new ProviderException("slotListIndex is "
       
   364                             + slotListIndex
       
   365                             + " but token only has " + slots.length + " slots");
       
   366                     }
       
   367                     slotID = slots[slotListIndex];
       
   368                 }
       
   369             }
       
   370             this.slotID = slotID;
       
   371             CK_SLOT_INFO slotInfo = p11.C_GetSlotInfo(slotID);
       
   372             removable = (slotInfo.flags & CKF_REMOVABLE_DEVICE) != 0;
       
   373             initToken(slotInfo);
       
   374             if (nssModule != null) {
       
   375                 nssModule.setProvider(this);
       
   376             }
       
   377         } catch (Exception e) {
       
   378             if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) {
       
   379                 throw new UnsupportedOperationException
       
   380                         ("Initialization failed", e);
       
   381             } else {
       
   382                 throw new ProviderException
       
   383                         ("Initialization failed", e);
       
   384             }
       
   385         }
       
   386     }
       
   387 
       
   388     private static String toString(long[] longs) {
       
   389         if (longs.length == 0) {
       
   390             return "(none)";
       
   391         }
       
   392         StringBuilder sb = new StringBuilder();
       
   393         sb.append(longs[0]);
       
   394         for (int i = 1; i < longs.length; i++) {
       
   395             sb.append(", ");
       
   396             sb.append(longs[i]);
       
   397         }
       
   398         return sb.toString();
       
   399     }
       
   400 
       
   401     public boolean equals(Object obj) {
       
   402         return this == obj;
       
   403     }
       
   404 
       
   405     public int hashCode() {
       
   406         return System.identityHashCode(this);
       
   407     }
       
   408 
       
   409     private static String[] s(String ...aliases) {
       
   410         return aliases;
       
   411     }
       
   412 
       
   413     private static final class Descriptor {
       
   414         final String type;
       
   415         final String algorithm;
       
   416         final String className;
       
   417         final String[] aliases;
       
   418         final int[] mechanisms;
       
   419 
       
   420         private Descriptor(String type, String algorithm, String className,
       
   421                 String[] aliases, int[] mechanisms) {
       
   422             this.type = type;
       
   423             this.algorithm = algorithm;
       
   424             this.className = className;
       
   425             this.aliases = aliases;
       
   426             this.mechanisms = mechanisms;
       
   427         }
       
   428         private P11Service service(Token token, int mechanism) {
       
   429             return new P11Service
       
   430                 (token, type, algorithm, className, aliases, mechanism);
       
   431         }
       
   432         public String toString() {
       
   433             return type + "." + algorithm;
       
   434         }
       
   435     }
       
   436 
       
   437     // Map from mechanism to List of Descriptors that should be
       
   438     // registered if the mechanism is supported
       
   439     private final static Map<Integer,List<Descriptor>> descriptors =
       
   440         new HashMap<Integer,List<Descriptor>>();
       
   441 
       
   442     private static int[] m(long m1) {
       
   443         return new int[] {(int)m1};
       
   444     }
       
   445 
       
   446     private static int[] m(long m1, long m2) {
       
   447         return new int[] {(int)m1, (int)m2};
       
   448     }
       
   449 
       
   450     private static int[] m(long m1, long m2, long m3) {
       
   451         return new int[] {(int)m1, (int)m2, (int)m3};
       
   452     }
       
   453 
       
   454     private static int[] m(long m1, long m2, long m3, long m4) {
       
   455         return new int[] {(int)m1, (int)m2, (int)m3, (int)m4};
       
   456     }
       
   457 
       
   458     private static void d(String type, String algorithm, String className,
       
   459             int[] m) {
       
   460         register(new Descriptor(type, algorithm, className, null, m));
       
   461     }
       
   462 
       
   463     private static void d(String type, String algorithm, String className,
       
   464             String[] aliases, int[] m) {
       
   465         register(new Descriptor(type, algorithm, className, aliases, m));
       
   466     }
       
   467 
       
   468     private static void register(Descriptor d) {
       
   469         for (int i = 0; i < d.mechanisms.length; i++) {
       
   470             int m = d.mechanisms[i];
       
   471             Integer key = Integer.valueOf(m);
       
   472             List<Descriptor> list = descriptors.get(key);
       
   473             if (list == null) {
       
   474                 list = new ArrayList<Descriptor>();
       
   475                 descriptors.put(key, list);
       
   476             }
       
   477             list.add(d);
       
   478         }
       
   479     }
       
   480 
       
   481     private final static String MD  = "MessageDigest";
       
   482 
       
   483     private final static String SIG = "Signature";
       
   484 
       
   485     private final static String KPG = "KeyPairGenerator";
       
   486 
       
   487     private final static String KG  = "KeyGenerator";
       
   488 
       
   489     private final static String AGP = "AlgorithmParameters";
       
   490 
       
   491     private final static String KF  = "KeyFactory";
       
   492 
       
   493     private final static String SKF = "SecretKeyFactory";
       
   494 
       
   495     private final static String CIP = "Cipher";
       
   496 
       
   497     private final static String MAC = "Mac";
       
   498 
       
   499     private final static String KA  = "KeyAgreement";
       
   500 
       
   501     private final static String KS  = "KeyStore";
       
   502 
       
   503     private final static String SR  = "SecureRandom";
       
   504 
       
   505     static {
       
   506         // names of all the implementation classes
       
   507         // use local variables, only used here
       
   508         String P11Digest           = "sun.security.pkcs11.P11Digest";
       
   509         String P11MAC              = "sun.security.pkcs11.P11MAC";
       
   510         String P11KeyPairGenerator = "sun.security.pkcs11.P11KeyPairGenerator";
       
   511         String P11KeyGenerator     = "sun.security.pkcs11.P11KeyGenerator";
       
   512         String P11RSAKeyFactory    = "sun.security.pkcs11.P11RSAKeyFactory";
       
   513         String P11DSAKeyFactory    = "sun.security.pkcs11.P11DSAKeyFactory";
       
   514         String P11DHKeyFactory     = "sun.security.pkcs11.P11DHKeyFactory";
       
   515         String P11KeyAgreement     = "sun.security.pkcs11.P11KeyAgreement";
       
   516         String P11SecretKeyFactory = "sun.security.pkcs11.P11SecretKeyFactory";
       
   517         String P11Cipher           = "sun.security.pkcs11.P11Cipher";
       
   518         String P11RSACipher        = "sun.security.pkcs11.P11RSACipher";
       
   519         String P11Signature        = "sun.security.pkcs11.P11Signature";
       
   520 
       
   521         // XXX register all aliases
       
   522 
       
   523         d(MD, "MD2",            P11Digest,
       
   524                 m(CKM_MD2));
       
   525         d(MD, "MD5",            P11Digest,
       
   526                 m(CKM_MD5));
       
   527         d(MD, "SHA1",           P11Digest,
       
   528                 s("SHA", "SHA-1", "1.3.14.3.2.26", "OID.1.3.14.3.2.26"),
       
   529                 m(CKM_SHA_1));
       
   530 
       
   531         d(MD, "SHA-224",        P11Digest,
       
   532                 s("2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4"),
       
   533                 m(CKM_SHA224));
       
   534         d(MD, "SHA-256",        P11Digest,
       
   535                 s("2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"),
       
   536                 m(CKM_SHA256));
       
   537         d(MD, "SHA-384",        P11Digest,
       
   538                 s("2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"),
       
   539                 m(CKM_SHA384));
       
   540         d(MD, "SHA-512",        P11Digest,
       
   541                 s("2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"),
       
   542                 m(CKM_SHA512));
       
   543 
       
   544         d(MAC, "HmacMD5",       P11MAC,
       
   545                 m(CKM_MD5_HMAC));
       
   546         d(MAC, "HmacSHA1",      P11MAC,
       
   547                 s("1.2.840.113549.2.7", "OID.1.2.840.113549.2.7"),
       
   548                 m(CKM_SHA_1_HMAC));
       
   549         d(MAC, "HmacSHA224",    P11MAC,
       
   550                 s("1.2.840.113549.2.8", "OID.1.2.840.113549.2.8"),
       
   551                 m(CKM_SHA224_HMAC));
       
   552         d(MAC, "HmacSHA256",    P11MAC,
       
   553                 s("1.2.840.113549.2.9", "OID.1.2.840.113549.2.9"),
       
   554                 m(CKM_SHA256_HMAC));
       
   555         d(MAC, "HmacSHA384",    P11MAC,
       
   556                 s("1.2.840.113549.2.10", "OID.1.2.840.113549.2.10"),
       
   557                 m(CKM_SHA384_HMAC));
       
   558         d(MAC, "HmacSHA512",    P11MAC,
       
   559                 s("1.2.840.113549.2.11", "OID.1.2.840.113549.2.11"),
       
   560                 m(CKM_SHA512_HMAC));
       
   561         d(MAC, "SslMacMD5",     P11MAC,
       
   562                 m(CKM_SSL3_MD5_MAC));
       
   563         d(MAC, "SslMacSHA1",    P11MAC,
       
   564                 m(CKM_SSL3_SHA1_MAC));
       
   565 
       
   566         d(KPG, "RSA",           P11KeyPairGenerator,
       
   567                 m(CKM_RSA_PKCS_KEY_PAIR_GEN));
       
   568         d(KPG, "DSA",           P11KeyPairGenerator,
       
   569                 s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),
       
   570                 m(CKM_DSA_KEY_PAIR_GEN));
       
   571         d(KPG, "DH",            P11KeyPairGenerator,    s("DiffieHellman"),
       
   572                 m(CKM_DH_PKCS_KEY_PAIR_GEN));
       
   573         d(KPG, "EC",            P11KeyPairGenerator,
       
   574                 m(CKM_EC_KEY_PAIR_GEN));
       
   575 
       
   576         d(KG,  "ARCFOUR",       P11KeyGenerator,        s("RC4"),
       
   577                 m(CKM_RC4_KEY_GEN));
       
   578         d(KG,  "DES",           P11KeyGenerator,
       
   579                 m(CKM_DES_KEY_GEN));
       
   580         d(KG,  "DESede",        P11KeyGenerator,
       
   581                 m(CKM_DES3_KEY_GEN, CKM_DES2_KEY_GEN));
       
   582         d(KG,  "AES",           P11KeyGenerator,
       
   583                 m(CKM_AES_KEY_GEN));
       
   584         d(KG,  "Blowfish",      P11KeyGenerator,
       
   585                 m(CKM_BLOWFISH_KEY_GEN));
       
   586 
       
   587         // register (Secret)KeyFactories if there are any mechanisms
       
   588         // for a particular algorithm that we support
       
   589         d(KF, "RSA",            P11RSAKeyFactory,
       
   590                 m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));
       
   591         d(KF, "DSA",            P11DSAKeyFactory,
       
   592                 s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),
       
   593                 m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));
       
   594         d(KF, "DH",             P11DHKeyFactory,        s("DiffieHellman"),
       
   595                 m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
       
   596         d(KF, "EC",             P11DHKeyFactory,
       
   597                 m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
       
   598                     CKM_ECDSA, CKM_ECDSA_SHA1));
       
   599 
       
   600         // AlgorithmParameters for EC.
       
   601         // Only needed until we have an EC implementation in the SUN provider.
       
   602         d(AGP, "EC",            "sun.security.util.ECParameters",
       
   603                                                 s("1.2.840.10045.2.1"),
       
   604                 m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
       
   605                     CKM_ECDSA, CKM_ECDSA_SHA1));
       
   606 
       
   607         d(KA, "DH",             P11KeyAgreement,        s("DiffieHellman"),
       
   608                 m(CKM_DH_PKCS_DERIVE));
       
   609         d(KA, "ECDH",           "sun.security.pkcs11.P11ECDHKeyAgreement",
       
   610                 m(CKM_ECDH1_DERIVE));
       
   611 
       
   612         d(SKF, "ARCFOUR",       P11SecretKeyFactory,    s("RC4"),
       
   613                 m(CKM_RC4));
       
   614         d(SKF, "DES",           P11SecretKeyFactory,
       
   615                 m(CKM_DES_CBC));
       
   616         d(SKF, "DESede",        P11SecretKeyFactory,
       
   617                 m(CKM_DES3_CBC));
       
   618         d(SKF, "AES",           P11SecretKeyFactory,
       
   619                 s("2.16.840.1.101.3.4.1", "OID.2.16.840.1.101.3.4.1"),
       
   620                 m(CKM_AES_CBC));
       
   621         d(SKF, "Blowfish",      P11SecretKeyFactory,
       
   622                 m(CKM_BLOWFISH_CBC));
       
   623 
       
   624         // XXX attributes for Ciphers (supported modes, padding)
       
   625         d(CIP, "ARCFOUR",                       P11Cipher,      s("RC4"),
       
   626                 m(CKM_RC4));
       
   627         d(CIP, "DES/CBC/NoPadding",             P11Cipher,
       
   628                 m(CKM_DES_CBC));
       
   629         d(CIP, "DES/CBC/PKCS5Padding",          P11Cipher,
       
   630                 m(CKM_DES_CBC_PAD, CKM_DES_CBC));
       
   631         d(CIP, "DES/ECB/NoPadding",             P11Cipher,
       
   632                 m(CKM_DES_ECB));
       
   633         d(CIP, "DES/ECB/PKCS5Padding",          P11Cipher,      s("DES"),
       
   634                 m(CKM_DES_ECB));
       
   635 
       
   636         d(CIP, "DESede/CBC/NoPadding",          P11Cipher,
       
   637                 m(CKM_DES3_CBC));
       
   638         d(CIP, "DESede/CBC/PKCS5Padding",       P11Cipher,
       
   639                 m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));
       
   640         d(CIP, "DESede/ECB/NoPadding",          P11Cipher,
       
   641                 m(CKM_DES3_ECB));
       
   642         d(CIP, "DESede/ECB/PKCS5Padding",       P11Cipher,      s("DESede"),
       
   643                 m(CKM_DES3_ECB));
       
   644         d(CIP, "AES/CBC/NoPadding",             P11Cipher,
       
   645                 m(CKM_AES_CBC));
       
   646         d(CIP, "AES_128/CBC/NoPadding",          P11Cipher,
       
   647                 s("2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),
       
   648                 m(CKM_AES_CBC));
       
   649         d(CIP, "AES_192/CBC/NoPadding",          P11Cipher,
       
   650                 s("2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),
       
   651                 m(CKM_AES_CBC));
       
   652         d(CIP, "AES_256/CBC/NoPadding",          P11Cipher,
       
   653                 s("2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42"),
       
   654                 m(CKM_AES_CBC));
       
   655         d(CIP, "AES/CBC/PKCS5Padding",          P11Cipher,
       
   656                 m(CKM_AES_CBC_PAD, CKM_AES_CBC));
       
   657         d(CIP, "AES/ECB/NoPadding",             P11Cipher,
       
   658                 m(CKM_AES_ECB));
       
   659         d(CIP, "AES_128/ECB/NoPadding",          P11Cipher,
       
   660                 s("2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),
       
   661                 m(CKM_AES_ECB));
       
   662         d(CIP, "AES_192/ECB/NoPadding",          P11Cipher,
       
   663                 s("2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),
       
   664                 m(CKM_AES_ECB));
       
   665         d(CIP, "AES_256/ECB/NoPadding",          P11Cipher,
       
   666                 s("2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41"),
       
   667                 m(CKM_AES_ECB));
       
   668         d(CIP, "AES/ECB/PKCS5Padding",          P11Cipher,      s("AES"),
       
   669                 m(CKM_AES_ECB));
       
   670         d(CIP, "AES/CTR/NoPadding",             P11Cipher,
       
   671                 m(CKM_AES_CTR));
       
   672         d(CIP, "Blowfish/CBC/NoPadding",        P11Cipher,
       
   673                 m(CKM_BLOWFISH_CBC));
       
   674         d(CIP, "Blowfish/CBC/PKCS5Padding",     P11Cipher,
       
   675                 m(CKM_BLOWFISH_CBC));
       
   676 
       
   677         // XXX RSA_X_509, RSA_OAEP not yet supported
       
   678         d(CIP, "RSA/ECB/PKCS1Padding",          P11RSACipher,   s("RSA"),
       
   679                 m(CKM_RSA_PKCS));
       
   680         d(CIP, "RSA/ECB/NoPadding",             P11RSACipher,
       
   681                 m(CKM_RSA_X_509));
       
   682 
       
   683         d(SIG, "RawDSA",        P11Signature,   s("NONEwithDSA"),
       
   684                 m(CKM_DSA));
       
   685         d(SIG, "DSA",           P11Signature,
       
   686                 s("SHA1withDSA", "1.3.14.3.2.13", "1.3.14.3.2.27",
       
   687                   "1.2.840.10040.4.3", "OID.1.2.840.10040.4.3"),
       
   688                 m(CKM_DSA_SHA1, CKM_DSA));
       
   689         d(SIG, "RawDSAinP1363Format",   P11Signature,
       
   690                 s("NONEwithDSAinP1363Format"),
       
   691                 m(CKM_DSA));
       
   692         d(SIG, "DSAinP1363Format",      P11Signature,
       
   693                 s("SHA1withDSAinP1363Format"),
       
   694                 m(CKM_DSA_SHA1, CKM_DSA));
       
   695         d(SIG, "NONEwithECDSA", P11Signature,
       
   696                 m(CKM_ECDSA));
       
   697         d(SIG, "SHA1withECDSA", P11Signature,
       
   698                 s("ECDSA", "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1"),
       
   699                 m(CKM_ECDSA_SHA1, CKM_ECDSA));
       
   700         d(SIG, "SHA224withECDSA",       P11Signature,
       
   701                 s("1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"),
       
   702                 m(CKM_ECDSA));
       
   703         d(SIG, "SHA256withECDSA",       P11Signature,
       
   704                 s("1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"),
       
   705                 m(CKM_ECDSA));
       
   706         d(SIG, "SHA384withECDSA",       P11Signature,
       
   707                 s("1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3"),
       
   708                 m(CKM_ECDSA));
       
   709         d(SIG, "SHA512withECDSA",       P11Signature,
       
   710                 s("1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4"),
       
   711                 m(CKM_ECDSA));
       
   712         d(SIG, "NONEwithECDSAinP1363Format",   P11Signature,
       
   713                 m(CKM_ECDSA));
       
   714         d(SIG, "SHA1withECDSAinP1363Format",   P11Signature,
       
   715                 m(CKM_ECDSA_SHA1, CKM_ECDSA));
       
   716         d(SIG, "SHA224withECDSAinP1363Format", P11Signature,
       
   717                 m(CKM_ECDSA));
       
   718         d(SIG, "SHA256withECDSAinP1363Format", P11Signature,
       
   719                 m(CKM_ECDSA));
       
   720         d(SIG, "SHA384withECDSAinP1363Format", P11Signature,
       
   721                 m(CKM_ECDSA));
       
   722         d(SIG, "SHA512withECDSAinP1363Format", P11Signature,
       
   723                 m(CKM_ECDSA));
       
   724         d(SIG, "MD2withRSA",    P11Signature,
       
   725                 s("1.2.840.113549.1.1.2", "OID.1.2.840.113549.1.1.2"),
       
   726                 m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
       
   727         d(SIG, "MD5withRSA",    P11Signature,
       
   728                 s("1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4"),
       
   729                 m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
       
   730         d(SIG, "SHA1withRSA",   P11Signature,
       
   731                 s("1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",
       
   732                   "1.3.14.3.2.29"),
       
   733                 m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
       
   734         d(SIG, "SHA224withRSA", P11Signature,
       
   735                 s("1.2.840.113549.1.1.14", "OID.1.2.840.113549.1.1.14"),
       
   736                 m(CKM_SHA224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
       
   737         d(SIG, "SHA256withRSA", P11Signature,
       
   738                 s("1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11"),
       
   739                 m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
       
   740         d(SIG, "SHA384withRSA", P11Signature,
       
   741                 s("1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12"),
       
   742                 m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
       
   743         d(SIG, "SHA512withRSA", P11Signature,
       
   744                 s("1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13"),
       
   745                 m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
       
   746 
       
   747         /*
       
   748          * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the
       
   749          * PRF calculations.  As of 2010, there is no PKCS11-level
       
   750          * support for TLS 1.2 PRF calculations, and no known OS's have
       
   751          * an internal variant we could use.  Therefore for TLS 1.2, we
       
   752          * are updating JSSE to request different provider algorithms
       
   753          * (e.g. "SunTls12Prf"), and currently only SunJCE has these
       
   754          * TLS 1.2 algorithms.
       
   755          *
       
   756          * If we reused the names such as "SunTlsPrf", the PKCS11
       
   757          * providers would need be updated to fail correctly when
       
   758          * presented with the wrong version number (via
       
   759          * Provider.Service.supportsParameters()), and we would also
       
   760          * need to add the appropriate supportsParamters() checks into
       
   761          * KeyGenerators (not currently there).
       
   762          *
       
   763          * In the future, if PKCS11 support is added, we will restructure
       
   764          * this.
       
   765          */
       
   766         d(KG, "SunTlsRsaPremasterSecret",
       
   767                     "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
       
   768                 m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
       
   769         d(KG, "SunTlsMasterSecret",
       
   770                     "sun.security.pkcs11.P11TlsMasterSecretGenerator",
       
   771                 m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,
       
   772                     CKM_SSL3_MASTER_KEY_DERIVE_DH,
       
   773                     CKM_TLS_MASTER_KEY_DERIVE_DH));
       
   774         d(KG, "SunTlsKeyMaterial",
       
   775                     "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
       
   776                 m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));
       
   777         d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",
       
   778                 m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));
       
   779     }
       
   780 
       
   781     // background thread that periodically checks for token insertion
       
   782     // if no token is present. We need to do that in a separate thread because
       
   783     // the insertion check may block for quite a long time on some tokens.
       
   784     private static class TokenPoller implements Runnable {
       
   785         private final SunPKCS11 provider;
       
   786         private volatile boolean enabled;
       
   787         private TokenPoller(SunPKCS11 provider) {
       
   788             this.provider = provider;
       
   789             enabled = true;
       
   790         }
       
   791         public void run() {
       
   792             int interval = provider.config.getInsertionCheckInterval();
       
   793             while (enabled) {
       
   794                 try {
       
   795                     Thread.sleep(interval);
       
   796                 } catch (InterruptedException e) {
       
   797                     break;
       
   798                 }
       
   799                 if (enabled == false) {
       
   800                     break;
       
   801                 }
       
   802                 try {
       
   803                     provider.initToken(null);
       
   804                 } catch (PKCS11Exception e) {
       
   805                     // ignore
       
   806                 }
       
   807             }
       
   808         }
       
   809         void disable() {
       
   810             enabled = false;
       
   811         }
       
   812     }
       
   813 
       
   814     // create the poller thread, if not already active
       
   815     private void createPoller() {
       
   816         if (poller != null) {
       
   817             return;
       
   818         }
       
   819         final TokenPoller poller = new TokenPoller(this);
       
   820         Thread t = new Thread(null, poller, "Poller " + getName(), 0, false);
       
   821         t.setContextClassLoader(null);
       
   822         t.setDaemon(true);
       
   823         t.setPriority(Thread.MIN_PRIORITY);
       
   824         t.start();
       
   825         this.poller = poller;
       
   826     }
       
   827 
       
   828     // destroy the poller thread, if active
       
   829     private void destroyPoller() {
       
   830         if (poller != null) {
       
   831             poller.disable();
       
   832             poller = null;
       
   833         }
       
   834     }
       
   835 
       
   836     private boolean hasValidToken() {
       
   837         /* Commented out to work with Solaris softtoken impl which
       
   838            returns 0-value flags, e.g. both REMOVABLE_DEVICE and
       
   839            TOKEN_PRESENT are false, when it can't access the token.
       
   840         if (removable == false) {
       
   841             return true;
       
   842         }
       
   843         */
       
   844         Token token = this.token;
       
   845         return (token != null) && token.isValid();
       
   846     }
       
   847 
       
   848     // destroy the token. Called if we detect that it has been removed
       
   849     synchronized void uninitToken(Token token) {
       
   850         if (this.token != token) {
       
   851             // mismatch, our token must already be destroyed
       
   852             return;
       
   853         }
       
   854         destroyPoller();
       
   855         this.token = null;
       
   856         // unregister all algorithms
       
   857         AccessController.doPrivileged(new PrivilegedAction<Object>() {
       
   858             public Object run() {
       
   859                 clear();
       
   860                 return null;
       
   861             }
       
   862         });
       
   863         createPoller();
       
   864     }
       
   865 
       
   866     // test if a token is present and initialize this provider for it if so.
       
   867     // does nothing if no token is found
       
   868     // called from constructor and by poller
       
   869     private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
       
   870         if (slotInfo == null) {
       
   871             slotInfo = p11.C_GetSlotInfo(slotID);
       
   872         }
       
   873         if (removable && (slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
       
   874             createPoller();
       
   875             return;
       
   876         }
       
   877         destroyPoller();
       
   878         boolean showInfo = config.getShowInfo();
       
   879         if (showInfo) {
       
   880             System.out.println("Slot info for slot " + slotID + ":");
       
   881             System.out.println(slotInfo);
       
   882         }
       
   883         final Token token = new Token(this);
       
   884         if (showInfo) {
       
   885             System.out.println
       
   886                 ("Token info for token in slot " + slotID + ":");
       
   887             System.out.println(token.tokenInfo);
       
   888         }
       
   889         long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
       
   890 
       
   891         // Create a map from the various Descriptors to the "most
       
   892         // preferred" mechanism that was defined during the
       
   893         // static initialization.  For example, DES/CBC/PKCS5Padding
       
   894         // could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC.  Prefer
       
   895         // the earliest entry.  When asked for "DES/CBC/PKCS5Padding", we
       
   896         // return a CKM_DES_CBC_PAD.
       
   897         final Map<Descriptor,Integer> supportedAlgs =
       
   898                                         new HashMap<Descriptor,Integer>();
       
   899         for (int i = 0; i < supportedMechanisms.length; i++) {
       
   900             long longMech = supportedMechanisms[i];
       
   901             boolean isEnabled = config.isEnabled(longMech);
       
   902             if (showInfo) {
       
   903                 CK_MECHANISM_INFO mechInfo =
       
   904                         p11.C_GetMechanismInfo(slotID, longMech);
       
   905                 System.out.println("Mechanism " +
       
   906                         Functions.getMechanismName(longMech) + ":");
       
   907                 if (isEnabled == false) {
       
   908                     System.out.println("DISABLED in configuration");
       
   909                 }
       
   910                 System.out.println(mechInfo);
       
   911             }
       
   912             if (isEnabled == false) {
       
   913                 continue;
       
   914             }
       
   915             // we do not know of mechs with the upper 32 bits set
       
   916             if (longMech >>> 32 != 0) {
       
   917                 continue;
       
   918             }
       
   919             int mech = (int)longMech;
       
   920             Integer integerMech = Integer.valueOf(mech);
       
   921             List<Descriptor> ds = descriptors.get(integerMech);
       
   922             if (ds == null) {
       
   923                 continue;
       
   924             }
       
   925             for (Descriptor d : ds) {
       
   926                 Integer oldMech = supportedAlgs.get(d);
       
   927                 if (oldMech == null) {
       
   928                     supportedAlgs.put(d, integerMech);
       
   929                     continue;
       
   930                 }
       
   931                 // See if there is something "more preferred"
       
   932                 // than what we currently have in the supportedAlgs
       
   933                 // map.
       
   934                 int intOldMech = oldMech.intValue();
       
   935                 for (int j = 0; j < d.mechanisms.length; j++) {
       
   936                     int nextMech = d.mechanisms[j];
       
   937                     if (mech == nextMech) {
       
   938                         supportedAlgs.put(d, integerMech);
       
   939                         break;
       
   940                     } else if (intOldMech == nextMech) {
       
   941                         break;
       
   942                     }
       
   943                 }
       
   944             }
       
   945 
       
   946         }
       
   947 
       
   948         // register algorithms in provider
       
   949         AccessController.doPrivileged(new PrivilegedAction<Object>() {
       
   950             public Object run() {
       
   951                 for (Map.Entry<Descriptor,Integer> entry
       
   952                         : supportedAlgs.entrySet()) {
       
   953                     Descriptor d = entry.getKey();
       
   954                     int mechanism = entry.getValue().intValue();
       
   955                     Service s = d.service(token, mechanism);
       
   956                     putService(s);
       
   957                 }
       
   958                 if (((token.tokenInfo.flags & CKF_RNG) != 0)
       
   959                         && config.isEnabled(PCKM_SECURERANDOM)
       
   960                         && !token.sessionManager.lowMaxSessions()) {
       
   961                     // do not register SecureRandom if the token does
       
   962                     // not support many sessions. if we did, we might
       
   963                     // run out of sessions in the middle of a
       
   964                     // nextBytes() call where we cannot fail over.
       
   965                     putService(new P11Service(token, SR, "PKCS11",
       
   966                         "sun.security.pkcs11.P11SecureRandom", null,
       
   967                         PCKM_SECURERANDOM));
       
   968                 }
       
   969                 if (config.isEnabled(PCKM_KEYSTORE)) {
       
   970                     putService(new P11Service(token, KS, "PKCS11",
       
   971                         "sun.security.pkcs11.P11KeyStore",
       
   972                         s("PKCS11-" + config.getName()),
       
   973                         PCKM_KEYSTORE));
       
   974                 }
       
   975                 return null;
       
   976             }
       
   977         });
       
   978 
       
   979         this.token = token;
       
   980     }
       
   981 
       
   982     private static final class P11Service extends Service {
       
   983 
       
   984         private final Token token;
       
   985 
       
   986         private final long mechanism;
       
   987 
       
   988         P11Service(Token token, String type, String algorithm,
       
   989                 String className, String[] al, long mechanism) {
       
   990             super(token.provider, type, algorithm, className, toList(al),
       
   991                     type.equals(SR) ? Map.of("ThreadSafe", "true") : null);
       
   992             this.token = token;
       
   993             this.mechanism = mechanism & 0xFFFFFFFFL;
       
   994         }
       
   995 
       
   996         private static List<String> toList(String[] aliases) {
       
   997             return (aliases == null) ? null : Arrays.asList(aliases);
       
   998         }
       
   999 
       
  1000         public Object newInstance(Object param)
       
  1001                 throws NoSuchAlgorithmException {
       
  1002             if (token.isValid() == false) {
       
  1003                 throw new NoSuchAlgorithmException("Token has been removed");
       
  1004             }
       
  1005             try {
       
  1006                 return newInstance0(param);
       
  1007             } catch (PKCS11Exception e) {
       
  1008                 throw new NoSuchAlgorithmException(e);
       
  1009             }
       
  1010         }
       
  1011 
       
  1012         public Object newInstance0(Object param) throws
       
  1013                 PKCS11Exception, NoSuchAlgorithmException {
       
  1014             String algorithm = getAlgorithm();
       
  1015             String type = getType();
       
  1016             if (type == MD) {
       
  1017                 return new P11Digest(token, algorithm, mechanism);
       
  1018             } else if (type == CIP) {
       
  1019                 if (algorithm.startsWith("RSA")) {
       
  1020                     return new P11RSACipher(token, algorithm, mechanism);
       
  1021                 } else {
       
  1022                     return new P11Cipher(token, algorithm, mechanism);
       
  1023                 }
       
  1024             } else if (type == SIG) {
       
  1025                 return new P11Signature(token, algorithm, mechanism);
       
  1026             } else if (type == MAC) {
       
  1027                 return new P11Mac(token, algorithm, mechanism);
       
  1028             } else if (type == KPG) {
       
  1029                 return new P11KeyPairGenerator(token, algorithm, mechanism);
       
  1030             } else if (type == KA) {
       
  1031                 if (algorithm.equals("ECDH")) {
       
  1032                     return new P11ECDHKeyAgreement(token, algorithm, mechanism);
       
  1033                 } else {
       
  1034                     return new P11KeyAgreement(token, algorithm, mechanism);
       
  1035                 }
       
  1036             } else if (type == KF) {
       
  1037                 return token.getKeyFactory(algorithm);
       
  1038             } else if (type == SKF) {
       
  1039                 return new P11SecretKeyFactory(token, algorithm);
       
  1040             } else if (type == KG) {
       
  1041                 // reference equality
       
  1042                 if (algorithm == "SunTlsRsaPremasterSecret") {
       
  1043                     return new P11TlsRsaPremasterSecretGenerator(
       
  1044                         token, algorithm, mechanism);
       
  1045                 } else if (algorithm == "SunTlsMasterSecret") {
       
  1046                     return new P11TlsMasterSecretGenerator(
       
  1047                         token, algorithm, mechanism);
       
  1048                 } else if (algorithm == "SunTlsKeyMaterial") {
       
  1049                     return new P11TlsKeyMaterialGenerator(
       
  1050                         token, algorithm, mechanism);
       
  1051                 } else if (algorithm == "SunTlsPrf") {
       
  1052                     return new P11TlsPrfGenerator(token, algorithm, mechanism);
       
  1053                 } else {
       
  1054                     return new P11KeyGenerator(token, algorithm, mechanism);
       
  1055                 }
       
  1056             } else if (type == SR) {
       
  1057                 return token.getRandom();
       
  1058             } else if (type == KS) {
       
  1059                 return token.getKeyStore();
       
  1060             } else if (type == AGP) {
       
  1061                 return new sun.security.util.ECParameters();
       
  1062             } else {
       
  1063                 throw new NoSuchAlgorithmException("Unknown type: " + type);
       
  1064             }
       
  1065         }
       
  1066 
       
  1067         public boolean supportsParameter(Object param) {
       
  1068             if ((param == null) || (token.isValid() == false)) {
       
  1069                 return false;
       
  1070             }
       
  1071             if (param instanceof Key == false) {
       
  1072                 throw new InvalidParameterException("Parameter must be a Key");
       
  1073             }
       
  1074             String algorithm = getAlgorithm();
       
  1075             String type = getType();
       
  1076             Key key = (Key)param;
       
  1077             String keyAlgorithm = key.getAlgorithm();
       
  1078             // RSA signatures and cipher
       
  1079             if (((type == CIP) && algorithm.startsWith("RSA"))
       
  1080                     || (type == SIG) && algorithm.endsWith("RSA")) {
       
  1081                 if (keyAlgorithm.equals("RSA") == false) {
       
  1082                     return false;
       
  1083                 }
       
  1084                 return isLocalKey(key)
       
  1085                         || (key instanceof RSAPrivateKey)
       
  1086                         || (key instanceof RSAPublicKey);
       
  1087             }
       
  1088             // EC
       
  1089             if (((type == KA) && algorithm.equals("ECDH"))
       
  1090                     || ((type == SIG) && algorithm.contains("ECDSA"))) {
       
  1091                 if (keyAlgorithm.equals("EC") == false) {
       
  1092                     return false;
       
  1093                 }
       
  1094                 return isLocalKey(key)
       
  1095                         || (key instanceof ECPrivateKey)
       
  1096                         || (key instanceof ECPublicKey);
       
  1097             }
       
  1098             // DSA signatures
       
  1099             if ((type == SIG) && algorithm.contains("DSA") &&
       
  1100                     !algorithm.contains("ECDSA")) {
       
  1101                 if (keyAlgorithm.equals("DSA") == false) {
       
  1102                     return false;
       
  1103                 }
       
  1104                 return isLocalKey(key)
       
  1105                         || (key instanceof DSAPrivateKey)
       
  1106                         || (key instanceof DSAPublicKey);
       
  1107             }
       
  1108             // MACs and symmetric ciphers
       
  1109             if ((type == CIP) || (type == MAC)) {
       
  1110                 // do not check algorithm name, mismatch is unlikely anyway
       
  1111                 return isLocalKey(key) || "RAW".equals(key.getFormat());
       
  1112             }
       
  1113             // DH key agreement
       
  1114             if (type == KA) {
       
  1115                 if (keyAlgorithm.equals("DH") == false) {
       
  1116                     return false;
       
  1117                 }
       
  1118                 return isLocalKey(key)
       
  1119                         || (key instanceof DHPrivateKey)
       
  1120                         || (key instanceof DHPublicKey);
       
  1121             }
       
  1122             // should not reach here,
       
  1123             // unknown engine type or algorithm
       
  1124             throw new AssertionError
       
  1125                 ("SunPKCS11 error: " + type + ", " + algorithm);
       
  1126         }
       
  1127 
       
  1128         private boolean isLocalKey(Key key) {
       
  1129             return (key instanceof P11Key) && (((P11Key)key).token == token);
       
  1130         }
       
  1131 
       
  1132         public String toString() {
       
  1133             return super.toString() +
       
  1134                 " (" + Functions.getMechanismName(mechanism) + ")";
       
  1135         }
       
  1136 
       
  1137     }
       
  1138 
       
  1139     /**
       
  1140      * Log in to this provider.
       
  1141      *
       
  1142      * <p> If the token expects a PIN to be supplied by the caller,
       
  1143      * the <code>handler</code> implementation must support
       
  1144      * a <code>PasswordCallback</code>.
       
  1145      *
       
  1146      * <p> To determine if the token supports a protected authentication path,
       
  1147      * the CK_TOKEN_INFO flag, CKF_PROTECTED_AUTHENTICATION_PATH, is consulted.
       
  1148      *
       
  1149      * @param subject this parameter is ignored
       
  1150      * @param handler the <code>CallbackHandler</code> used by
       
  1151      *  this provider to communicate with the caller
       
  1152      *
       
  1153      * @throws IllegalStateException if the provider requires configuration
       
  1154      * and Provider.configure has not been called
       
  1155      * @throws LoginException if the login operation fails
       
  1156      * @throws SecurityException if the does not pass a security check for
       
  1157      *  <code>SecurityPermission("authProvider.<i>name</i>")</code>,
       
  1158      *  where <i>name</i> is the value returned by
       
  1159      *  this provider's <code>getName</code> method
       
  1160      */
       
  1161     public void login(Subject subject, CallbackHandler handler)
       
  1162         throws LoginException {
       
  1163 
       
  1164         if (!isConfigured()) {
       
  1165             throw new IllegalStateException("Configuration is required");
       
  1166         }
       
  1167 
       
  1168         // security check
       
  1169         SecurityManager sm = System.getSecurityManager();
       
  1170         if (sm != null) {
       
  1171             if (debug != null) {
       
  1172                 debug.println("checking login permission");
       
  1173             }
       
  1174             sm.checkPermission(new SecurityPermission
       
  1175                         ("authProvider." + this.getName()));
       
  1176         }
       
  1177 
       
  1178         if (hasValidToken() == false) {
       
  1179             throw new LoginException("No token present");
       
  1180         }
       
  1181 
       
  1182         // see if a login is required
       
  1183 
       
  1184         if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {
       
  1185             if (debug != null) {
       
  1186                 debug.println("login operation not required for token - " +
       
  1187                                 "ignoring login request");
       
  1188             }
       
  1189             return;
       
  1190         }
       
  1191 
       
  1192         // see if user already logged in
       
  1193 
       
  1194         try {
       
  1195             if (token.isLoggedInNow(null)) {
       
  1196                 // user already logged in
       
  1197                 if (debug != null) {
       
  1198                     debug.println("user already logged in");
       
  1199                 }
       
  1200                 return;
       
  1201             }
       
  1202         } catch (PKCS11Exception e) {
       
  1203             // ignore - fall thru and attempt login
       
  1204         }
       
  1205 
       
  1206         // get the pin if necessary
       
  1207 
       
  1208         char[] pin = null;
       
  1209         if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
       
  1210 
       
  1211             // get password
       
  1212 
       
  1213             CallbackHandler myHandler = getCallbackHandler(handler);
       
  1214             if (myHandler == null) {
       
  1215                 // XXX PolicyTool is dependent on this message text
       
  1216                 throw new LoginException
       
  1217                         ("no password provided, and no callback handler " +
       
  1218                         "available for retrieving password");
       
  1219             }
       
  1220 
       
  1221             java.text.MessageFormat form = new java.text.MessageFormat
       
  1222                         (ResourcesMgr.getString
       
  1223                         ("PKCS11.Token.providerName.Password."));
       
  1224             Object[] source = { getName() };
       
  1225 
       
  1226             PasswordCallback pcall = new PasswordCallback(form.format(source),
       
  1227                                                         false);
       
  1228             Callback[] callbacks = { pcall };
       
  1229             try {
       
  1230                 myHandler.handle(callbacks);
       
  1231             } catch (Exception e) {
       
  1232                 LoginException le = new LoginException
       
  1233                         ("Unable to perform password callback");
       
  1234                 le.initCause(e);
       
  1235                 throw le;
       
  1236             }
       
  1237 
       
  1238             pin = pcall.getPassword();
       
  1239             pcall.clearPassword();
       
  1240             if (pin == null) {
       
  1241                 if (debug != null) {
       
  1242                     debug.println("caller passed NULL pin");
       
  1243                 }
       
  1244             }
       
  1245         }
       
  1246 
       
  1247         // perform token login
       
  1248 
       
  1249         Session session = null;
       
  1250         try {
       
  1251             session = token.getOpSession();
       
  1252 
       
  1253             // pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH
       
  1254             p11.C_Login(session.id(), CKU_USER, pin);
       
  1255             if (debug != null) {
       
  1256                 debug.println("login succeeded");
       
  1257             }
       
  1258         } catch (PKCS11Exception pe) {
       
  1259             if (pe.getErrorCode() == CKR_USER_ALREADY_LOGGED_IN) {
       
  1260                 // let this one go
       
  1261                 if (debug != null) {
       
  1262                     debug.println("user already logged in");
       
  1263                 }
       
  1264                 return;
       
  1265             } else if (pe.getErrorCode() == CKR_PIN_INCORRECT) {
       
  1266                 FailedLoginException fle = new FailedLoginException();
       
  1267                 fle.initCause(pe);
       
  1268                 throw fle;
       
  1269             } else {
       
  1270                 LoginException le = new LoginException();
       
  1271                 le.initCause(pe);
       
  1272                 throw le;
       
  1273             }
       
  1274         } finally {
       
  1275             token.releaseSession(session);
       
  1276             if (pin != null) {
       
  1277                 Arrays.fill(pin, ' ');
       
  1278             }
       
  1279         }
       
  1280 
       
  1281         // we do not store the PIN in the subject for now
       
  1282     }
       
  1283 
       
  1284     /**
       
  1285      * Log out from this provider
       
  1286      *
       
  1287      * @throws IllegalStateException if the provider requires configuration
       
  1288      * and Provider.configure has not been called
       
  1289      * @throws LoginException if the logout operation fails
       
  1290      * @throws SecurityException if the does not pass a security check for
       
  1291      *  <code>SecurityPermission("authProvider.<i>name</i>")</code>,
       
  1292      *  where <i>name</i> is the value returned by
       
  1293      *  this provider's <code>getName</code> method
       
  1294      */
       
  1295     public void logout() throws LoginException {
       
  1296 
       
  1297         if (!isConfigured()) {
       
  1298             throw new IllegalStateException("Configuration is required");
       
  1299         }
       
  1300 
       
  1301         // security check
       
  1302         SecurityManager sm = System.getSecurityManager();
       
  1303         if (sm != null) {
       
  1304             sm.checkPermission
       
  1305                 (new SecurityPermission("authProvider." + this.getName()));
       
  1306         }
       
  1307 
       
  1308         if (hasValidToken() == false) {
       
  1309             // app may call logout for cleanup, allow
       
  1310             return;
       
  1311         }
       
  1312 
       
  1313         if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {
       
  1314             if (debug != null) {
       
  1315                 debug.println("logout operation not required for token - " +
       
  1316                                 "ignoring logout request");
       
  1317             }
       
  1318             return;
       
  1319         }
       
  1320 
       
  1321         try {
       
  1322             if (token.isLoggedInNow(null) == false) {
       
  1323                 if (debug != null) {
       
  1324                     debug.println("user not logged in");
       
  1325                 }
       
  1326                 return;
       
  1327             }
       
  1328         } catch (PKCS11Exception e) {
       
  1329             // ignore
       
  1330         }
       
  1331 
       
  1332         // perform token logout
       
  1333 
       
  1334         Session session = null;
       
  1335         try {
       
  1336             session = token.getOpSession();
       
  1337             p11.C_Logout(session.id());
       
  1338             if (debug != null) {
       
  1339                 debug.println("logout succeeded");
       
  1340             }
       
  1341         } catch (PKCS11Exception pe) {
       
  1342             if (pe.getErrorCode() == CKR_USER_NOT_LOGGED_IN) {
       
  1343                 // let this one go
       
  1344                 if (debug != null) {
       
  1345                     debug.println("user not logged in");
       
  1346                 }
       
  1347                 return;
       
  1348             }
       
  1349             LoginException le = new LoginException();
       
  1350             le.initCause(pe);
       
  1351             throw le;
       
  1352         } finally {
       
  1353             token.releaseSession(session);
       
  1354         }
       
  1355     }
       
  1356 
       
  1357     /**
       
  1358      * Set a <code>CallbackHandler</code>
       
  1359      *
       
  1360      * <p> The provider uses this handler if one is not passed to the
       
  1361      * <code>login</code> method.  The provider also uses this handler
       
  1362      * if it invokes <code>login</code> on behalf of callers.
       
  1363      * In either case if a handler is not set via this method,
       
  1364      * the provider queries the
       
  1365      * <i>auth.login.defaultCallbackHandler</i> security property
       
  1366      * for the fully qualified class name of a default handler implementation.
       
  1367      * If the security property is not set,
       
  1368      * the provider is assumed to have alternative means
       
  1369      * for obtaining authentication information.
       
  1370      *
       
  1371      * @param handler a <code>CallbackHandler</code> for obtaining
       
  1372      *          authentication information, which may be <code>null</code>
       
  1373      *
       
  1374      * @throws IllegalStateException if the provider requires configuration
       
  1375      * and Provider.configure has not been called
       
  1376      * @throws SecurityException if the caller does not pass a
       
  1377      *  security check for
       
  1378      *  <code>SecurityPermission("authProvider.<i>name</i>")</code>,
       
  1379      *  where <i>name</i> is the value returned by
       
  1380      *  this provider's <code>getName</code> method
       
  1381      */
       
  1382     public void setCallbackHandler(CallbackHandler handler) {
       
  1383 
       
  1384         if (!isConfigured()) {
       
  1385             throw new IllegalStateException("Configuration is required");
       
  1386         }
       
  1387 
       
  1388         // security check
       
  1389         SecurityManager sm = System.getSecurityManager();
       
  1390         if (sm != null) {
       
  1391             sm.checkPermission
       
  1392                 (new SecurityPermission("authProvider." + this.getName()));
       
  1393         }
       
  1394 
       
  1395         synchronized (LOCK_HANDLER) {
       
  1396             pHandler = handler;
       
  1397         }
       
  1398     }
       
  1399 
       
  1400     private CallbackHandler getCallbackHandler(CallbackHandler handler) {
       
  1401 
       
  1402         // get default handler if necessary
       
  1403 
       
  1404         if (handler != null) {
       
  1405             return handler;
       
  1406         }
       
  1407 
       
  1408         if (debug != null) {
       
  1409             debug.println("getting provider callback handler");
       
  1410         }
       
  1411 
       
  1412         synchronized (LOCK_HANDLER) {
       
  1413             // see if handler was set via setCallbackHandler
       
  1414             if (pHandler != null) {
       
  1415                 return pHandler;
       
  1416             }
       
  1417 
       
  1418             try {
       
  1419                 if (debug != null) {
       
  1420                     debug.println("getting default callback handler");
       
  1421                 }
       
  1422 
       
  1423                 CallbackHandler myHandler = AccessController.doPrivileged
       
  1424                     (new PrivilegedExceptionAction<CallbackHandler>() {
       
  1425                     public CallbackHandler run() throws Exception {
       
  1426 
       
  1427                         String defaultHandler =
       
  1428                                 java.security.Security.getProperty
       
  1429                                 ("auth.login.defaultCallbackHandler");
       
  1430 
       
  1431                         if (defaultHandler == null ||
       
  1432                             defaultHandler.length() == 0) {
       
  1433 
       
  1434                             // ok
       
  1435                             if (debug != null) {
       
  1436                                 debug.println("no default handler set");
       
  1437                             }
       
  1438                             return null;
       
  1439                         }
       
  1440 
       
  1441                         Class<?> c = Class.forName
       
  1442                                    (defaultHandler,
       
  1443                                    true,
       
  1444                                    Thread.currentThread().getContextClassLoader());
       
  1445                         if (!javax.security.auth.callback.CallbackHandler.class.isAssignableFrom(c)) {
       
  1446                             // not the right subtype
       
  1447                             if (debug != null) {
       
  1448                                 debug.println("default handler " + defaultHandler +
       
  1449                                               " is not a CallbackHandler");
       
  1450                             }
       
  1451                             return null;
       
  1452                         }
       
  1453                         @SuppressWarnings("deprecation")
       
  1454                         Object result = c.newInstance();
       
  1455                         return (CallbackHandler)result;
       
  1456                     }
       
  1457                 });
       
  1458                 // save it
       
  1459                 pHandler = myHandler;
       
  1460                 return myHandler;
       
  1461 
       
  1462             } catch (PrivilegedActionException pae) {
       
  1463                 // ok
       
  1464                 if (debug != null) {
       
  1465                     debug.println("Unable to load default callback handler");
       
  1466                     pae.printStackTrace();
       
  1467                 }
       
  1468             }
       
  1469         }
       
  1470         return null;
       
  1471     }
       
  1472 
       
  1473     private Object writeReplace() throws ObjectStreamException {
       
  1474         return new SunPKCS11Rep(this);
       
  1475     }
       
  1476 
       
  1477     /**
       
  1478      * Serialized representation of the SunPKCS11 provider.
       
  1479      */
       
  1480     private static class SunPKCS11Rep implements Serializable {
       
  1481 
       
  1482         static final long serialVersionUID = -2896606995897745419L;
       
  1483 
       
  1484         private final String providerName;
       
  1485 
       
  1486         private final String configName;
       
  1487 
       
  1488         SunPKCS11Rep(SunPKCS11 provider) throws NotSerializableException {
       
  1489             providerName = provider.getName();
       
  1490             configName = provider.config.getFileName();
       
  1491             if (Security.getProvider(providerName) != provider) {
       
  1492                 throw new NotSerializableException("Only SunPKCS11 providers "
       
  1493                     + "installed in java.security.Security can be serialized");
       
  1494             }
       
  1495         }
       
  1496 
       
  1497         private Object readResolve() throws ObjectStreamException {
       
  1498             SunPKCS11 p = (SunPKCS11)Security.getProvider(providerName);
       
  1499             if ((p == null) || (p.config.getFileName().equals(configName) == false)) {
       
  1500                 throw new NotSerializableException("Could not find "
       
  1501                         + providerName + " in installed providers");
       
  1502             }
       
  1503             return p;
       
  1504         }
       
  1505     }
       
  1506 }