UcryptoProvider.java revision 10854:558e97e47abe
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
26package com.oracle.security.ucrypto;
27
28import java.io.IOException;
29import java.util.HashMap;
30import java.util.StringTokenizer;
31import java.security.*;
32import sun.security.action.PutAllAction;
33import sun.security.action.GetPropertyAction;
34
35/**
36 * OracleUcrypto provider main class.
37 *
38 * @since 1.9
39 */
40public 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}
180