src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java

Print this page
7191662: JCE providers should be located via ServiceLoader
   1 /*
   2  * Copyright (c) 2014, 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 com.oracle.security.ucrypto;
  27 
  28 import java.io.IOException;
  29 import java.util.HashMap;
  30 import java.util.StringTokenizer;
  31 import java.security.*;
  32 import sun.security.action.PutAllAction;
  33 import sun.security.action.GetPropertyAction;
  34 
  35 /**
  36  * OracleUcrypto provider main class.
  37  *
  38  * @since 1.9
  39  */
  40 public final class UcryptoProvider extends Provider {
  41 
  42     private static final long serialVersionUID = 351251234302833L;
  43 
  44     private static boolean DEBUG;
  45     private static HashMap<String, String> provProp;

  46 
  47     static {
  48         try {
  49             DEBUG = Boolean.parseBoolean(AccessController.doPrivileged
  50                 (new GetPropertyAction("com.oracle.security.ucrypto.debug")));
  51 
  52             // cannot use LoadLibraryAction because that would make the native
  53             // library available to the bootclassloader, but we run in the
  54             // extension classloader.


  55             provProp = AccessController.doPrivileged
  56                 (new PrivilegedAction<HashMap<String, String>>() {
  57                     public HashMap<String, String> run() {
  58                         try {





  59                             System.loadLibrary("j2ucrypto");
  60                             String osname = System.getProperty("os.name");
  61                             if (osname.startsWith("SunOS")) {
  62                                 return new HashMap<String, String>();
  63                             } else return null;
  64                         } catch (Error err) {

  65                             return null;
  66                         } catch (SecurityException se) {

  67                             return null;
  68                         }
  69                     }
  70                 });

  71             if (provProp != null) {
  72                 boolean[] result = loadLibraries();
  73                 if (result.length == 2) {
  74                     if (result[0]) { // successfully loaded libmd
  75                         provProp.put("MessageDigest.MD5",
  76                                      "com.oracle.security.ucrypto.NativeDigest$MD5");

  77                         provProp.put("MessageDigest.SHA",
  78                                      "com.oracle.security.ucrypto.NativeDigest$SHA1");
  79                         provProp.put("Alg.Alias.MessageDigest.SHA-1", "SHA");
  80                         provProp.put("Alg.Alias.MessageDigest.SHA1", "SHA");
  81                         provProp.put("MessageDigest.SHA-256",
  82                                      "com.oracle.security.ucrypto.NativeDigest$SHA256");
  83                         provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
  84                         provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.1", "SHA-256");
  85 
  86                         provProp.put("MessageDigest.SHA-384",
  87                                      "com.oracle.security.ucrypto.NativeDigest$SHA384");
  88                         provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
  89                         provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.2", "SHA-384");
  90 
  91                         provProp.put("MessageDigest.SHA-512",
  92                                      "com.oracle.security.ucrypto.NativeDigest$SHA512");
  93                         provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
  94                         provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.3", "SHA-512");
  95 
  96                     }
  97                     if (result[1]) { // successfully loaded libsoftcrypto
  98                         String supportedMechs = getMechList();
  99                         debug("Prov: supported mechs = " + supportedMechs);
 100                         for (UcryptoMech m : UcryptoMech.values()) {
 101                             if (supportedMechs.indexOf(m.name() + ",") != -1) {
 102                                 String[] jceProps = m.jceProperties();
 103                                 // skip unsupported UcryptoMech
 104                                 if (jceProps == null) continue;
 105                                 for (int p = 0; p < jceProps.length; p++) {
 106                                     StringTokenizer st =
 107                                         new StringTokenizer(jceProps[p], ";");
 108                                     if (st.countTokens() != 2) {
 109                                         throw new RuntimeException("Wrong format: " + jceProps[p]);
 110                                     }
 111                                     provProp.put(st.nextToken(), st.nextToken());
 112                                 }
 113                             }
 114                         }
 115                         // NOTE: GCM support is only available since jdk 7
 116                         provProp.put("AlgorithmParameters.GCM",
 117                                      "com.oracle.security.ucrypto.GCMParameters");
 118                     }
 119                 } else {
 120                     debug("Prov: unexpected ucrypto library loading error, got " + result.length);
 121                 }
 122             }
 123         } catch (AccessControlException ace) {

 124             // disable Ucrypto provider
 125             DEBUG = false;
 126             provProp = null;
 127         }
 128     }
 129 






















































































 130     static Provider provider = null;
 131     private static native boolean[] loadLibraries();
 132     private static native String getMechList();
 133 
 134     static void debug(String msg) {
 135         if (DEBUG) {
 136             System.out.println("UCrypto/" + msg);
 137         }
 138     }
 139 
 140     public UcryptoProvider() {
 141         super("OracleUcrypto", 1.9d, "Provider using Oracle Ucrypto API");
 142         if (provProp != null) {
 143             AccessController.doPrivileged(new PutAllAction(this, provProp));



 144         }

 145         if (provider == null) provider = this;
 146     }
 147 
 148     public UcryptoProvider(String configName) {
 149         super("OracleUcrypto", 1.9d, "Provider using Oracle Ucrypto API");
 150         try {
 151             if (provProp != null) {
 152                 HashMap<String, String> customProvProp =
 153                     new HashMap<String, String>(provProp);
 154                 Config c = new Config(configName);





 155                 String[] disabledServices = c.getDisabledServices();
 156                 for (int i = 0; i < disabledServices.length; i++) {
 157                     if (customProvProp.remove(disabledServices[i]) != null) {
 158                         debug("Prov: remove config-disabled service " + disabledServices[i]);
 159                     } else {
 160                         debug("Prov: ignore unsupported config-disabled service " +
 161                               disabledServices[i]);
 162                     }
 163                 }
 164                 AccessController.doPrivileged(new PutAllAction(this, customProvProp));



 165             }
 166         } catch (IOException ioe) { // thrown by Config
 167             throw new UcryptoException("Error parsing Config", ioe);
 168         }
 169         if (provider == null) provider = this;
 170     }
 171 














 172     public boolean equals(Object obj) {
 173         return this == obj;
 174     }
 175 
 176     public int hashCode() {
 177         return System.identityHashCode(this);
 178     }
 179 }
   1 /*
   2  * Copyright (c) 2014, 2015, 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 com.oracle.security.ucrypto;
  27 
  28 import java.io.IOException;
  29 import java.util.*;

  30 import java.security.*;


  31 
  32 /**
  33  * OracleUcrypto provider main class.
  34  *
  35  * @since 1.9
  36  */
  37 public final class UcryptoProvider extends Provider {
  38 
  39     private static final long serialVersionUID = 351251234302833L;
  40 
  41     private static boolean DEBUG = false;
  42     private static HashMap<String, ServiceDesc> provProp = null;
  43     private static String defConfigName = "";
  44 
  45     static {
  46         try {



  47             // cannot use LoadLibraryAction because that would make the native
  48             // library available to the bootclassloader, but we run in the
  49             // extension classloader.
  50             String osname = System.getProperty("os.name");
  51             if (osname.startsWith("SunOS")) {
  52                 provProp = AccessController.doPrivileged
  53                     (new PrivilegedAction<HashMap<String, ServiceDesc>>() {
  54                         public HashMap<String, ServiceDesc> run() {
  55                             try {
  56                                 DEBUG = Boolean.parseBoolean(System.getProperty("com.oracle.security.ucrypto.debug"));
  57                                 String javaHome = System.getProperty("java.home");
  58                                 String sep = System.getProperty("file.separator");
  59                                 defConfigName = javaHome + sep + "conf" + sep + "security" + sep +
  60                                     "ucrypto-solaris.cfg";
  61                                 System.loadLibrary("j2ucrypto");
  62                                 return new HashMap<>();



  63                             } catch (Error err) {
  64                                 if (DEBUG) err.printStackTrace();
  65                                 return null;
  66                             } catch (SecurityException se) {
  67                                 if (DEBUG) se.printStackTrace();
  68                                 return null;
  69                             }
  70                         }
  71                     });
  72             }
  73             if (provProp != null) {
  74                 boolean[] result = loadLibraries();
  75                 if (result.length == 2) {
  76                     if (result[0]) { // successfully loaded libmd
  77                         provProp.put("MessageDigest.MD5",
  78                             sd("MessageDigest", "MD5",
  79                                "com.oracle.security.ucrypto.NativeDigest$MD5"));
  80                         provProp.put("MessageDigest.SHA",
  81                             sd("MessageDigest", "SHA",
  82                                "com.oracle.security.ucrypto.NativeDigest$SHA1",
  83                                "SHA-1", "SHA1"));
  84                         provProp.put("MessageDigest.SHA-256",
  85                             sd("MessageDigest", "SHA-256",
  86                                "com.oracle.security.ucrypto.NativeDigest$SHA256",
  87                                "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"));
  88 
  89                         provProp.put("MessageDigest.SHA-384",
  90                             sd("MessageDigest", "SHA-384",
  91                                "com.oracle.security.ucrypto.NativeDigest$SHA384",
  92                                "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"));
  93 
  94                         provProp.put("MessageDigest.SHA-512",
  95                             sd("MessageDigest", "SHA-512",
  96                                "com.oracle.security.ucrypto.NativeDigest$SHA512",
  97                                "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"));
  98                     };

  99                     if (result[1]) { // successfully loaded libsoftcrypto
 100                         String supportedMechs = getMechList();
 101                         debug("Prov: supported mechs = " + supportedMechs);
 102                         for (UcryptoMech m : UcryptoMech.values()) {
 103                             if (supportedMechs.indexOf(m.name() + ",") != -1) {
 104                                 ServiceDesc[] services = m.getServiceDescriptions();
 105                                 // skip unsupported UcryptoMech
 106                                 if (services == null || services.length == 0) continue;
 107                                 for (int p = 0; p < services.length; p++) {
 108                                     ServiceDesc entry = services[p];
 109                                     provProp.put(entry.getType() + "." + entry.getAlgorithm(),
 110                                                  entry);

 111                                 }

 112                             }
 113                         }

 114                         // NOTE: GCM support is only available since jdk 7
 115                         provProp.put("AlgorithmParameters.GCM",
 116                                      sd("AlgorithmParameters", "GCM", "com.oracle.security.ucrypto.GCMParameters"));
 117                     }
 118                 } else {
 119                     debug("Prov: unexpected ucrypto library loading error, got " + result.length);
 120                 }
 121             }
 122         } catch (AccessControlException ace) {
 123             if (DEBUG) ace.printStackTrace();
 124             // disable Ucrypto provider

 125             provProp = null;
 126         }
 127     }
 128 
 129     private static ServiceDesc sd(String type, String algo, String cn,
 130         String... aliases) {
 131         return new ServiceDesc(type, algo, cn, aliases);
 132     }
 133 
 134     private static final class ProviderService extends Provider.Service {
 135         ProviderService(Provider p, ServiceDesc sd) {
 136             super(p, sd.getType(), sd.getAlgorithm(), sd.getClassName(),
 137                   sd.getAliases(), null);
 138         }
 139 
 140         @Override
 141         public Object newInstance(Object ctrParamObj)
 142             throws NoSuchAlgorithmException {
 143             String type = getType();
 144             if (ctrParamObj != null) {
 145                 throw new InvalidParameterException
 146                     ("constructorParameter not used with " + type + " engines");
 147             }
 148             String algo = getAlgorithm();
 149             try {
 150                 if (type.equals("Cipher")) {
 151                     int keySize = -1;
 152                     if (algo.charAt(3) == '_') {
 153                         keySize = Integer.parseInt(algo.substring(4, 7))/8;
 154                         algo = algo.substring(0, 3) + algo.substring(7);
 155                     }
 156                     if (algo.equals("AES/ECB/NoPadding")) {
 157                         return new NativeCipher.AesEcbNoPadding(keySize);
 158                     } else if (algo.equals("AES/ECB/PKCS5Padding")) {
 159                         return new NativeCipherWithJavaPadding.AesEcbPKCS5();
 160                     } else if (algo.equals("AES/CBC/NoPadding")) {
 161                         return new NativeCipher.AesCbcNoPadding(keySize);
 162                     } else if (algo.equals("AES/CBC/PKCS5Padding")) {
 163                         return new NativeCipherWithJavaPadding.AesCbcPKCS5();
 164                     } else if (algo.equals("AES/CTR/NoPadding")) {
 165                         return new NativeCipher.AesCtrNoPadding();
 166                     } else if (algo.equals("AES/GCM/NoPadding")) {
 167                         return new NativeGCMCipher.AesGcmNoPadding(keySize);
 168                     } else if (algo.equals("AES/CFB128/NoPadding")) {
 169                         return new NativeCipher.AesCfb128NoPadding();
 170                     } else if (algo.equals("AES/CFB128/PKCS5Padding")) {
 171                         return new NativeCipherWithJavaPadding.AesCfb128PKCS5();
 172                     } else if (algo.equals("RSA/ECB/NoPadding")) {
 173                         return new NativeRSACipher.NoPadding();
 174                     } else if (algo.equals("RSA/ECB/PKCS1Padding")) {
 175                         return new NativeRSACipher.PKCS1Padding();
 176                     }
 177                 } else if (type.equals("Signature")) {
 178                     if (algo.equals("SHA1withRSA")) {
 179                         return new NativeRSASignature.SHA1();
 180                     } else if (algo.equals("SHA256withRSA")) {
 181                         return new NativeRSASignature.SHA256();
 182                     } else if (algo.equals("SHA384withRSA")) {
 183                         return new NativeRSASignature.SHA384();
 184                     } else if (algo.equals("SHA512withRSA")) {
 185                         return new NativeRSASignature.SHA512();
 186                     } else if (algo.equals("MD5withRSA")) {
 187                         return new NativeRSASignature.MD5();
 188                     }
 189                 } else if (type.equals("MessageDigest")) {
 190                     if (algo.equals("SHA")) {
 191                         return new NativeDigest.SHA1();
 192                     } else if (algo.equals("SHA-256")) {
 193                         return new NativeDigest.SHA256();
 194                     } else if (algo.equals("SHA-384")) {
 195                         return new NativeDigest.SHA384();
 196                     } else if (algo.equals("SHA-512")) {
 197                         return new NativeDigest.SHA512();
 198                     } else if (algo.equals("MD5")) {
 199                         return new NativeDigest.MD5();
 200                     }
 201                 } else if (type.equals("AlgorithmParameters")) {
 202                     if (algo.equals("GCM")) {
 203                         return new GCMParameters();
 204                     }
 205                 }
 206             } catch (Exception ex) {
 207                 throw new NoSuchAlgorithmException("Error constructing " +
 208                     type + " for " + algo + " using OracleUcrypto", ex);
 209             }
 210             throw new ProviderException("No impl for " + algo +
 211                 " " + type);
 212         }
 213     }
 214 
 215     static Provider provider = null;
 216     private static native boolean[] loadLibraries();
 217     private static native String getMechList();
 218 
 219     static void debug(String msg) {
 220         if (DEBUG) {
 221             System.out.println("UCrypto/" + msg);
 222         }
 223     }
 224 
 225     public UcryptoProvider() {
 226         super("OracleUcrypto", 1.9d, "Provider using Oracle Ucrypto API");
 227 
 228         AccessController.doPrivileged(new PrivilegedAction<>() {
 229             public Void run() {
 230                 init(defConfigName);
 231                 return null;
 232             }
 233         });
 234         if (provider == null) provider = this;
 235     }
 236 
 237     private void init(final String configName) {


 238         if (provProp != null) {
 239             debug("Prov: configuration file " + configName);
 240             Config c;
 241             try {
 242                 c = new Config(configName);
 243             } catch (Exception ex) {
 244                 throw new UcryptoException("Error parsing Config", ex);
 245             }
 246 
 247             String[] disabledServices = c.getDisabledServices();
 248             for (String ds : disabledServices) {
 249                 if (provProp.remove(ds) != null) {
 250                     debug("Prov: remove config-disabled service " + ds);
 251                 } else {
 252                     debug("Prov: ignore unsupported service " + ds);

 253                 }
 254             }
 255 
 256             for (ServiceDesc s: provProp.values()) {
 257                 debug("Prov: add service for " + s);
 258                 putService(new ProviderService(this, s));
 259             }


 260         }

 261     }
 262 
 263     @Override
 264     public Provider configure(String configArg) throws InvalidParameterException {
 265         if (!defConfigName.equals(configArg)) {
 266             throw new InvalidParameterException("Ucrypto provider can only be " +
 267                 "configured with default configuration file");
 268         }
 269         return this;
 270     }
 271     
 272     @Override
 273     public String getArgument() {
 274         return defConfigName;
 275     }
 276 
 277     public boolean equals(Object obj) {
 278         return this == obj;
 279     }
 280 
 281     public int hashCode() {
 282         return System.identityHashCode(this);
 283     }
 284 }