jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java
changeset 31270 e6470b24700d
parent 27182 4525d13b8af1
child 33991 619bfc4d582d
equal deleted inserted replaced
31269:14968253ce7e 31270:e6470b24700d
     1 /*
     1 /*
     2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    24  */
    24  */
    25 
    25 
    26 package com.oracle.security.ucrypto;
    26 package com.oracle.security.ucrypto;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.util.HashMap;
    29 import java.io.File;
    30 import java.util.StringTokenizer;
    30 import java.util.*;
    31 import java.security.*;
    31 import java.security.*;
    32 import sun.security.action.PutAllAction;
       
    33 import sun.security.action.GetPropertyAction;
       
    34 
    32 
    35 /**
    33 /**
    36  * OracleUcrypto provider main class.
    34  * OracleUcrypto provider main class.
    37  *
    35  *
    38  * @since 1.9
    36  * @since 1.9
    39  */
    37  */
    40 public final class UcryptoProvider extends Provider {
    38 public final class UcryptoProvider extends Provider {
    41 
    39 
    42     private static final long serialVersionUID = 351251234302833L;
    40     private static final long serialVersionUID = 351251234302833L;
    43 
    41 
    44     private static boolean DEBUG;
    42     private static boolean DEBUG = false;
    45     private static HashMap<String, String> provProp;
    43     private static HashMap<String, ServiceDesc> provProp = null;
       
    44     private static String defConfigName = "";
    46 
    45 
    47     static {
    46     static {
    48         try {
    47         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
    48             // cannot use LoadLibraryAction because that would make the native
    53             // library available to the bootclassloader, but we run in the
    49             // library available to the bootclassloader, but we run in the
    54             // extension classloader.
    50             // extension classloader.
    55             provProp = AccessController.doPrivileged
    51             String osname = System.getProperty("os.name");
    56                 (new PrivilegedAction<HashMap<String, String>>() {
    52             if (osname.startsWith("SunOS")) {
    57                     public HashMap<String, String> run() {
    53                 provProp = AccessController.doPrivileged
    58                         try {
    54                     (new PrivilegedAction<HashMap<String, ServiceDesc>>() {
    59                             System.loadLibrary("j2ucrypto");
    55                         public HashMap<String, ServiceDesc> run() {
    60                             String osname = System.getProperty("os.name");
    56                             try {
    61                             if (osname.startsWith("SunOS")) {
    57                                 DEBUG = Boolean.parseBoolean(System.getProperty("com.oracle.security.ucrypto.debug"));
    62                                 return new HashMap<String, String>();
    58                                 String javaHome = System.getProperty("java.home");
    63                             } else return null;
    59                                 String sep = System.getProperty("file.separator");
    64                         } catch (Error err) {
    60                                 defConfigName = javaHome + sep + "conf" + sep + "security" + sep +
    65                             return null;
    61                                     "ucrypto-solaris.cfg";
    66                         } catch (SecurityException se) {
    62                                 System.loadLibrary("j2ucrypto");
    67                             return null;
    63                                 return new HashMap<>();
       
    64                             } catch (Error err) {
       
    65                                 if (DEBUG) err.printStackTrace();
       
    66                                 return null;
       
    67                             } catch (SecurityException se) {
       
    68                                 if (DEBUG) se.printStackTrace();
       
    69                                 return null;
       
    70                             }
    68                         }
    71                         }
    69                     }
    72                     });
    70                 });
    73             }
    71             if (provProp != null) {
    74             if (provProp != null) {
    72                 boolean[] result = loadLibraries();
    75                 boolean[] result = loadLibraries();
    73                 if (result.length == 2) {
    76                 if (result.length == 2) {
    74                     if (result[0]) { // successfully loaded libmd
    77                     if (result[0]) { // successfully loaded libmd
    75                         provProp.put("MessageDigest.MD5",
    78                         provProp.put("MessageDigest.MD5",
    76                                      "com.oracle.security.ucrypto.NativeDigest$MD5");
    79                             sd("MessageDigest", "MD5",
       
    80                                "com.oracle.security.ucrypto.NativeDigest$MD5"));
    77                         provProp.put("MessageDigest.SHA",
    81                         provProp.put("MessageDigest.SHA",
    78                                      "com.oracle.security.ucrypto.NativeDigest$SHA1");
    82                             sd("MessageDigest", "SHA",
    79                         provProp.put("Alg.Alias.MessageDigest.SHA-1", "SHA");
    83                                "com.oracle.security.ucrypto.NativeDigest$SHA1",
    80                         provProp.put("Alg.Alias.MessageDigest.SHA1", "SHA");
    84                                "SHA-1", "SHA1"));
    81                         provProp.put("MessageDigest.SHA-256",
    85                         provProp.put("MessageDigest.SHA-256",
    82                                      "com.oracle.security.ucrypto.NativeDigest$SHA256");
    86                             sd("MessageDigest", "SHA-256",
    83                         provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
    87                                "com.oracle.security.ucrypto.NativeDigest$SHA256",
    84                         provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.1", "SHA-256");
    88                                "2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"));
    85 
    89 
    86                         provProp.put("MessageDigest.SHA-384",
    90                         provProp.put("MessageDigest.SHA-384",
    87                                      "com.oracle.security.ucrypto.NativeDigest$SHA384");
    91                             sd("MessageDigest", "SHA-384",
    88                         provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
    92                                "com.oracle.security.ucrypto.NativeDigest$SHA384",
    89                         provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.2", "SHA-384");
    93                                "2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"));
    90 
    94 
    91                         provProp.put("MessageDigest.SHA-512",
    95                         provProp.put("MessageDigest.SHA-512",
    92                                      "com.oracle.security.ucrypto.NativeDigest$SHA512");
    96                             sd("MessageDigest", "SHA-512",
    93                         provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
    97                                "com.oracle.security.ucrypto.NativeDigest$SHA512",
    94                         provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.3", "SHA-512");
    98                                "2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"));
    95 
    99                     };
    96                     }
       
    97                     if (result[1]) { // successfully loaded libsoftcrypto
   100                     if (result[1]) { // successfully loaded libsoftcrypto
    98                         String supportedMechs = getMechList();
   101                         String supportedMechs = getMechList();
    99                         debug("Prov: supported mechs = " + supportedMechs);
   102                         debug("Prov: supported mechs = " + supportedMechs);
   100                         for (UcryptoMech m : UcryptoMech.values()) {
   103                         for (UcryptoMech m : UcryptoMech.values()) {
   101                             if (supportedMechs.indexOf(m.name() + ",") != -1) {
   104                             if (supportedMechs.indexOf(m.name() + ",") != -1) {
   102                                 String[] jceProps = m.jceProperties();
   105                                 ServiceDesc[] services = m.getServiceDescriptions();
   103                                 // skip unsupported UcryptoMech
   106                                 // skip unsupported UcryptoMech
   104                                 if (jceProps == null) continue;
   107                                 if (services == null || services.length == 0) continue;
   105                                 for (int p = 0; p < jceProps.length; p++) {
   108                                 for (int p = 0; p < services.length; p++) {
   106                                     StringTokenizer st =
   109                                     ServiceDesc entry = services[p];
   107                                         new StringTokenizer(jceProps[p], ";");
   110                                     provProp.put(entry.getType() + "." + entry.getAlgorithm(),
   108                                     if (st.countTokens() != 2) {
   111                                                  entry);
   109                                         throw new RuntimeException("Wrong format: " + jceProps[p]);
       
   110                                     }
       
   111                                     provProp.put(st.nextToken(), st.nextToken());
       
   112                                 }
   112                                 }
   113                             }
   113                             }
   114                         }
   114                         }
   115                         // NOTE: GCM support is only available since jdk 7
   115                         // NOTE: GCM support is only available since jdk 7
   116                         provProp.put("AlgorithmParameters.GCM",
   116                         provProp.put("AlgorithmParameters.GCM",
   117                                      "com.oracle.security.ucrypto.GCMParameters");
   117                                      sd("AlgorithmParameters", "GCM", "com.oracle.security.ucrypto.GCMParameters"));
   118                     }
   118                     }
   119                 } else {
   119                 } else {
   120                     debug("Prov: unexpected ucrypto library loading error, got " + result.length);
   120                     debug("Prov: unexpected ucrypto library loading error, got " + result.length);
   121                 }
   121                 }
   122             }
   122             }
   123         } catch (AccessControlException ace) {
   123         } catch (AccessControlException ace) {
       
   124             if (DEBUG) ace.printStackTrace();
   124             // disable Ucrypto provider
   125             // disable Ucrypto provider
   125             DEBUG = false;
       
   126             provProp = null;
   126             provProp = null;
       
   127         }
       
   128     }
       
   129 
       
   130     private static ServiceDesc sd(String type, String algo, String cn,
       
   131         String... aliases) {
       
   132         return new ServiceDesc(type, algo, cn, aliases);
       
   133     }
       
   134 
       
   135     private static final class ProviderService extends Provider.Service {
       
   136         ProviderService(Provider p, ServiceDesc sd) {
       
   137             super(p, sd.getType(), sd.getAlgorithm(), sd.getClassName(),
       
   138                   sd.getAliases(), null);
       
   139         }
       
   140 
       
   141         @Override
       
   142         public Object newInstance(Object ctrParamObj)
       
   143             throws NoSuchAlgorithmException {
       
   144             String type = getType();
       
   145             if (ctrParamObj != null) {
       
   146                 throw new InvalidParameterException
       
   147                     ("constructorParameter not used with " + type + " engines");
       
   148             }
       
   149             String algo = getAlgorithm();
       
   150             try {
       
   151                 if (type.equals("Cipher")) {
       
   152                     int keySize = -1;
       
   153                     if (algo.charAt(3) == '_') {
       
   154                         keySize = Integer.parseInt(algo.substring(4, 7))/8;
       
   155                         algo = algo.substring(0, 3) + algo.substring(7);
       
   156                     }
       
   157                     if (algo.equals("AES/ECB/NoPadding")) {
       
   158                         return new NativeCipher.AesEcbNoPadding(keySize);
       
   159                     } else if (algo.equals("AES/ECB/PKCS5Padding")) {
       
   160                         return new NativeCipherWithJavaPadding.AesEcbPKCS5();
       
   161                     } else if (algo.equals("AES/CBC/NoPadding")) {
       
   162                         return new NativeCipher.AesCbcNoPadding(keySize);
       
   163                     } else if (algo.equals("AES/CBC/PKCS5Padding")) {
       
   164                         return new NativeCipherWithJavaPadding.AesCbcPKCS5();
       
   165                     } else if (algo.equals("AES/CTR/NoPadding")) {
       
   166                         return new NativeCipher.AesCtrNoPadding();
       
   167                     } else if (algo.equals("AES/GCM/NoPadding")) {
       
   168                         return new NativeGCMCipher.AesGcmNoPadding(keySize);
       
   169                     } else if (algo.equals("AES/CFB128/NoPadding")) {
       
   170                         return new NativeCipher.AesCfb128NoPadding();
       
   171                     } else if (algo.equals("AES/CFB128/PKCS5Padding")) {
       
   172                         return new NativeCipherWithJavaPadding.AesCfb128PKCS5();
       
   173                     } else if (algo.equals("RSA/ECB/NoPadding")) {
       
   174                         return new NativeRSACipher.NoPadding();
       
   175                     } else if (algo.equals("RSA/ECB/PKCS1Padding")) {
       
   176                         return new NativeRSACipher.PKCS1Padding();
       
   177                     }
       
   178                 } else if (type.equals("Signature")) {
       
   179                     if (algo.equals("SHA1withRSA")) {
       
   180                         return new NativeRSASignature.SHA1();
       
   181                     } else if (algo.equals("SHA256withRSA")) {
       
   182                         return new NativeRSASignature.SHA256();
       
   183                     } else if (algo.equals("SHA384withRSA")) {
       
   184                         return new NativeRSASignature.SHA384();
       
   185                     } else if (algo.equals("SHA512withRSA")) {
       
   186                         return new NativeRSASignature.SHA512();
       
   187                     } else if (algo.equals("MD5withRSA")) {
       
   188                         return new NativeRSASignature.MD5();
       
   189                     }
       
   190                 } else if (type.equals("MessageDigest")) {
       
   191                     if (algo.equals("SHA")) {
       
   192                         return new NativeDigest.SHA1();
       
   193                     } else if (algo.equals("SHA-256")) {
       
   194                         return new NativeDigest.SHA256();
       
   195                     } else if (algo.equals("SHA-384")) {
       
   196                         return new NativeDigest.SHA384();
       
   197                     } else if (algo.equals("SHA-512")) {
       
   198                         return new NativeDigest.SHA512();
       
   199                     } else if (algo.equals("MD5")) {
       
   200                         return new NativeDigest.MD5();
       
   201                     }
       
   202                 } else if (type.equals("AlgorithmParameters")) {
       
   203                     if (algo.equals("GCM")) {
       
   204                         return new GCMParameters();
       
   205                     }
       
   206                 }
       
   207             } catch (Exception ex) {
       
   208                 throw new NoSuchAlgorithmException("Error constructing " +
       
   209                     type + " for " + algo + " using OracleUcrypto", ex);
       
   210             }
       
   211             throw new ProviderException("No impl for " + algo +
       
   212                 " " + type);
   127         }
   213         }
   128     }
   214     }
   129 
   215 
   130     static Provider provider = null;
   216     static Provider provider = null;
   131     private static native boolean[] loadLibraries();
   217     private static native boolean[] loadLibraries();
   137         }
   223         }
   138     }
   224     }
   139 
   225 
   140     public UcryptoProvider() {
   226     public UcryptoProvider() {
   141         super("OracleUcrypto", 1.9d, "Provider using Oracle Ucrypto API");
   227         super("OracleUcrypto", 1.9d, "Provider using Oracle Ucrypto API");
       
   228 
       
   229         AccessController.doPrivileged(new PrivilegedAction<>() {
       
   230             public Void run() {
       
   231                 init(defConfigName);
       
   232                 return null;
       
   233             }
       
   234         });
       
   235         if (provider == null) provider = this;
       
   236     }
       
   237 
       
   238     private void init(final String configName) {
   142         if (provProp != null) {
   239         if (provProp != null) {
   143             AccessController.doPrivileged(new PutAllAction(this, provProp));
   240             debug("Prov: configuration file " + configName);
   144         }
   241             Config c;
   145         if (provider == null) provider = this;
   242             try {
   146     }
   243                 c = new Config(configName);
   147 
   244             } catch (Exception ex) {
   148     public UcryptoProvider(String configName) {
   245                 throw new UcryptoException("Error parsing Config", ex);
   149         super("OracleUcrypto", 1.9d, "Provider using Oracle Ucrypto API");
   246             }
   150         try {
   247 
   151             if (provProp != null) {
   248             String[] disabledServices = c.getDisabledServices();
   152                 HashMap<String, String> customProvProp =
   249             for (String ds : disabledServices) {
   153                     new HashMap<String, String>(provProp);
   250                 if (provProp.remove(ds) != null) {
   154                 Config c = new Config(configName);
   251                     debug("Prov: remove config-disabled service " + ds);
   155                 String[] disabledServices = c.getDisabledServices();
   252                 } else {
   156                 for (int i = 0; i < disabledServices.length; i++) {
   253                     debug("Prov: ignore unsupported service " + ds);
   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                 }
   254                 }
   164                 AccessController.doPrivileged(new PutAllAction(this, customProvProp));
   255             }
   165             }
   256 
   166         } catch (IOException ioe) { // thrown by Config
   257             for (ServiceDesc s: provProp.values()) {
   167             throw new UcryptoException("Error parsing Config", ioe);
   258                 debug("Prov: add service for " + s);
   168         }
   259                 putService(new ProviderService(this, s));
   169         if (provider == null) provider = this;
   260             }
       
   261         }
       
   262     }
       
   263 
       
   264     @Override
       
   265     public Provider configure(String configArg) throws InvalidParameterException {
       
   266         // default policy entry only grants read access to default config
       
   267         if (!defConfigName.equals(configArg)) {
       
   268             throw new InvalidParameterException("Ucrypto provider can only be " +
       
   269                 "configured with default configuration file");
       
   270         }
       
   271         // re-read the config
       
   272         init(defConfigName);
       
   273         return this;
   170     }
   274     }
   171 
   275 
   172     public boolean equals(Object obj) {
   276     public boolean equals(Object obj) {
   173         return this == obj;
   277         return this == obj;
   174     }
   278     }