50 // Elliptic Curves (RFC 4492) |
49 // Elliptic Curves (RFC 4492) |
51 // |
50 // |
52 // See sun.security.util.CurveDB for the OIDs |
51 // See sun.security.util.CurveDB for the OIDs |
53 // NIST K-163 |
52 // NIST K-163 |
54 |
53 |
55 SECT163_K1(0x0001, "sect163k1", "1.3.132.0.1", |
54 SECT163_K1(0x0001, "sect163k1", |
56 NamedGroupType.NAMED_GROUP_ECDHE, |
55 NamedGroupSpec.NAMED_GROUP_ECDHE, |
57 ProtocolVersion.PROTOCOLS_TO_12), |
56 ProtocolVersion.PROTOCOLS_TO_12, |
58 SECT163_R1(0x0002, "sect163r1", "1.3.132.0.2", |
57 CurveDB.lookup("sect163k1")), |
59 NamedGroupType.NAMED_GROUP_ECDHE, |
58 SECT163_R1(0x0002, "sect163r1", |
60 ProtocolVersion.PROTOCOLS_TO_12), |
59 NamedGroupSpec.NAMED_GROUP_ECDHE, |
|
60 ProtocolVersion.PROTOCOLS_TO_12, |
|
61 CurveDB.lookup("sect163r1")), |
61 |
62 |
62 // NIST B-163 |
63 // NIST B-163 |
63 SECT163_R2(0x0003, "sect163r2", "1.3.132.0.15", |
64 SECT163_R2(0x0003, "sect163r2", |
64 NamedGroupType.NAMED_GROUP_ECDHE, |
65 NamedGroupSpec.NAMED_GROUP_ECDHE, |
65 ProtocolVersion.PROTOCOLS_TO_12), |
66 ProtocolVersion.PROTOCOLS_TO_12, |
66 SECT193_R1(0x0004, "sect193r1", "1.3.132.0.24", |
67 CurveDB.lookup("sect163r2")), |
67 NamedGroupType.NAMED_GROUP_ECDHE, |
68 SECT193_R1(0x0004, "sect193r1", |
68 ProtocolVersion.PROTOCOLS_TO_12), |
69 NamedGroupSpec.NAMED_GROUP_ECDHE, |
69 SECT193_R2(0x0005, "sect193r2", "1.3.132.0.25", |
70 ProtocolVersion.PROTOCOLS_TO_12, |
70 NamedGroupType.NAMED_GROUP_ECDHE, |
71 CurveDB.lookup("sect193r1")), |
71 ProtocolVersion.PROTOCOLS_TO_12), |
72 SECT193_R2(0x0005, "sect193r2", |
|
73 NamedGroupSpec.NAMED_GROUP_ECDHE, |
|
74 ProtocolVersion.PROTOCOLS_TO_12, |
|
75 CurveDB.lookup("sect193r2")), |
72 |
76 |
73 // NIST K-233 |
77 // NIST K-233 |
74 SECT233_K1(0x0006, "sect233k1", "1.3.132.0.26", |
78 SECT233_K1(0x0006, "sect233k1", |
75 NamedGroupType.NAMED_GROUP_ECDHE, |
79 NamedGroupSpec.NAMED_GROUP_ECDHE, |
76 ProtocolVersion.PROTOCOLS_TO_12), |
80 ProtocolVersion.PROTOCOLS_TO_12, |
|
81 CurveDB.lookup("sect233k1")), |
77 |
82 |
78 // NIST B-233 |
83 // NIST B-233 |
79 SECT233_R1(0x0007, "sect233r1", "1.3.132.0.27", |
84 SECT233_R1(0x0007, "sect233r1", |
80 NamedGroupType.NAMED_GROUP_ECDHE, |
85 NamedGroupSpec.NAMED_GROUP_ECDHE, |
81 ProtocolVersion.PROTOCOLS_TO_12), |
86 ProtocolVersion.PROTOCOLS_TO_12, |
82 SECT239_K1(0x0008, "sect239k1", "1.3.132.0.3", |
87 CurveDB.lookup("sect233r1")), |
83 NamedGroupType.NAMED_GROUP_ECDHE, |
88 SECT239_K1(0x0008, "sect239k1", |
84 ProtocolVersion.PROTOCOLS_TO_12), |
89 NamedGroupSpec.NAMED_GROUP_ECDHE, |
|
90 ProtocolVersion.PROTOCOLS_TO_12, |
|
91 CurveDB.lookup("sect239k1")), |
85 |
92 |
86 // NIST K-283 |
93 // NIST K-283 |
87 SECT283_K1(0x0009, "sect283k1", "1.3.132.0.16", |
94 SECT283_K1(0x0009, "sect283k1", |
88 NamedGroupType.NAMED_GROUP_ECDHE, |
95 NamedGroupSpec.NAMED_GROUP_ECDHE, |
89 ProtocolVersion.PROTOCOLS_TO_12), |
96 ProtocolVersion.PROTOCOLS_TO_12, |
|
97 CurveDB.lookup("sect283k1")), |
90 |
98 |
91 // NIST B-283 |
99 // NIST B-283 |
92 SECT283_R1(0x000A, "sect283r1", "1.3.132.0.17", |
100 SECT283_R1(0x000A, "sect283r1", |
93 NamedGroupType.NAMED_GROUP_ECDHE, |
101 NamedGroupSpec.NAMED_GROUP_ECDHE, |
94 ProtocolVersion.PROTOCOLS_TO_12), |
102 ProtocolVersion.PROTOCOLS_TO_12, |
|
103 CurveDB.lookup("sect283r1")), |
95 |
104 |
96 // NIST K-409 |
105 // NIST K-409 |
97 SECT409_K1(0x000B, "sect409k1", "1.3.132.0.36", |
106 SECT409_K1(0x000B, "sect409k1", |
98 NamedGroupType.NAMED_GROUP_ECDHE, |
107 NamedGroupSpec.NAMED_GROUP_ECDHE, |
99 ProtocolVersion.PROTOCOLS_TO_12), |
108 ProtocolVersion.PROTOCOLS_TO_12, |
|
109 CurveDB.lookup("sect409k1")), |
100 |
110 |
101 // NIST B-409 |
111 // NIST B-409 |
102 SECT409_R1(0x000C, "sect409r1", "1.3.132.0.37", |
112 SECT409_R1(0x000C, "sect409r1", |
103 NamedGroupType.NAMED_GROUP_ECDHE, |
113 NamedGroupSpec.NAMED_GROUP_ECDHE, |
104 ProtocolVersion.PROTOCOLS_TO_12), |
114 ProtocolVersion.PROTOCOLS_TO_12, |
|
115 CurveDB.lookup("sect409r1")), |
105 |
116 |
106 // NIST K-571 |
117 // NIST K-571 |
107 SECT571_K1(0x000D, "sect571k1", "1.3.132.0.38", |
118 SECT571_K1(0x000D, "sect571k1", |
108 NamedGroupType.NAMED_GROUP_ECDHE, |
119 NamedGroupSpec.NAMED_GROUP_ECDHE, |
109 ProtocolVersion.PROTOCOLS_TO_12), |
120 ProtocolVersion.PROTOCOLS_TO_12, |
|
121 CurveDB.lookup("sect571k1")), |
110 |
122 |
111 // NIST B-571 |
123 // NIST B-571 |
112 SECT571_R1(0x000E, "sect571r1", "1.3.132.0.39", |
124 SECT571_R1(0x000E, "sect571r1", |
113 NamedGroupType.NAMED_GROUP_ECDHE, |
125 NamedGroupSpec.NAMED_GROUP_ECDHE, |
114 ProtocolVersion.PROTOCOLS_TO_12), |
126 ProtocolVersion.PROTOCOLS_TO_12, |
115 SECP160_K1(0x000F, "secp160k1", "1.3.132.0.9", |
127 CurveDB.lookup("sect571r1")), |
116 NamedGroupType.NAMED_GROUP_ECDHE, |
128 SECP160_K1(0x000F, "secp160k1", |
117 ProtocolVersion.PROTOCOLS_TO_12), |
129 NamedGroupSpec.NAMED_GROUP_ECDHE, |
118 SECP160_R1(0x0010, "secp160r1", "1.3.132.0.8", |
130 ProtocolVersion.PROTOCOLS_TO_12, |
119 NamedGroupType.NAMED_GROUP_ECDHE, |
131 CurveDB.lookup("secp160k1")), |
120 ProtocolVersion.PROTOCOLS_TO_12), |
132 SECP160_R1(0x0010, "secp160r1", |
121 SECP160_R2(0x0011, "secp160r2", "1.3.132.0.30", |
133 NamedGroupSpec.NAMED_GROUP_ECDHE, |
122 NamedGroupType.NAMED_GROUP_ECDHE, |
134 ProtocolVersion.PROTOCOLS_TO_12, |
123 ProtocolVersion.PROTOCOLS_TO_12), |
135 CurveDB.lookup("secp160r1")), |
124 SECP192_K1(0x0012, "secp192k1", "1.3.132.0.31", |
136 SECP160_R2(0x0011, "secp160r2", |
125 NamedGroupType.NAMED_GROUP_ECDHE, |
137 NamedGroupSpec.NAMED_GROUP_ECDHE, |
126 ProtocolVersion.PROTOCOLS_TO_12), |
138 ProtocolVersion.PROTOCOLS_TO_12, |
|
139 CurveDB.lookup("secp160r2")), |
|
140 SECP192_K1(0x0012, "secp192k1", |
|
141 NamedGroupSpec.NAMED_GROUP_ECDHE, |
|
142 ProtocolVersion.PROTOCOLS_TO_12, |
|
143 CurveDB.lookup("secp192k1")), |
127 |
144 |
128 // NIST P-192 |
145 // NIST P-192 |
129 SECP192_R1(0x0013, "secp192r1", "1.2.840.10045.3.1.1", |
146 SECP192_R1(0x0013, "secp192r1", |
130 NamedGroupType.NAMED_GROUP_ECDHE, |
147 NamedGroupSpec.NAMED_GROUP_ECDHE, |
131 ProtocolVersion.PROTOCOLS_TO_12), |
148 ProtocolVersion.PROTOCOLS_TO_12, |
132 SECP224_K1(0x0014, "secp224k1", "1.3.132.0.32", |
149 CurveDB.lookup("secp192r1")), |
133 NamedGroupType.NAMED_GROUP_ECDHE, |
150 SECP224_K1(0x0014, "secp224k1", |
134 ProtocolVersion.PROTOCOLS_TO_12), |
151 NamedGroupSpec.NAMED_GROUP_ECDHE, |
|
152 ProtocolVersion.PROTOCOLS_TO_12, |
|
153 CurveDB.lookup("secp224k1")), |
135 |
154 |
136 // NIST P-224 |
155 // NIST P-224 |
137 SECP224_R1(0x0015, "secp224r1", "1.3.132.0.33", |
156 SECP224_R1(0x0015, "secp224r1", |
138 NamedGroupType.NAMED_GROUP_ECDHE, |
157 NamedGroupSpec.NAMED_GROUP_ECDHE, |
139 ProtocolVersion.PROTOCOLS_TO_12), |
158 ProtocolVersion.PROTOCOLS_TO_12, |
140 SECP256_K1(0x0016, "secp256k1", "1.3.132.0.10", |
159 CurveDB.lookup("secp224r1")), |
141 NamedGroupType.NAMED_GROUP_ECDHE, |
160 SECP256_K1(0x0016, "secp256k1", |
142 ProtocolVersion.PROTOCOLS_TO_12), |
161 NamedGroupSpec.NAMED_GROUP_ECDHE, |
|
162 ProtocolVersion.PROTOCOLS_TO_12, |
|
163 CurveDB.lookup("secp256k1")), |
143 |
164 |
144 // NIST P-256 |
165 // NIST P-256 |
145 SECP256_R1(0x0017, "secp256r1", "1.2.840.10045.3.1.7", |
166 SECP256_R1(0x0017, "secp256r1", |
146 NamedGroupType.NAMED_GROUP_ECDHE, |
167 NamedGroupSpec.NAMED_GROUP_ECDHE, |
147 ProtocolVersion.PROTOCOLS_TO_13), |
168 ProtocolVersion.PROTOCOLS_TO_13, |
|
169 CurveDB.lookup("secp256r1")), |
148 |
170 |
149 // NIST P-384 |
171 // NIST P-384 |
150 SECP384_R1(0x0018, "secp384r1", "1.3.132.0.34", |
172 SECP384_R1(0x0018, "secp384r1", |
151 NamedGroupType.NAMED_GROUP_ECDHE, |
173 NamedGroupSpec.NAMED_GROUP_ECDHE, |
152 ProtocolVersion.PROTOCOLS_TO_13), |
174 ProtocolVersion.PROTOCOLS_TO_13, |
|
175 CurveDB.lookup("secp384r1")), |
153 |
176 |
154 // NIST P-521 |
177 // NIST P-521 |
155 SECP521_R1(0x0019, "secp521r1", "1.3.132.0.35", |
178 SECP521_R1(0x0019, "secp521r1", |
156 NamedGroupType.NAMED_GROUP_ECDHE, |
179 NamedGroupSpec.NAMED_GROUP_ECDHE, |
157 ProtocolVersion.PROTOCOLS_TO_13), |
180 ProtocolVersion.PROTOCOLS_TO_13, |
|
181 CurveDB.lookup("secp521r1")), |
158 |
182 |
159 // x25519 and x448 (RFC 8422/8446) |
183 // x25519 and x448 (RFC 8422/8446) |
160 X25519(0x001D, "x25519", "1.3.101.110", |
184 X25519(0x001D, "x25519", |
161 NamedGroupType.NAMED_GROUP_XDH, |
185 NamedGroupSpec.NAMED_GROUP_XDH, |
162 ProtocolVersion.PROTOCOLS_TO_13), |
186 ProtocolVersion.PROTOCOLS_TO_13, |
163 X448(0x001E, "x448", "1.3.101.111", |
187 NamedParameterSpec.X25519), |
164 NamedGroupType.NAMED_GROUP_XDH, |
188 X448(0x001E, "x448", |
165 ProtocolVersion.PROTOCOLS_TO_13), |
189 NamedGroupSpec.NAMED_GROUP_XDH, |
|
190 ProtocolVersion.PROTOCOLS_TO_13, |
|
191 NamedParameterSpec.X448), |
166 |
192 |
167 // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919) |
193 // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919) |
168 FFDHE_2048(0x0100, "ffdhe2048", null, |
194 FFDHE_2048(0x0100, "ffdhe2048", |
169 NamedGroupType.NAMED_GROUP_FFDHE, |
195 NamedGroupSpec.NAMED_GROUP_FFDHE, |
170 ProtocolVersion.PROTOCOLS_TO_13), |
196 ProtocolVersion.PROTOCOLS_TO_13, |
171 FFDHE_3072(0x0101, "ffdhe3072", null, |
197 PredefinedDHParameterSpecs.ffdheParams.get(2048)), |
172 NamedGroupType.NAMED_GROUP_FFDHE, |
198 |
173 ProtocolVersion.PROTOCOLS_TO_13), |
199 FFDHE_3072(0x0101, "ffdhe3072", |
174 FFDHE_4096(0x0102, "ffdhe4096", null, |
200 NamedGroupSpec.NAMED_GROUP_FFDHE, |
175 NamedGroupType.NAMED_GROUP_FFDHE, |
201 ProtocolVersion.PROTOCOLS_TO_13, |
176 ProtocolVersion.PROTOCOLS_TO_13), |
202 PredefinedDHParameterSpecs.ffdheParams.get(3072)), |
177 FFDHE_6144(0x0103, "ffdhe6144", null, |
203 FFDHE_4096(0x0102, "ffdhe4096", |
178 NamedGroupType.NAMED_GROUP_FFDHE, |
204 NamedGroupSpec.NAMED_GROUP_FFDHE, |
179 ProtocolVersion.PROTOCOLS_TO_13), |
205 ProtocolVersion.PROTOCOLS_TO_13, |
180 FFDHE_8192(0x0104, "ffdhe8192", null, |
206 PredefinedDHParameterSpecs.ffdheParams.get(4096)), |
181 NamedGroupType.NAMED_GROUP_FFDHE, |
207 FFDHE_6144(0x0103, "ffdhe6144", |
182 ProtocolVersion.PROTOCOLS_TO_13), |
208 NamedGroupSpec.NAMED_GROUP_FFDHE, |
|
209 ProtocolVersion.PROTOCOLS_TO_13, |
|
210 PredefinedDHParameterSpecs.ffdheParams.get(6144)), |
|
211 FFDHE_8192(0x0104, "ffdhe8192", |
|
212 NamedGroupSpec.NAMED_GROUP_FFDHE, |
|
213 ProtocolVersion.PROTOCOLS_TO_13, |
|
214 PredefinedDHParameterSpecs.ffdheParams.get(8192)), |
183 |
215 |
184 // Elliptic Curves (RFC 4492) |
216 // Elliptic Curves (RFC 4492) |
185 // |
217 // |
186 // arbitrary prime and characteristic-2 curves |
218 // arbitrary prime and characteristic-2 curves |
187 ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", null, |
219 ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", |
188 NamedGroupType.NAMED_GROUP_ARBITRARY, |
220 NamedGroupSpec.NAMED_GROUP_ARBITRARY, |
189 ProtocolVersion.PROTOCOLS_TO_12), |
221 ProtocolVersion.PROTOCOLS_TO_12, |
190 ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", null, |
222 null), |
191 NamedGroupType.NAMED_GROUP_ARBITRARY, |
223 ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", |
192 ProtocolVersion.PROTOCOLS_TO_12); |
224 NamedGroupSpec.NAMED_GROUP_ARBITRARY, |
|
225 ProtocolVersion.PROTOCOLS_TO_12, |
|
226 null); |
193 |
227 |
194 final int id; // hash + signature |
228 final int id; // hash + signature |
195 final NamedGroupType type; // group type |
|
196 final String name; // literal name |
229 final String name; // literal name |
197 final String oid; // object identifier of the named group |
230 final NamedGroupSpec spec; // group type |
198 final String algorithm; // signature algorithm |
|
199 final ProtocolVersion[] supportedProtocols; |
231 final ProtocolVersion[] supportedProtocols; |
200 private final NamedGroupFunctions functions; // may be null |
232 final String algorithm; // key exchange algorithm |
|
233 final AlgorithmParameterSpec keAlgParamSpec; |
|
234 final AlgorithmParameters keAlgParams; |
|
235 final boolean isAvailable; |
|
236 |
|
237 // performance optimization |
|
238 private static final Set<CryptoPrimitive> KEY_AGREEMENT_PRIMITIVE_SET = |
|
239 Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT)); |
201 |
240 |
202 // Constructor used for all NamedGroup types |
241 // Constructor used for all NamedGroup types |
203 private NamedGroup(int id, String name, String oid, |
242 private NamedGroup(int id, String name, |
204 NamedGroupType namedGroupType, |
243 NamedGroupSpec namedGroupSpec, |
205 ProtocolVersion[] supportedProtocols) { |
244 ProtocolVersion[] supportedProtocols, |
|
245 AlgorithmParameterSpec keAlgParamSpec) { |
206 this.id = id; |
246 this.id = id; |
207 this.name = name; |
247 this.name = name; |
208 this.oid = oid; |
248 this.spec = namedGroupSpec; |
209 this.type = namedGroupType; |
249 this.algorithm = namedGroupSpec.algorithm; |
210 this.supportedProtocols = supportedProtocols; |
250 this.supportedProtocols = supportedProtocols; |
211 |
251 this.keAlgParamSpec = keAlgParamSpec; |
212 if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) { |
252 |
213 this.functions = ECDHFunctions.getInstance(); |
253 AlgorithmParameters algParams = null; |
214 this.algorithm = "EC"; |
254 boolean mediator = (keAlgParamSpec != null); |
215 } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) { |
255 if (mediator) { |
216 this.functions = FFDHFunctions.getInstance(); |
256 try { |
217 this.algorithm = "DiffieHellman"; |
257 algParams = |
218 } else if (this.type == NamedGroupType.NAMED_GROUP_XDH) { |
258 AlgorithmParameters.getInstance(namedGroupSpec.algorithm); |
219 this.functions = XDHFunctions.getInstance(); |
259 algParams.init(keAlgParamSpec); |
220 this.algorithm = "XDH"; |
260 } catch (InvalidParameterSpecException |
221 } else if (this.type == NamedGroupType.NAMED_GROUP_ARBITRARY) { |
261 | NoSuchAlgorithmException exp) { |
222 this.functions = null; |
262 if (namedGroupSpec != NamedGroupSpec.NAMED_GROUP_XDH) { |
223 this.algorithm = "EC"; |
263 mediator = false; |
224 } else { |
264 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
225 throw new RuntimeException("Unexpected Named Group Type"); |
265 SSLLogger.warning( |
226 } |
266 "No AlgorithmParameters for " + name, exp); |
227 } |
267 } |
228 |
268 } else { |
229 private Optional<NamedGroupFunctions> getFunctions() { |
269 // HACK CODE |
230 return Optional.ofNullable(functions); |
270 // |
231 } |
271 // Please remove the following code if the XDH/X25519/X448 |
232 |
272 // AlgorithmParameters algorithms are supported in JDK. |
|
273 algParams = null; |
|
274 try { |
|
275 KeyAgreement.getInstance(name); |
|
276 |
|
277 // The following service is also needed. But for |
|
278 // performance, check the KeyAgreement impl only. |
|
279 // |
|
280 // KeyFactory.getInstance(name); |
|
281 // KeyPairGenerator.getInstance(name); |
|
282 // AlgorithmParameters.getInstance(name); |
|
283 } catch (NoSuchAlgorithmException nsae) { |
|
284 mediator = false; |
|
285 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
286 SSLLogger.warning( |
|
287 "No AlgorithmParameters for " + name, nsae); |
|
288 } |
|
289 } |
|
290 } |
|
291 } |
|
292 } |
|
293 |
|
294 this.isAvailable = mediator; |
|
295 this.keAlgParams = mediator ? algParams : null; |
|
296 } |
|
297 |
|
298 // |
233 // The next set of methods search & retrieve NamedGroups. |
299 // The next set of methods search & retrieve NamedGroups. |
234 |
300 // |
235 static NamedGroup valueOf(int id) { |
301 static NamedGroup valueOf(int id) { |
236 for (NamedGroup group : NamedGroup.values()) { |
302 for (NamedGroup group : NamedGroup.values()) { |
237 if (group.id == id) { |
303 if (group.id == id) { |
238 return group; |
304 return group; |
239 } |
305 } |
302 } |
355 } |
303 |
356 |
304 return "UNDEFINED-NAMED-GROUP(" + id + ")"; |
357 return "UNDEFINED-NAMED-GROUP(" + id + ")"; |
305 } |
358 } |
306 |
359 |
307 // Are the NamedGroups available for the protocol desired? |
360 // Is the NamedGroup available for the protocols desired? |
308 |
|
309 boolean isAvailable(List<ProtocolVersion> protocolVersions) { |
361 boolean isAvailable(List<ProtocolVersion> protocolVersions) { |
310 for (ProtocolVersion pv : supportedProtocols) { |
362 if (this.isAvailable) { |
311 if (protocolVersions.contains(pv)) { |
363 for (ProtocolVersion pv : supportedProtocols) { |
312 return true; |
364 if (protocolVersions.contains(pv)) { |
313 } |
365 return true; |
314 } |
366 } |
|
367 } |
|
368 } |
|
369 |
315 return false; |
370 return false; |
316 } |
371 } |
317 |
372 |
318 boolean isAvailable(ProtocolVersion protocolVersion) { |
373 boolean isAvailable(ProtocolVersion protocolVersion) { |
319 for (ProtocolVersion pv : supportedProtocols) { |
374 if (this.isAvailable) { |
320 if (protocolVersion == pv) { |
375 for (ProtocolVersion pv : supportedProtocols) { |
321 return true; |
376 if (protocolVersion == pv) { |
322 } |
377 return true; |
323 } |
378 } |
|
379 } |
|
380 } |
|
381 |
324 return false; |
382 return false; |
325 } |
383 } |
326 |
384 |
327 // Are the NamedGroups available for the ciphersuites desired? |
385 // Are the NamedGroups available for the ciphersuites desired? |
328 |
|
329 boolean isSupported(List<CipherSuite> cipherSuites) { |
386 boolean isSupported(List<CipherSuite> cipherSuites) { |
330 for (CipherSuite cs : cipherSuites) { |
387 for (CipherSuite cs : cipherSuites) { |
331 boolean isMatch = isAvailable(cs.supportedProtocols); |
388 boolean isMatch = isAvailable(cs.supportedProtocols); |
332 if (isMatch && ((cs.keyExchange == null) |
389 if (isMatch && ((cs.keyExchange == null) |
333 || (NamedGroupType.arrayContains( |
390 || (NamedGroupSpec.arrayContains( |
334 cs.keyExchange.groupTypes, type)))) { |
391 cs.keyExchange.groupTypes, spec)))) { |
335 return true; |
392 return true; |
336 } |
393 } |
337 } |
394 } |
|
395 |
338 return false; |
396 return false; |
339 } |
397 } |
340 |
398 |
341 // lazy loading of parameters |
399 boolean isPermitted(AlgorithmConstraints constraints) { |
342 AlgorithmParameters getParameters() { |
400 return constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET, |
343 Optional<NamedGroupFunctions> ngf = getFunctions(); |
401 this.name, null) && |
344 if (ngf.isEmpty()) { |
402 constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET, |
345 return null; |
403 this.algorithm, this.keAlgParams); |
346 } |
|
347 return ngf.get().getParameters(this); |
|
348 } |
|
349 |
|
350 // The next set of methods use the NamedGroupFunctions table |
|
351 // to do various operations in a consistent way. |
|
352 |
|
353 AlgorithmParameterSpec getParameterSpec() { |
|
354 Optional<NamedGroupFunctions> ngf = getFunctions(); |
|
355 if (ngf.isEmpty()) { |
|
356 return null; |
|
357 } |
|
358 return ngf.get().getParameterSpec(this); |
|
359 } |
404 } |
360 |
405 |
361 byte[] encodePossessionPublicKey( |
406 byte[] encodePossessionPublicKey( |
362 NamedGroupPossession namedGroupPossession) { |
407 NamedGroupPossession namedGroupPossession) { |
363 |
408 return spec.encodePossessionPublicKey(namedGroupPossession); |
364 Optional<NamedGroupFunctions> ngf = getFunctions(); |
|
365 if (ngf.isEmpty()) { |
|
366 return null; |
|
367 } |
|
368 return ngf.get().encodePossessionPublicKey(namedGroupPossession); |
|
369 } |
409 } |
370 |
410 |
371 SSLCredentials decodeCredentials(byte[] encoded, |
411 SSLCredentials decodeCredentials(byte[] encoded, |
372 AlgorithmConstraints constraints, |
412 AlgorithmConstraints constraints, |
373 ExceptionSupplier onConstraintFail) |
413 ExceptionSupplier onConstraintFail) |
374 throws IOException, GeneralSecurityException { |
414 throws IOException, GeneralSecurityException { |
375 |
415 return spec.decodeCredentials( |
376 Optional<NamedGroupFunctions> ngf = getFunctions(); |
416 this, encoded, constraints, onConstraintFail); |
377 if (ngf.isEmpty()) { |
|
378 return null; |
|
379 } |
|
380 return ngf.get().decodeCredentials(this, encoded, constraints, |
|
381 onConstraintFail); |
|
382 } |
417 } |
383 |
418 |
384 SSLPossession createPossession(SecureRandom random) { |
419 SSLPossession createPossession(SecureRandom random) { |
385 |
420 return spec.createPossession(this, random); |
386 Optional<NamedGroupFunctions> ngf = getFunctions(); |
421 } |
387 if (ngf.isEmpty()) { |
422 |
388 return null; |
423 SSLKeyDerivation createKeyDerivation( |
389 } |
424 HandshakeContext hc) throws IOException { |
390 return ngf.get().createPossession(this, random); |
425 return spec.createKeyDerivation(hc); |
391 } |
426 } |
392 |
427 |
393 SSLKeyDerivation createKeyDerivation(HandshakeContext hc) |
428 interface ExceptionSupplier { |
394 throws IOException { |
429 void apply(String s) throws SSLException; |
395 |
430 } |
396 Optional<NamedGroupFunctions> ngf = getFunctions(); |
431 |
397 if (ngf.isEmpty()) { |
432 // A list of operations related to named groups. |
398 return null; |
433 private interface NamedGroupScheme { |
399 } |
434 default void checkConstraints(PublicKey publicKey, |
400 return ngf.get().createKeyDerivation(hc); |
435 AlgorithmConstraints constraints, |
401 |
436 ExceptionSupplier onConstraintFail) throws SSLException { |
402 } |
437 if (!constraints.permits( |
403 |
438 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) { |
404 boolean isAvailableGroup() { |
439 onConstraintFail.apply("key share entry does not " |
405 Optional<NamedGroupFunctions> ngfOpt = getFunctions(); |
440 + "comply with algorithm constraints"); |
406 if (ngfOpt.isEmpty()) { |
441 } |
407 return false; |
442 } |
408 } |
443 |
409 NamedGroupFunctions ngf = ngfOpt.get(); |
444 byte[] encodePossessionPublicKey( |
410 return ngf.isAvailable(this); |
445 NamedGroupPossession namedGroupPossession); |
411 } |
446 |
412 |
447 SSLCredentials decodeCredentials( |
413 enum NamedGroupType { |
448 NamedGroup ng, byte[] encoded, |
414 NAMED_GROUP_ECDHE, // Elliptic Curve Groups (ECDHE) |
449 AlgorithmConstraints constraints, |
415 NAMED_GROUP_FFDHE, // Finite Field Groups (DHE) |
450 ExceptionSupplier onConstraintFail |
416 NAMED_GROUP_XDH, // Finite Field Groups (XDH) |
451 ) throws IOException, GeneralSecurityException; |
417 NAMED_GROUP_ARBITRARY, // arbitrary prime and curves (ECDHE) |
452 |
418 NAMED_GROUP_NONE; // Not predefined named group |
453 SSLPossession createPossession(NamedGroup ng, SecureRandom random); |
|
454 |
|
455 SSLKeyDerivation createKeyDerivation( |
|
456 HandshakeContext hc) throws IOException; |
|
457 } |
|
458 |
|
459 enum NamedGroupSpec implements NamedGroupScheme { |
|
460 // Elliptic Curve Groups (ECDHE) |
|
461 NAMED_GROUP_ECDHE("EC", ECDHEScheme.instance), |
|
462 |
|
463 // Finite Field Groups (DHE) |
|
464 NAMED_GROUP_FFDHE("DiffieHellman", FFDHEScheme.instance), |
|
465 |
|
466 // Finite Field Groups (XDH) |
|
467 NAMED_GROUP_XDH("XDH", XDHScheme.instance), |
|
468 |
|
469 // arbitrary prime and curves (ECDHE) |
|
470 NAMED_GROUP_ARBITRARY("EC", null), |
|
471 |
|
472 // Not predefined named group |
|
473 NAMED_GROUP_NONE("", null); |
|
474 |
|
475 private final String algorithm; // key exchange name |
|
476 private final NamedGroupScheme scheme; // named group operations |
|
477 |
|
478 private NamedGroupSpec(String algorithm, NamedGroupScheme scheme) { |
|
479 this.algorithm = algorithm; |
|
480 this.scheme = scheme; |
|
481 } |
419 |
482 |
420 boolean isSupported(List<CipherSuite> cipherSuites) { |
483 boolean isSupported(List<CipherSuite> cipherSuites) { |
421 for (CipherSuite cs : cipherSuites) { |
484 for (CipherSuite cs : cipherSuites) { |
422 if (cs.keyExchange == null || |
485 if (cs.keyExchange == null || |
423 arrayContains(cs.keyExchange.groupTypes, this)) { |
486 arrayContains(cs.keyExchange.groupTypes, this)) { |
426 } |
489 } |
427 |
490 |
428 return false; |
491 return false; |
429 } |
492 } |
430 |
493 |
431 static boolean arrayContains(NamedGroupType[] namedGroupTypes, |
494 static boolean arrayContains(NamedGroupSpec[] namedGroupTypes, |
432 NamedGroupType namedGroupType) { |
495 NamedGroupSpec namedGroupType) { |
433 for (NamedGroupType ng : namedGroupTypes) { |
496 for (NamedGroupSpec ng : namedGroupTypes) { |
434 if (ng == namedGroupType) { |
497 if (ng == namedGroupType) { |
435 return true; |
498 return true; |
436 } |
499 } |
437 } |
500 } |
|
501 |
438 return false; |
502 return false; |
439 } |
503 } |
440 } |
504 |
441 |
505 @Override |
442 interface ExceptionSupplier { |
506 public byte[] encodePossessionPublicKey( |
443 void apply(String s) throws SSLException; |
507 NamedGroupPossession namedGroupPossession) { |
444 } |
508 if (scheme != null) { |
445 |
509 return scheme.encodePossessionPublicKey(namedGroupPossession); |
446 /* |
510 } |
447 * A list of functions to do NamedGroup operations in a |
511 |
448 * algorithm-independent and consistent way. |
512 return null; |
449 */ |
513 } |
450 private static abstract class NamedGroupFunctions { |
514 |
451 |
515 @Override |
452 // cache to speed up the parameters construction |
516 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded, |
453 protected static final Map<NamedGroup, AlgorithmParameters> |
517 AlgorithmConstraints constraints, |
454 namedGroupParams = new ConcurrentHashMap<>(); |
518 ExceptionSupplier onConstraintFail |
455 |
519 ) throws IOException, GeneralSecurityException { |
456 protected void checkConstraints(PublicKey publicKey, |
520 if (scheme != null) { |
457 AlgorithmConstraints constraints, |
521 return scheme.decodeCredentials( |
458 ExceptionSupplier onConstraintFail) |
522 ng, encoded, constraints, onConstraintFail); |
459 throws SSLException { |
523 } |
460 |
524 |
461 if (!constraints.permits( |
525 return null; |
462 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), |
526 } |
463 publicKey)) { |
527 |
464 |
528 @Override |
465 onConstraintFail.apply("key share entry does not " |
529 public SSLPossession createPossession( |
466 + "comply with algorithm constraints"); |
530 NamedGroup ng, SecureRandom random) { |
467 } |
531 if (scheme != null) { |
468 } |
532 return scheme.createPossession(ng, random); |
469 |
533 } |
470 public AlgorithmParameters getParameters(NamedGroup ng) { |
534 |
471 |
535 return null; |
472 AlgorithmParameters result = namedGroupParams.get(ng); |
536 } |
473 if (result == null) { |
537 |
474 Optional<AlgorithmParameters> paramsOpt = getParametersImpl(ng); |
538 @Override |
475 if (paramsOpt.isPresent()) { |
539 public SSLKeyDerivation createKeyDerivation( |
476 result = paramsOpt.get(); |
540 HandshakeContext hc) throws IOException { |
477 namedGroupParams.put(ng, result); |
541 if (scheme != null) { |
478 } |
542 return scheme.createKeyDerivation(hc); |
479 } |
543 } |
480 |
544 |
481 return result; |
545 return null; |
482 } |
546 } |
483 |
547 } |
484 public abstract byte[] encodePossessionPublicKey( |
548 |
485 NamedGroupPossession namedGroupPossession); |
549 private static class FFDHEScheme implements NamedGroupScheme { |
486 |
550 private static final FFDHEScheme instance = new FFDHEScheme(); |
487 public abstract SSLCredentials decodeCredentials( |
|
488 NamedGroup ng, byte[] encoded, |
|
489 AlgorithmConstraints constraints, |
|
490 ExceptionSupplier onConstraintFail) |
|
491 throws IOException, GeneralSecurityException; |
|
492 |
|
493 public abstract SSLPossession createPossession(NamedGroup ng, |
|
494 SecureRandom random); |
|
495 |
|
496 public abstract SSLKeyDerivation createKeyDerivation( |
|
497 HandshakeContext hc) throws IOException; |
|
498 |
|
499 protected abstract Optional<AlgorithmParameters> getParametersImpl( |
|
500 NamedGroup ng); |
|
501 |
|
502 public abstract AlgorithmParameterSpec getParameterSpec(NamedGroup ng); |
|
503 |
|
504 public abstract boolean isAvailable(NamedGroup ng); |
|
505 } |
|
506 |
|
507 private static class FFDHFunctions extends NamedGroupFunctions { |
|
508 |
|
509 // lazy initialization |
|
510 private static class FunctionsHolder { |
|
511 private static final FFDHFunctions instance = new FFDHFunctions(); |
|
512 } |
|
513 |
|
514 private static FFDHFunctions getInstance() { |
|
515 return FunctionsHolder.instance; |
|
516 } |
|
517 |
551 |
518 @Override |
552 @Override |
519 public byte[] encodePossessionPublicKey( |
553 public byte[] encodePossessionPublicKey( |
520 NamedGroupPossession namedGroupPossession) { |
554 NamedGroupPossession namedGroupPossession) { |
521 return ((DHEPossession)namedGroupPossession).encode(); |
555 return ((DHEPossession)namedGroupPossession).encode(); |
522 } |
556 } |
523 |
557 |
524 @Override |
558 @Override |
525 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded, |
559 public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded, |
526 AlgorithmConstraints constraints, |
560 AlgorithmConstraints constraints, |
527 ExceptionSupplier onConstraintFail) |
561 ExceptionSupplier onConstraintFail |
528 throws IOException, GeneralSecurityException { |
562 ) throws IOException, GeneralSecurityException { |
529 |
563 |
530 DHKeyExchange.DHECredentials result |
564 DHKeyExchange.DHECredentials result |
531 = DHKeyExchange.DHECredentials.valueOf(ng, encoded); |
565 = DHKeyExchange.DHECredentials.valueOf(ng, encoded); |
532 |
566 |
533 checkConstraints(result.getPublicKey(), constraints, |
567 checkConstraints(result.getPublicKey(), constraints, |