1 /*
2  * Copyright (c) 2017, 2020, 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 sun.security.util;
27 
28 import java.util.*;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.regex.PatternSyntaxException;
31 import java.security.InvalidParameterException;
32 import java.security.ProviderException;
33 import sun.security.action.GetPropertyAction;
34 
35 /**
36  * Various constants such as version number, default key length, used by
37  * the JDK security/crypto providers.
38  */
39 public final class SecurityProviderConstants {
40     // Cannot create one of these
SecurityProviderConstants()41     private SecurityProviderConstants () {}
42 
43     private static final Debug debug =
44         Debug.getInstance("jca", "ProviderConfig");
45 
46     // cache for provider aliases; key is the standard algorithm name
47     // value is the associated aliases List
48     private static final ConcurrentHashMap<String, List<String>> aliasesMap;
49 
50     // utility method for generating aliases list using the supplied
51     // 'oid' and 'extraAliases', then store into "aliasesMap" cache under the
52     // key 'stdName'
store(String stdName, KnownOIDs oid, String ... extraAliases)53     private static List<String> store(String stdName, KnownOIDs oid,
54             String ... extraAliases) {
55         List<String> value;
56         if (oid == null && extraAliases.length != 0) {
57             value = List.of(extraAliases);
58         } else {
59             value = new ArrayList<>();
60             if (oid != null) {
61                 value.add("OID." + oid.value());
62                 value.add(oid.value());
63                 String[] knownAliases = oid.aliases();
64                 if (knownAliases != null) {
65                     for (String ka : knownAliases) {
66                         value.add(ka);
67                     }
68                 }
69             }
70             for (String ea : extraAliases) {
71                 value.add(ea);
72             }
73         }
74         aliasesMap.put(stdName, value);
75         return value;
76     }
77 
78     // returns an aliases List for the specified algorithm name o
79     // NOTE: exception is thrown if no aliases nor oid found, so
80     // only call this method if aliases are expected
getAliases(String o)81     public static List<String> getAliases(String o) {
82         List<String> res = aliasesMap.get(o);
83         if (res == null) {
84             KnownOIDs e = KnownOIDs.findMatch(o);
85             if (e != null) {
86                 return store(o, e);
87             }
88             ProviderException pe =
89                     new ProviderException("Cannot find aliases for " + o);
90             throw pe;
91         }
92         return res;
93     }
94 
getDefDSASubprimeSize(int primeSize)95     public static final int getDefDSASubprimeSize(int primeSize) {
96         if (primeSize <= 1024) {
97             return 160;
98         } else if (primeSize == 2048) {
99             return 224;
100         } else if (primeSize == 3072) {
101             return 256;
102         } else {
103             throw new InvalidParameterException("Invalid DSA Prime Size: " +
104                 primeSize);
105         }
106     }
107 
108     public static final int DEF_DSA_KEY_SIZE;
109     public static final int DEF_RSA_KEY_SIZE;
110     public static final int DEF_RSASSA_PSS_KEY_SIZE;
111     public static final int DEF_DH_KEY_SIZE;
112     public static final int DEF_EC_KEY_SIZE;
113     public static final int DEF_ED_KEY_SIZE;
114 
115     private static final String KEY_LENGTH_PROP =
116         "jdk.security.defaultKeySize";
117 
118     static {
119         String keyLengthStr = GetPropertyAction.privilegedGetProperty
120             (KEY_LENGTH_PROP);
121         int dsaKeySize = 2048;
122         int rsaKeySize = 2048;
123         int rsaSsaPssKeySize = rsaKeySize; // default to same value as RSA
124         int dhKeySize = 2048;
125         int ecKeySize = 256;
126         int edKeySize = 255;
127 
128         if (keyLengthStr != null) {
129             try {
130                 String[] pairs = keyLengthStr.split(",");
131                 for (String p : pairs) {
132                     String[] algoAndValue = p.split(":");
133                     if (algoAndValue.length != 2) {
134                         // invalid pair, skip to next pair
135                         if (debug != null) {
136                             debug.println("Ignoring invalid pair in " +
137                                 KEY_LENGTH_PROP + " property: " + p);
138                         }
139                         continue;
140                     }
141                     String algoName = algoAndValue[0].trim().toUpperCase();
142                     int value = -1;
143                     try {
144                         value = Integer.parseInt(algoAndValue[1].trim());
145                     } catch (NumberFormatException nfe) {
146                         // invalid value, skip to next pair
147                         if (debug != null) {
148                             debug.println("Ignoring invalid value in " +
149                                 KEY_LENGTH_PROP + " property: " + p);
150                         }
151                         continue;
152                     }
153                     if (algoName.equals("DSA")) {
154                         dsaKeySize = value;
155                     } else if (algoName.equals("RSA")) {
156                         rsaKeySize = value;
157                     } else if (algoName.equals("RSASSA-PSS")) {
158                         rsaSsaPssKeySize = value;
159                     } else if (algoName.equals("DH")) {
160                         dhKeySize = value;
161                     } else if (algoName.equals("EC")) {
162                         ecKeySize = value;
163                     } else if (algoName.equalsIgnoreCase("EdDSA")) {
164                         edKeySize = value;
165                     } else {
166                         if (debug != null) {
167                             debug.println("Ignoring unsupported algo in " +
168                                 KEY_LENGTH_PROP + " property: " + p);
169                         }
170                         continue;
171                     }
172                     if (debug != null) {
173                         debug.println("Overriding default " + algoName +
174                             " keysize with value from " +
175                             KEY_LENGTH_PROP + " property: " + value);
176                     }
177                 }
178             } catch (PatternSyntaxException pse) {
179                 // if property syntax is not followed correctly
180                 if (debug != null) {
181                     debug.println("Unexpected exception while parsing " +
182                         KEY_LENGTH_PROP + " property: " + pse);
183                 }
184             }
185         }
186         DEF_DSA_KEY_SIZE = dsaKeySize;
187         DEF_RSA_KEY_SIZE = rsaKeySize;
188         DEF_RSASSA_PSS_KEY_SIZE = rsaSsaPssKeySize;
189         DEF_DH_KEY_SIZE = dhKeySize;
190         DEF_EC_KEY_SIZE = ecKeySize;
191         DEF_ED_KEY_SIZE = edKeySize;
192 
193         // Set up aliases with default mappings
194         // This is needed when the mapping contains non-oid
195         // aliases
196         aliasesMap = new ConcurrentHashMap<>();
197 
198         store("SHA1withDSA", KnownOIDs.SHA1withDSA,
199                 KnownOIDs.OIW_JDK_SHA1withDSA.value(),
200                 KnownOIDs.OIW_SHA1withDSA.value(),
201                 "DSA", "SHA/DSA", "SHA-1/DSA",
202                 "SHA1/DSA", "SHAwithDSA", "DSAWithSHA1");
203 
204         store("DSA", KnownOIDs.DSA, KnownOIDs.OIW_DSA.value());
205 
206         store("SHA1withRSA", KnownOIDs.SHA1withRSA,
207                 KnownOIDs.OIW_SHA1withRSA.value());
208 
209         store("SHA-1", KnownOIDs.SHA_1);
210 
211         store("PBEWithMD5AndDES", KnownOIDs.PBEWithMD5AndDES, "PBE");
212 
213         store("DiffieHellman", KnownOIDs.DiffieHellman);
214 
215         store("AES", KnownOIDs.AES, "Rijndael");
216 
217         store("EC", KnownOIDs.EC, "EllipticCurve");
218 
219         store("X.509", null, "X509");
220         store("NONEwithDSA", null, "RawDSA");
221         store("DESede", null, "TripleDES");
222         store("ARCFOUR", KnownOIDs.ARCFOUR);
223         // For backward compatility, refer to PKCS1 mapping for RSA
224         // KeyPairGenerator and KeyFactory
225         store("PKCS1", KnownOIDs.PKCS1, KnownOIDs.RSA.value());
226     }
227 }
228