SunEC.java revision 12245:2f69eb7d4b90
1/*
2 * Copyright (c) 2009, 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
26package sun.security.ec;
27
28import java.util.*;
29import java.security.*;
30import java.util.regex.Pattern;
31import sun.security.util.CurveDB;
32import sun.security.util.NamedCurve;
33import sun.security.util.ECParameters;
34
35/**
36 * Provider class for the Elliptic Curve provider.
37 * Supports EC keypair and parameter generation, ECDSA signing and
38 * ECDH key agreement.
39 *
40 * IMPLEMENTATION NOTE:
41 * The Java classes in this provider access a native ECC implementation
42 * via JNI to a C++ wrapper class which in turn calls C functions.
43 * The Java classes are packaged into the jdk.crypto.sunec module and the
44 * C++ and C functions are packaged into libsunec.so or sunec.dll in the
45 * JRE native libraries directory.  If the native library is not present
46 * then this provider is registered with support for fewer ECC algorithms
47 * (KeyPairGenerator, Signature and KeyAgreement are omitted).
48 *
49 * @since   1.7
50 */
51public final class SunEC extends Provider {
52
53    private static final long serialVersionUID = -2279741672933606418L;
54
55    // flag indicating whether the full EC implementation is present
56    // (when native library is absent then fewer EC algorithms are available)
57    private static boolean useFullImplementation = true;
58    static {
59        try {
60            AccessController.doPrivileged(new PrivilegedAction<Void>() {
61                public Void run() {
62                    System.loadLibrary("sunec"); // check for native library
63                    return null;
64                }
65            });
66        } catch (UnsatisfiedLinkError e) {
67            useFullImplementation = false;
68        }
69    }
70
71    private static class ProviderService extends Provider.Service {
72
73        ProviderService(Provider p, String type, String algo, String cn) {
74            super(p, type, algo, cn, null, null);
75        }
76
77        ProviderService(Provider p, String type, String algo, String cn,
78            String[] aliases, HashMap<String, String> attrs) {
79            super(p, type, algo, cn,
80                  (aliases == null? null : Arrays.asList(aliases)), attrs);
81        }
82
83        @Override
84        public Object newInstance(Object ctrParamObj)
85            throws NoSuchAlgorithmException {
86            String type = getType();
87            if (ctrParamObj != null) {
88                throw new InvalidParameterException
89                    ("constructorParameter not used with " + type + " engines");
90            }
91
92            String algo = getAlgorithm();
93            try {
94                if (type.equals("Signature")) {
95                    boolean inP1363 = algo.endsWith("inP1363Format");
96                    if (inP1363) {
97                        algo = algo.substring(0, algo.length() - 13);
98                    }
99                    if (algo.equals("SHA1withECDSA")) {
100                        return (inP1363? new ECDSASignature.SHA1inP1363Format() :
101                            new ECDSASignature.SHA1());
102                    } else if (algo.equals("SHA224withECDSA")) {
103                        return (inP1363? new ECDSASignature.SHA224inP1363Format() :
104                            new ECDSASignature.SHA224());
105                    } else if (algo.equals("SHA256withECDSA")) {
106                        return (inP1363? new ECDSASignature.SHA256inP1363Format() :
107                            new ECDSASignature.SHA256());
108                    } else if (algo.equals("SHA384withECDSA")) {
109                        return (inP1363? new ECDSASignature.SHA384inP1363Format() :
110                            new ECDSASignature.SHA384());
111                    } else if (algo.equals("SHA512withECDSA")) {
112                        return (inP1363? new ECDSASignature.SHA512inP1363Format() :
113                            new ECDSASignature.SHA512());
114                    } else if (algo.equals("NONEwithECDSA")) {
115                        return (inP1363? new ECDSASignature.RawinP1363Format() :
116                            new ECDSASignature.Raw());
117                    }
118                } else  if (type.equals("KeyFactory")) {
119                    if (algo.equals("EC")) {
120                        return new ECKeyFactory();
121                    }
122                } else  if (type.equals("AlgorithmParameters")) {
123                    if (algo.equals("EC")) {
124                        return new sun.security.util.ECParameters();
125                    }
126                } else  if (type.equals("KeyPairGenerator")) {
127                    if (algo.equals("EC")) {
128                        return new ECKeyPairGenerator();
129                    }
130                } else  if (type.equals("KeyAgreement")) {
131                    if (algo.equals("ECDH")) {
132                        return new ECDHKeyAgreement();
133                    }
134                }
135            } catch (Exception ex) {
136                throw new NoSuchAlgorithmException("Error constructing " +
137                    type + " for " + algo + " using SunEC", ex);
138            }
139            throw new ProviderException("No impl for " + algo +
140                " " + type);
141        }
142    }
143
144    public SunEC() {
145        super("SunEC", 1.9d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)");
146        AccessController.doPrivileged(new PrivilegedAction<Void>() {
147            public Void run() {
148                putEntries(useFullImplementation);
149                return null;
150            }
151        });
152    }
153
154    void putEntries(boolean useFullImplementation) {
155        HashMap<String, String> ATTRS = new HashMap<>(3);
156        ATTRS.put("ImplementedIn", "Software");
157        String ecKeyClasses = "java.security.interfaces.ECPublicKey" +
158                 "|java.security.interfaces.ECPrivateKey";
159        ATTRS.put("SupportedKeyClasses", ecKeyClasses);
160        ATTRS.put("KeySize", "256");
161
162        /*
163         *  Key Factory engine
164         */
165        putService(new ProviderService(this, "KeyFactory",
166            "EC", "sun.security.ec.ECKeyFactory",
167            new String[] { "EllipticCurve" }, ATTRS));
168
169        /*
170         * Algorithm Parameter engine
171         */
172        // "AlgorithmParameters.EC SupportedCurves" prop used by unit test
173        boolean firstCurve = true;
174        StringBuilder names = new StringBuilder();
175        Pattern nameSplitPattern = Pattern.compile(CurveDB.SPLIT_PATTERN);
176
177        Collection<? extends NamedCurve> supportedCurves =
178            CurveDB.getSupportedCurves();
179        for (NamedCurve namedCurve : supportedCurves) {
180            if (!firstCurve) {
181                names.append("|");
182            } else {
183                firstCurve = false;
184            }
185
186            names.append("[");
187
188            String[] commonNames = nameSplitPattern.split(namedCurve.getName());
189            for (String commonName : commonNames) {
190                names.append(commonName.trim());
191                names.append(",");
192            }
193
194            names.append(namedCurve.getObjectId());
195            names.append("]");
196        }
197
198        HashMap<String, String> apAttrs = new HashMap<>(ATTRS);
199        apAttrs.put("SupportedCurves", names.toString());
200
201        putService(new ProviderService(this, "AlgorithmParameters",
202            "EC", "sun.security.util.ECParameters",
203            new String[] { "EllipticCurve", "1.2.840.10045.2.1", "OID.1.2.840.10045.2.1" },
204            apAttrs));
205
206        /*
207         * Register the algorithms below only when the full ECC implementation
208         * is available
209         */
210        if (!useFullImplementation) {
211            return;
212        }
213
214        /*
215         * Signature engines
216         */
217        putService(new ProviderService(this, "Signature",
218            "NONEwithECDSA", "sun.security.ec.ECDSASignature$Raw",
219            null, ATTRS));
220        putService(new ProviderService(this, "Signature",
221            "SHA1withECDSA", "sun.security.ec.ECDSASignature$SHA1",
222            new String[] { "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1" },
223            ATTRS));
224        putService(new ProviderService(this, "Signature",
225            "SHA224withECDSA", "sun.security.ec.ECDSASignature$SHA224",
226            new String[] { "1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"},
227            ATTRS));
228        putService(new ProviderService(this, "Signature",
229            "SHA256withECDSA", "sun.security.ec.ECDSASignature$SHA256",
230            new String[] { "1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"},
231            ATTRS));
232        putService(new ProviderService(this, "Signature",
233            "SHA384withECDSA", "sun.security.ec.ECDSASignature$SHA384",
234            new String[] { "1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3" },
235            ATTRS));
236        putService(new ProviderService(this, "Signature",
237            "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512",
238            new String[] { "1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4" },
239            ATTRS));
240
241        putService(new ProviderService(this, "Signature",
242             "NONEwithECDSAinP1363Format",
243             "sun.security.ec.ECDSASignature$RawinP1363Format"));
244        putService(new ProviderService(this, "Signature",
245             "SHA1withECDSAinP1363Format",
246             "sun.security.ec.ECDSASignature$SHA1inP1363Format"));
247        putService(new ProviderService(this, "Signature",
248             "SHA224withECDSAinP1363Format",
249             "sun.security.ec.ECDSASignature$SHA224inP1363Format"));
250        putService(new ProviderService(this, "Signature",
251             "SHA256withECDSAinP1363Format",
252             "sun.security.ec.ECDSASignature$SHA256inP1363Format"));
253        putService(new ProviderService(this, "Signature",
254            "SHA384withECDSAinP1363Format",
255            "sun.security.ec.ECDSASignature$SHA384inP1363Format"));
256        putService(new ProviderService(this, "Signature",
257            "SHA512withECDSAinP1363Format",
258            "sun.security.ec.ECDSASignature$SHA512inP1363Format"));
259
260        /*
261         *  Key Pair Generator engine
262         */
263        putService(new ProviderService(this, "KeyPairGenerator",
264            "EC", "sun.security.ec.ECKeyPairGenerator",
265            new String[] { "EllipticCurve" }, ATTRS));
266
267        /*
268         * Key Agreement engine
269         */
270        putService(new ProviderService(this, "KeyAgreement",
271            "ECDH", "sun.security.ec.ECDHKeyAgreement", null, ATTRS));
272    }
273}
274