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 }
|