1/*
2 * Copyright (c) 2005, 2016, 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.mscapi;
27
28import java.security.AccessController;
29import java.security.PrivilegedAction;
30import java.security.Provider;
31import java.security.NoSuchAlgorithmException;
32import java.security.InvalidParameterException;
33import java.security.ProviderException;
34import java.util.HashMap;
35import java.util.Arrays;
36import java.util.Map;
37
38import static sun.security.util.SecurityConstants.PROVIDER_VER;
39
40/**
41 * A Cryptographic Service Provider for the Microsoft Crypto API.
42 *
43 * @since 1.6
44 */
45
46public final class SunMSCAPI extends Provider {
47
48    private static final long serialVersionUID = 8622598936488630849L; //TODO
49
50    private static final String INFO = "Sun's Microsoft Crypto API provider";
51
52    static {
53        AccessController.doPrivileged(new PrivilegedAction<Void>() {
54            public Void run() {
55                System.loadLibrary("sunmscapi");
56                return null;
57            }
58        });
59    }
60
61    private static final class ProviderService extends Provider.Service {
62        ProviderService(Provider p, String type, String algo, String cn) {
63            super(p, type, algo, cn, null, null);
64        }
65
66        ProviderService(Provider p, String type, String algo, String cn,
67            String[] aliases, HashMap<String, String> attrs) {
68            super(p, type, algo, cn,
69                  (aliases == null? null : Arrays.asList(aliases)), attrs);
70        }
71
72        @Override
73        public Object newInstance(Object ctrParamObj)
74            throws NoSuchAlgorithmException {
75            String type = getType();
76            if (ctrParamObj != null) {
77                throw new InvalidParameterException
78                    ("constructorParameter not used with " + type +
79                     " engines");
80            }
81            String algo = getAlgorithm();
82            try {
83                if (type.equals("SecureRandom")) {
84                    if (algo.equals("Windows-PRNG")) {
85                        return new PRNG();
86                    }
87                } else if (type.equals("KeyStore")) {
88                    if (algo.equals("Windows-MY")) {
89                        return new KeyStore.MY();
90                    } else if (algo.equals("Windows-ROOT")) {
91                        return new KeyStore.ROOT();
92                    }
93                } else if (type.equals("Signature")) {
94                    if (algo.equals("NONEwithRSA")) {
95                        return new RSASignature.Raw();
96                    } else if (algo.equals("SHA1withRSA")) {
97                        return new RSASignature.SHA1();
98                    } else if (algo.equals("SHA256withRSA")) {
99                        return new RSASignature.SHA256();
100                    } else if (algo.equals("SHA384withRSA")) {
101                        return new RSASignature.SHA384();
102                    } else if (algo.equals("SHA512withRSA")) {
103                        return new RSASignature.SHA512();
104                    } else if (algo.equals("MD5withRSA")) {
105                        return new RSASignature.MD5();
106                    } else if (algo.equals("MD2withRSA")) {
107                        return new RSASignature.MD2();
108                    }
109                } else if (type.equals("KeyPairGenerator")) {
110                    if (algo.equals("RSA")) {
111                        return new RSAKeyPairGenerator();
112                    }
113                } else if (type.equals("Cipher")) {
114                    if (algo.equals("RSA") ||
115                        algo.equals("RSA/ECB/PKCS1Padding")) {
116                        return new RSACipher();
117                    }
118                }
119            } catch (Exception ex) {
120                throw new NoSuchAlgorithmException
121                    ("Error constructing " + type + " for " +
122                    algo + " using SunMSCAPI", ex);
123            }
124            throw new ProviderException("No impl for " + algo +
125                " " + type);
126        }
127    }
128
129    public SunMSCAPI() {
130        super("SunMSCAPI", PROVIDER_VER, INFO);
131
132        final Provider p = this;
133        AccessController.doPrivileged(new PrivilegedAction<Void>() {
134            public Void run() {
135                /*
136                 * Secure random
137                 */
138                HashMap<String, String> srattrs = new HashMap<>(1);
139                srattrs.put("ThreadSafe", "true");
140                putService(new ProviderService(p, "SecureRandom",
141                           "Windows-PRNG", "sun.security.mscapi.PRNG",
142                           null, srattrs));
143
144                /*
145                 * Key store
146                 */
147                putService(new ProviderService(p, "KeyStore",
148                           "Windows-MY", "sun.security.mscapi.KeyStore$MY"));
149                putService(new ProviderService(p, "KeyStore",
150                           "Windows-ROOT", "sun.security.mscapi.KeyStore$ROOT"));
151
152                /*
153                 * Signature engines
154                 */
155                HashMap<String, String> attrs = new HashMap<>(1);
156                attrs.put("SupportedKeyClasses", "sun.security.mscapi.Key");
157
158                // NONEwithRSA must be supplied with a pre-computed message digest.
159                // Only the following digest algorithms are supported: MD5, SHA-1,
160                // SHA-256, SHA-384, SHA-512 and a special-purpose digest
161                // algorithm which is a concatenation of SHA-1 and MD5 digests.
162                putService(new ProviderService(p, "Signature",
163                           "NONEwithRSA", "sun.security.mscapi.RSASignature$Raw",
164                           null, attrs));
165                putService(new ProviderService(p, "Signature",
166                           "SHA1withRSA", "sun.security.mscapi.RSASignature$SHA1",
167                           null, attrs));
168                putService(new ProviderService(p, "Signature",
169                           "SHA256withRSA", "sun.security.mscapi.RSASignature$SHA256",
170                           new String[] { "1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11" },
171                           attrs));
172                putService(new ProviderService(p, "Signature",
173                           "SHA384withRSA", "sun.security.mscapi.RSASignature$SHA384",
174                           new String[] { "1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12" },
175                           attrs));
176                putService(new ProviderService(p, "Signature",
177                           "SHA512withRSA", "sun.security.mscapi.RSASignature$SHA512",
178                           new String[] { "1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13" },
179                           attrs));
180                putService(new ProviderService(p, "Signature",
181                           "MD5withRSA", "sun.security.mscapi.RSASignature$MD5",
182                           null, attrs));
183                putService(new ProviderService(p, "Signature",
184                           "MD2withRSA", "sun.security.mscapi.RSASignature$MD2",
185                           null, attrs));
186
187                /*
188                 * Key Pair Generator engines
189                 */
190                attrs.clear();
191                attrs.put("KeySize", "16384");
192                putService(new ProviderService(p, "KeyPairGenerator",
193                           "RSA", "sun.security.mscapi.RSAKeyPairGenerator",
194                           null, attrs));
195
196                /*
197                 * Cipher engines
198                 */
199                attrs.clear();
200                attrs.put("SupportedModes", "ECB");
201                attrs.put("SupportedPaddings", "PKCS1PADDING");
202                attrs.put("SupportedKeyClasses", "sun.security.mscapi.Key");
203                putService(new ProviderService(p, "Cipher",
204                           "RSA", "sun.security.mscapi.RSACipher",
205                           null, attrs));
206                putService(new ProviderService(p, "Cipher",
207                           "RSA/ECB/PKCS1Padding", "sun.security.mscapi.RSACipher",
208                           null, attrs));
209                return null;
210            }
211        });
212    }
213}
214