Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/net/ssl/TLSCommon/SSLEngineTestCase.java
38853 views
1
/*
2
* Copyright (c) 2015, 2018, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import javax.net.ssl.KeyManagerFactory;
25
import javax.net.ssl.SNIHostName;
26
import javax.net.ssl.SNIMatcher;
27
import javax.net.ssl.SNIServerName;
28
import javax.net.ssl.SSLContext;
29
import javax.net.ssl.SSLEngine;
30
import javax.net.ssl.SSLSession;
31
import javax.net.ssl.SSLEngineResult;
32
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
33
import javax.net.ssl.SSLException;
34
import javax.net.ssl.SSLParameters;
35
import javax.net.ssl.TrustManagerFactory;
36
import java.io.File;
37
import java.io.FileInputStream;
38
import java.io.IOException;
39
import java.lang.reflect.Field;
40
import java.nio.ByteBuffer;
41
import java.security.KeyManagementException;
42
import java.security.KeyStore;
43
import java.security.KeyStoreException;
44
import java.security.NoSuchAlgorithmException;
45
import java.security.UnrecoverableKeyException;
46
import java.security.cert.CertificateException;
47
import java.util.ArrayList;
48
import java.util.Arrays;
49
import java.util.HashMap;
50
import java.util.LinkedList;
51
import java.util.List;
52
import java.util.Map;
53
54
/**
55
* Basic class to inherit SSLEngine test cases from it. Tests apply for
56
* the TLS security protocols and their versions.
57
*/
58
abstract public class SSLEngineTestCase {
59
60
public enum Ciphers {
61
62
/**
63
* Ciphers supported by the tested SSLEngine without those with
64
* kerberos authentication.
65
*/
66
SUPPORTED_NON_KRB_CIPHERS(SSLEngineTestCase.SUPPORTED_NON_KRB_CIPHERS,
67
"Supported non kerberos"),
68
/**
69
* Ciphers supported by the tested SSLEngine without those with
70
* kerberos authentication and without those with SHA256 ans SHA384.
71
*/
72
SUPPORTED_NON_KRB_NON_SHA_CIPHERS(
73
SSLEngineTestCase.SUPPORTED_NON_KRB_NON_SHA_CIPHERS,
74
"Supported non kerberos non SHA256 and SHA384"),
75
/**
76
* Ciphers supported by the tested SSLEngine with kerberos
77
* authentication.
78
*/
79
SUPPORTED_KRB_CIPHERS(SSLEngineTestCase.SUPPORTED_KRB_CIPHERS,
80
"Supported kerberos"),
81
/**
82
* Ciphers enabled by default for the tested SSLEngine without kerberos
83
* and anon.
84
*/
85
ENABLED_NON_KRB_NOT_ANON_CIPHERS(
86
SSLEngineTestCase.ENABLED_NON_KRB_NOT_ANON_CIPHERS,
87
"Enabled by default non kerberos not anonymous"),
88
/**
89
* Ciphers supported by TLS 1.3 only.
90
*/
91
TLS13_CIPHERS(
92
SSLEngineTestCase.TLS13_CIPHERS,
93
"Supported by TLS 1.3 only"),
94
/**
95
* Ciphers unsupported by the tested SSLEngine.
96
*/
97
UNSUPPORTED_CIPHERS(SSLEngineTestCase.UNSUPPORTED_CIPHERS,
98
"Unsupported");
99
100
Ciphers(String[] ciphers, String description) {
101
this.ciphers = ciphers;
102
this.description = description;
103
}
104
105
final String[] ciphers;
106
final String description;
107
}
108
109
/**
110
* Enumeration used to distinguish handshake mode in
111
* {@link SSLEngineTestCase#doHandshake(javax.net.ssl.SSLEngine,
112
* javax.net.ssl.SSLEngine, int, SSLEngineTestCase.HandshakeMode, boolean)
113
* SSLEngineTestCase.doHandshake} method.
114
*/
115
public enum HandshakeMode {
116
117
/**
118
* Initial handshake done for the first time: both engines call
119
* {@link SSLEngine#beginHandshake()} method.
120
*/
121
INITIAL_HANDSHAKE,
122
/**
123
* Repeated handshake done by client: client engine calls
124
* {@link SSLEngine#beginHandshake()} method.
125
*/
126
REHANDSHAKE_BEGIN_CLIENT,
127
/**
128
* Repeated handshake done by server: server engine calls
129
* {@link SSLEngine#beginHandshake()} method.
130
*/
131
REHANDSHAKE_BEGIN_SERVER;
132
}
133
/**
134
* Security protocol to be tested: "TLS" or their versions,
135
* e.g. "TLSv1", "TLSv1.1", "TLSv1.2".
136
*/
137
public static final String TESTED_SECURITY_PROTOCOL
138
= System.getProperty("test.security.protocol", "TLS");
139
/**
140
* Test mode: "norm", "norm_sni" or "krb".
141
* Modes "norm" and "norm_sni" are used to run
142
* with all supported non-kerberos ciphers.
143
* Mode "krb" is used to run with kerberos ciphers.
144
*/
145
public static final String TEST_MODE
146
= System.getProperty("test.mode", "norm");
147
148
private static final String FS = System.getProperty("file.separator", "/");
149
private static final String PATH_TO_STORES = ".." + FS + "etc";
150
private static final String KEY_STORE_FILE = "keystore";
151
private static final String TRUST_STORE_FILE = "truststore";
152
private static final String PASSWD = "passphrase";
153
154
private static final String KEY_FILE_NAME
155
= System.getProperty("test.src", ".") + FS + PATH_TO_STORES
156
+ FS + KEY_STORE_FILE;
157
private static final String TRUST_FILE_NAME
158
= System.getProperty("test.src", ".") + FS + PATH_TO_STORES
159
+ FS + TRUST_STORE_FILE;
160
161
// Need an enhancement to use none-static mutable global variables.
162
private static ByteBuffer net;
163
private static boolean doUnwrapForNotHandshakingStatus;
164
private static boolean endHandshakeLoop = false;
165
166
private static final int MAX_HANDSHAKE_LOOPS = 100;
167
private static final String EXCHANGE_MSG_SENT = "Hello, peer!";
168
private static final String TEST_SRC = System.getProperty("test.src", ".");
169
private static final String KTAB_FILENAME = "krb5.keytab.data";
170
private static final String KRB_REALM = "TEST.REALM";
171
private static final String KRBTGT_PRINCIPAL = "krbtgt/" + KRB_REALM;
172
private static final String KRB_USER = "USER";
173
private static final String KRB_USER_PASSWORD = "password";
174
private static final String KRB_USER_PRINCIPAL = KRB_USER + "@" + KRB_REALM;
175
private static final String KRB5_CONF_FILENAME = "krb5.conf";
176
private static final String PATH_TO_COMMON = ".." + FS + "TLSCommon";
177
private static final String JAAS_CONF_FILE = PATH_TO_COMMON
178
+ FS + "jaas.conf";
179
private static final int DELAY = 1000;
180
private static final String HOST = "localhost";
181
private static final String SERVER_NAME = "service.localhost";
182
private static final String SNI_PATTERN = ".*";
183
184
private static final String[] TLS13_CIPHERS = {
185
"TLS_AES_256_GCM_SHA384",
186
"TLS_AES_128_GCM_SHA256"
187
};
188
189
private static final String[] SUPPORTED_NON_KRB_CIPHERS;
190
191
static {
192
try {
193
String[] allSupportedCiphers = getContext()
194
.createSSLEngine().getSupportedCipherSuites();
195
List<String> supportedCiphersList = new LinkedList<>();
196
for (String cipher : allSupportedCiphers) {
197
if (!cipher.contains("KRB5")
198
&& !isTLS13Cipher(cipher)
199
&& !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
200
supportedCiphersList.add(cipher);
201
}
202
}
203
SUPPORTED_NON_KRB_CIPHERS =
204
supportedCiphersList.toArray(new String[0]);
205
} catch (Exception ex) {
206
throw new Error("Unexpected issue", ex);
207
}
208
}
209
210
private static final String[] SUPPORTED_NON_KRB_NON_SHA_CIPHERS;
211
212
static {
213
try {
214
String[] allSupportedCiphers = getContext()
215
.createSSLEngine().getSupportedCipherSuites();
216
List<String> supportedCiphersList = new LinkedList<>();
217
for (String cipher : allSupportedCiphers) {
218
if (!cipher.contains("KRB5")
219
&& !isTLS13Cipher(cipher)
220
&& !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")
221
&& !cipher.endsWith("_SHA256")
222
&& !cipher.endsWith("_SHA384")) {
223
supportedCiphersList.add(cipher);
224
}
225
}
226
SUPPORTED_NON_KRB_NON_SHA_CIPHERS
227
= supportedCiphersList.toArray(new String[0]);
228
} catch (Exception ex) {
229
throw new Error("Unexpected issue", ex);
230
}
231
}
232
233
private static final String[] SUPPORTED_KRB_CIPHERS;
234
235
static {
236
try {
237
String[] allSupportedCiphers = getContext()
238
.createSSLEngine().getSupportedCipherSuites();
239
List<String> supportedCiphersList = new LinkedList<>();
240
for (String cipher : allSupportedCiphers) {
241
if (cipher.contains("KRB5")
242
&& !isTLS13Cipher(cipher)
243
&& !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
244
supportedCiphersList.add(cipher);
245
}
246
}
247
SUPPORTED_KRB_CIPHERS = supportedCiphersList.toArray(new String[0]);
248
} catch (Exception ex) {
249
throw new Error("Unexpected issue", ex);
250
}
251
}
252
253
private static final String[] ENABLED_NON_KRB_NOT_ANON_CIPHERS;
254
255
static {
256
try {
257
SSLEngine temporary = getContext().createSSLEngine();
258
temporary.setUseClientMode(true);
259
String[] enabledCiphers = temporary.getEnabledCipherSuites();
260
List<String> enabledCiphersList = new LinkedList<>();
261
for (String cipher : enabledCiphers) {
262
if (!cipher.contains("anon") && !cipher.contains("KRB5")
263
&& !isTLS13Cipher(cipher)
264
&& !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
265
enabledCiphersList.add(cipher);
266
}
267
}
268
ENABLED_NON_KRB_NOT_ANON_CIPHERS =
269
enabledCiphersList.toArray(new String[0]);
270
} catch (Exception ex) {
271
throw new Error("Unexpected issue", ex);
272
}
273
}
274
275
private static final String[] UNSUPPORTED_CIPHERS = {
276
"SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA",
277
"SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA",
278
"SSL_DHE_DSS_WITH_RC4_128_SHA",
279
"SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",
280
"SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",
281
"SSL_DH_DSS_WITH_DES_CBC_SHA",
282
"SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",
283
"SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",
284
"SSL_DH_RSA_WITH_DES_CBC_SHA",
285
"SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",
286
"SSL_FORTEZZA_DMS_WITH_NULL_SHA",
287
"SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA",
288
"SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",
289
"SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",
290
"SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",
291
"SSL_RSA_FIPS_WITH_DES_CBC_SHA",
292
"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",
293
"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",
294
"TLS_KRB5_WITH_IDEA_CBC_MD5",
295
"TLS_KRB5_WITH_IDEA_CBC_SHA",
296
"SSL_RSA_WITH_IDEA_CBC_SHA",
297
"TLS_DH_RSA_WITH_AES_128_GCM_SHA256",
298
"TLS_DH_RSA_WITH_AES_256_GCM_SHA384",
299
"TLS_DH_DSS_WITH_AES_128_GCM_SHA256",
300
"TLS_DH_DSS_WITH_AES_256_GCM_SHA384"
301
};
302
303
private final int maxPacketSize;
304
305
// to access maximumPacketSize and packetSize protected fields
306
static Class<?> sslEngineImplClz;
307
static Class<?> transportContextClz;
308
static Class<?> sslConfigurationClz;
309
static Class<?> outputRecordClz;
310
static Field conContextFld;
311
static Field sslConfigFld;
312
static Field maximumPacketSizeFld;
313
static Field outputRecordFld;
314
static Field packetSizeFld;
315
316
static {
317
try {
318
sslEngineImplClz = Class.forName("sun.security.ssl.SSLEngineImpl");
319
transportContextClz = Class.forName("sun.security.ssl.TransportContext");
320
sslConfigurationClz = Class.forName("sun.security.ssl.SSLConfiguration");
321
outputRecordClz = Class.forName("sun.security.ssl.OutputRecord");
322
323
conContextFld = sslEngineImplClz.getDeclaredField("conContext");
324
sslConfigFld = transportContextClz.getDeclaredField("sslConfig");
325
outputRecordFld = transportContextClz.getDeclaredField("outputRecord");
326
maximumPacketSizeFld = sslConfigurationClz.getDeclaredField("maximumPacketSize");
327
packetSizeFld = outputRecordClz.getDeclaredField("packetSize");
328
329
conContextFld.setAccessible(true);
330
sslConfigFld.setAccessible(true);
331
outputRecordFld.setAccessible(true);
332
maximumPacketSizeFld.setAccessible(true);
333
packetSizeFld.setAccessible(true);
334
} catch (Exception x) {
335
throw new RuntimeException(x);
336
}
337
}
338
339
public static void setMaxPacketSize(SSLEngine sslEngine, int maxPacketSize) {
340
try {
341
Object conContext = conContextFld.get(sslEngine);
342
Object sslConfig = sslConfigFld.get(conContext);
343
maximumPacketSizeFld.setInt(sslConfig, maxPacketSize);
344
345
if (maxPacketSize != 0) {
346
Object outputRecord = outputRecordFld.get(conContext);
347
packetSizeFld.setInt(outputRecord, maxPacketSize);
348
}
349
} catch(IllegalAccessException | IllegalArgumentException iae) {
350
throw new RuntimeException(iae);
351
}
352
}
353
354
/**
355
* Constructs test case with the given MFLN maxMacketSize.
356
*
357
* @param maxPacketSize - MLFN extension max packet size.
358
*/
359
public SSLEngineTestCase(int maxPacketSize) {
360
this.maxPacketSize = maxPacketSize;
361
}
362
363
/**
364
* Constructs test case with {@code maxPacketSize = 0}.
365
*/
366
public SSLEngineTestCase() {
367
this.maxPacketSize = 0;
368
}
369
370
private static boolean isTLS13Cipher(String cipher) {
371
for (String cipherSuite : TLS13_CIPHERS) {
372
if (cipherSuite.equals(cipher)) {
373
return true;
374
}
375
}
376
377
return false;
378
}
379
380
/**
381
* Wraps data with the specified engine.
382
*
383
* @param engine - SSLEngine that wraps data.
384
* @param wrapper - Set wrapper id, e.g. "server" of "client".
385
* Used for logging only.
386
* @param maxPacketSize - Max packet size to check that MFLN extension
387
* works or zero for no check.
388
* @param app - Buffer with data to wrap.
389
* @return - Buffer with wrapped data.
390
* @throws SSLException - thrown on engine errors.
391
*/
392
public static ByteBuffer doWrap(SSLEngine engine, String wrapper,
393
int maxPacketSize, ByteBuffer app)
394
throws SSLException {
395
return doWrap(engine, wrapper, maxPacketSize,
396
app, SSLEngineResult.Status.OK, null);
397
}
398
399
/**
400
* Wraps data with the specified engine.
401
*
402
* @param engine - SSLEngine that wraps data.
403
* @param wrapper - Set wrapper id, e.g. "server" of "client".
404
* Used for logging only.
405
* @param maxPacketSize - Max packet size to check that MFLN extension
406
* works or zero for no check.
407
* @param app - Buffer with data to wrap.
408
* @param result - Array which first element will be used to
409
* output wrap result object.
410
* @return - Buffer with wrapped data.
411
* @throws SSLException - thrown on engine errors.
412
*/
413
public static ByteBuffer doWrap(SSLEngine engine, String wrapper,
414
int maxPacketSize, ByteBuffer app,
415
SSLEngineResult[] result)
416
throws SSLException {
417
return doWrap(engine, wrapper, maxPacketSize,
418
app, SSLEngineResult.Status.OK, result);
419
}
420
421
/**
422
* Wraps data with the specified engine.
423
*
424
* @param engine - SSLEngine that wraps data.
425
* @param wrapper - Set wrapper id, e.g. "server" of "client".
426
* Used for logging only.
427
* @param maxPacketSize - Max packet size to check that MFLN extension
428
* works or zero for no check.
429
* @param app - Buffer with data to wrap.
430
* @param wantedStatus - Specifies expected result status of wrapping.
431
* @return - Buffer with wrapped data.
432
* @throws SSLException - thrown on engine errors.
433
*/
434
public static ByteBuffer doWrap(SSLEngine engine, String wrapper,
435
int maxPacketSize, ByteBuffer app,
436
SSLEngineResult.Status wantedStatus)
437
throws SSLException {
438
return doWrap(engine, wrapper, maxPacketSize,
439
app, wantedStatus, null);
440
}
441
442
/**
443
* Wraps data with the specified engine.
444
*
445
* @param engine - SSLEngine that wraps data.
446
* @param wrapper - Set wrapper id, e.g. "server" of "client".
447
* Used for logging only.
448
* @param maxPacketSize - Max packet size to check that MFLN extension
449
* works or zero for no check.
450
* @param app - Buffer with data to wrap.
451
* @param wantedStatus - Specifies expected result status of wrapping.
452
* @param result - Array which first element will be used to output
453
* wrap result object.
454
* @return - Buffer with wrapped data.
455
* @throws SSLException - thrown on engine errors.
456
*/
457
public static ByteBuffer doWrap(SSLEngine engine, String wrapper,
458
int maxPacketSize, ByteBuffer app,
459
SSLEngineResult.Status wantedStatus,
460
SSLEngineResult[] result)
461
throws SSLException {
462
ByteBuffer net = ByteBuffer.allocate(engine.getSession()
463
.getPacketBufferSize());
464
SSLEngineResult r = engine.wrap(app, net);
465
net.flip();
466
int length = net.remaining();
467
System.out.println(wrapper + " wrapped " + length + " bytes.");
468
System.out.println(wrapper + " handshake status is "
469
+ engine.getHandshakeStatus() + " Result is " + r.getStatus());
470
if (maxPacketSize < length && maxPacketSize != 0) {
471
throw new AssertionError("Handshake wrapped net buffer length "
472
+ length + " exceeds maximum packet size "
473
+ maxPacketSize);
474
}
475
checkResult(r, wantedStatus);
476
if (result != null && result.length > 0) {
477
result[0] = r;
478
}
479
return net;
480
}
481
482
/**
483
* Unwraps data with the specified engine.
484
*
485
* @param engine - SSLEngine that unwraps data.
486
* @param unwrapper - Set unwrapper id, e.g. "server" of "client". Used for
487
* logging only.
488
* @param net - Buffer with data to unwrap.
489
* @return - Buffer with unwrapped data.
490
* @throws SSLException - thrown on engine errors.
491
*/
492
public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper,
493
ByteBuffer net) throws SSLException {
494
return doUnWrap(engine, unwrapper,
495
net, SSLEngineResult.Status.OK, null);
496
}
497
498
/**
499
* Unwraps data with the specified engine.
500
*
501
* @param engine - SSLEngine that unwraps data.
502
* @param unwrapper - Set unwrapper id, e.g. "server" of "client". Used for
503
* logging only.
504
* @param net - Buffer with data to unwrap.
505
* @param result - Array which first element will be used to output wrap
506
* result object.
507
* @return - Buffer with unwrapped data.
508
* @throws SSLException - thrown on engine errors.
509
*/
510
public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper,
511
ByteBuffer net, SSLEngineResult[] result) throws SSLException {
512
return doUnWrap(engine, unwrapper,
513
net, SSLEngineResult.Status.OK, result);
514
}
515
516
/**
517
* Unwraps data with the specified engine.
518
*
519
* @param engine - SSLEngine that unwraps data.
520
* @param unwrapper - Set unwrapper id, e.g. "server" of "client".
521
* Used for logging only.
522
* @param net - Buffer with data to unwrap.
523
* @param wantedStatus - Specifies expected result status of wrapping.
524
* @return - Buffer with unwrapped data.
525
* @throws SSLException - thrown on engine errors.
526
*/
527
public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper,
528
ByteBuffer net,
529
SSLEngineResult.Status wantedStatus) throws SSLException {
530
return doUnWrap(engine, unwrapper, net, wantedStatus, null);
531
}
532
533
/**
534
* Unwraps data with the specified engine.
535
*
536
* @param engine - SSLEngine that unwraps data.
537
* @param unwrapper - Set unwrapper id, e.g. "server" of "client".
538
* Used for logging only.
539
* @param net - Buffer with data to unwrap.
540
* @param wantedStatus - Specifies expected result status of wrapping.
541
* @param result - Array which first element will be used to output
542
* wrap result object.
543
* @return - Buffer with unwrapped data.
544
* @throws SSLException - thrown on engine errors.
545
*/
546
public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper,
547
ByteBuffer net, SSLEngineResult.Status wantedStatus,
548
SSLEngineResult[] result) throws SSLException {
549
550
ByteBuffer app = ByteBuffer.allocate(
551
engine.getSession().getApplicationBufferSize());
552
int length = net.remaining();
553
System.out.println(unwrapper + " unwrapping " + length + " bytes...");
554
SSLEngineResult r = engine.unwrap(net, app);
555
app.flip();
556
System.out.println(unwrapper + " handshake status is "
557
+ engine.getHandshakeStatus() + " Result is " + r.getStatus());
558
checkResult(r, wantedStatus);
559
if (result != null && result.length > 0) {
560
result[0] = r;
561
}
562
return app;
563
}
564
565
/**
566
* Does the handshake of the two specified engines according to the
567
* {@code mode} specified.
568
*
569
* @param clientEngine - Client SSLEngine.
570
* @param serverEngine - Server SSLEngine.
571
* @param maxPacketSize - Maximum packet size for MFLN of zero for no limit.
572
* @param mode - Handshake mode according to
573
* {@link HandshakeMode} enum.
574
* @throws SSLException - thrown on engine errors.
575
*/
576
public static void doHandshake(SSLEngine clientEngine,
577
SSLEngine serverEngine,
578
int maxPacketSize, HandshakeMode mode) throws SSLException {
579
580
doHandshake(clientEngine, serverEngine, maxPacketSize, mode, false);
581
}
582
583
/**
584
* Does the handshake of the two specified engines according to the
585
* {@code mode} specified.
586
*
587
* @param clientEngine - Client SSLEngine.
588
* @param serverEngine - Server SSLEngine.
589
* @param maxPacketSize - Maximum packet size for MFLN of zero
590
* for no limit.
591
* @param mode - Handshake mode according to
592
* {@link HandshakeMode} enum.
593
* @param enableReplicatedPacks - Set {@code true} to enable replicated
594
* packet sending.
595
* @throws SSLException - thrown on engine errors.
596
*/
597
public static void doHandshake(SSLEngine clientEngine,
598
SSLEngine serverEngine, int maxPacketSize,
599
HandshakeMode mode,
600
boolean enableReplicatedPacks) throws SSLException {
601
602
System.out.println("=============================================");
603
System.out.println("Starting handshake " + mode.name());
604
int loop = 0;
605
if (maxPacketSize < 0) {
606
throw new Error("Test issue: maxPacketSize is less than zero!");
607
}
608
setMaxPacketSize(clientEngine, maxPacketSize);
609
setMaxPacketSize(serverEngine, maxPacketSize);
610
SSLEngine firstEngine;
611
SSLEngine secondEngine;
612
switch (mode) {
613
case INITIAL_HANDSHAKE:
614
firstEngine = clientEngine;
615
secondEngine = serverEngine;
616
doUnwrapForNotHandshakingStatus = false;
617
clientEngine.beginHandshake();
618
serverEngine.beginHandshake();
619
break;
620
case REHANDSHAKE_BEGIN_CLIENT:
621
firstEngine = clientEngine;
622
secondEngine = serverEngine;
623
doUnwrapForNotHandshakingStatus = true;
624
clientEngine.beginHandshake();
625
break;
626
case REHANDSHAKE_BEGIN_SERVER:
627
firstEngine = serverEngine;
628
secondEngine = clientEngine;
629
doUnwrapForNotHandshakingStatus = true;
630
serverEngine.beginHandshake();
631
break;
632
default:
633
throw new Error("Test issue: unknown handshake mode");
634
}
635
endHandshakeLoop = false;
636
while (!endHandshakeLoop) {
637
if (++loop > MAX_HANDSHAKE_LOOPS) {
638
throw new Error("Too much loops for handshaking");
639
}
640
System.out.println("============================================");
641
System.out.println("Handshake loop " + loop + ": round 1");
642
System.out.println("==========================");
643
handshakeProcess(firstEngine, secondEngine, maxPacketSize,
644
enableReplicatedPacks);
645
if (endHandshakeLoop) {
646
break;
647
}
648
System.out.println("Handshake loop " + loop + ": round 2");
649
System.out.println("==========================");
650
handshakeProcess(secondEngine, firstEngine, maxPacketSize,
651
enableReplicatedPacks);
652
}
653
}
654
655
/**
656
* Routine to send application data from one SSLEngine to another.
657
*
658
* @param fromEngine - Sending engine.
659
* @param toEngine - Receiving engine.
660
* @return - Result of unwrap method of the receiving engine.
661
* @throws SSLException - thrown on engine errors.
662
*/
663
public static SSLEngineResult sendApplicationData(SSLEngine fromEngine,
664
SSLEngine toEngine)
665
throws SSLException {
666
String sender = null;
667
String reciever = null;
668
String excMsgSent = EXCHANGE_MSG_SENT;
669
if (fromEngine.getUseClientMode() && !toEngine.getUseClientMode()) {
670
sender = "Client";
671
reciever = "Server";
672
excMsgSent += " Client.";
673
} else if (toEngine.getUseClientMode() &&
674
!fromEngine.getUseClientMode()) {
675
sender = "Server";
676
reciever = "Client";
677
excMsgSent += " Server.";
678
} else {
679
throw new Error("Test issue: both engines are in the same mode");
680
}
681
System.out.println("=============================================");
682
System.out.println("Trying to send application data from " + sender
683
+ " to " + reciever);
684
ByteBuffer clientAppSent
685
= ByteBuffer.wrap(excMsgSent.getBytes());
686
net = doWrap(fromEngine, sender, 0, clientAppSent);
687
SSLEngineResult[] r = new SSLEngineResult[1];
688
ByteBuffer serverAppRecv = doUnWrap(toEngine, reciever, net, r);
689
byte[] serverAppRecvTrunc = Arrays.copyOf(serverAppRecv.array(),
690
serverAppRecv.limit());
691
String msgRecv = new String(serverAppRecvTrunc);
692
if (!msgRecv.equals(excMsgSent)) {
693
throw new AssertionError(sender + " to " + reciever
694
+ ": application data"
695
+ " has been altered while sending."
696
+ " Message sent: " + "\"" + excMsgSent + "\"."
697
+ " Message recieved: " + "\"" + msgRecv + "\".");
698
}
699
System.out.println("Successful sending application data from " + sender
700
+ " to " + reciever);
701
return r[0];
702
}
703
704
/**
705
* Close engines by sending "close outbound" message from one SSLEngine to
706
* another.
707
*
708
* @param fromEngine - Sending engine.
709
* @param toEngine - Receiving engine.
710
* @throws SSLException - thrown on engine errors.
711
*/
712
public static void closeEngines(SSLEngine fromEngine,
713
SSLEngine toEngine) throws SSLException {
714
String from = null;
715
String to = null;
716
ByteBuffer app;
717
if (fromEngine.getUseClientMode() && !toEngine.getUseClientMode()) {
718
from = "Client";
719
to = "Server";
720
} else if (toEngine.getUseClientMode() &&
721
!fromEngine.getUseClientMode()) {
722
from = "Server";
723
to = "Client";
724
} else {
725
throw new Error("Both engines are in the same mode");
726
}
727
System.out.println("=============================================");
728
System.out.println(
729
"Trying to close engines from " + from + " to " + to);
730
// Sending close outbound request to peer
731
fromEngine.closeOutbound();
732
app = ByteBuffer.allocate(
733
fromEngine.getSession().getApplicationBufferSize());
734
net = doWrap(fromEngine, from, 0, app, SSLEngineResult.Status.CLOSED);
735
doUnWrap(toEngine, to, net, SSLEngineResult.Status.CLOSED);
736
app = ByteBuffer.allocate(
737
fromEngine.getSession().getApplicationBufferSize());
738
net = doWrap(toEngine, to, 0, app, SSLEngineResult.Status.CLOSED);
739
doUnWrap(fromEngine, from, net, SSLEngineResult.Status.CLOSED);
740
if (!toEngine.isInboundDone()) {
741
throw new AssertionError(from + " sent close request to " + to
742
+ ", but " + to + "did not close inbound.");
743
}
744
// Executing close inbound
745
fromEngine.closeInbound();
746
app = ByteBuffer.allocate(
747
fromEngine.getSession().getApplicationBufferSize());
748
net = doWrap(fromEngine, from, 0, app, SSLEngineResult.Status.CLOSED);
749
doUnWrap(toEngine, to, net, SSLEngineResult.Status.CLOSED);
750
if (!toEngine.isOutboundDone()) {
751
throw new AssertionError(from + "sent close request to " + to
752
+ ", but " + to + "did not close outbound.");
753
}
754
System.out.println("Successful closing from " + from + " to " + to);
755
}
756
757
/**
758
* Runs the same test case for all given {@code ciphers}. Method counts all
759
* failures and throws {@code AssertionError} if one or more tests fail.
760
*
761
* @param ciphers - Ciphers that should be tested.
762
*/
763
public void runTests(Ciphers ciphers) {
764
int total = ciphers.ciphers.length;
765
int failed = testSomeCiphers(ciphers);
766
if (failed > 0) {
767
throw new AssertionError("" + failed + " of " + total
768
+ " tests failed!");
769
}
770
System.out.println("All tests passed!");
771
}
772
773
/**
774
* Runs test cases for ciphers defined by the test mode.
775
*/
776
public void runTests() {
777
switch (TEST_MODE) {
778
case "norm":
779
case "norm_sni":
780
switch (TESTED_SECURITY_PROTOCOL) {
781
case "TLSv1":
782
case "TLSv1.1":
783
runTests(Ciphers.SUPPORTED_NON_KRB_NON_SHA_CIPHERS);
784
break;
785
case "TLSv1.2":
786
runTests(Ciphers.SUPPORTED_NON_KRB_CIPHERS);
787
break;
788
case "TLSv1.3":
789
runTests(Ciphers.TLS13_CIPHERS);
790
break;
791
}
792
break;
793
case "krb":
794
runTests(Ciphers.SUPPORTED_KRB_CIPHERS);
795
break;
796
default:
797
throw new Error(
798
"Test error: unexpected test mode: " + TEST_MODE);
799
}
800
}
801
802
/**
803
* Returns maxPacketSize value used for MFLN extension testing
804
*
805
* @return - MLFN extension max packet size.
806
*/
807
public int getMaxPacketSize() {
808
return maxPacketSize;
809
}
810
811
/**
812
* Checks that status of result {@code r} is {@code wantedStatus}.
813
*
814
* @param r - Result.
815
* @param wantedStatus - Wanted status of the result.
816
* @throws AssertionError - if status or {@code r} is not
817
* {@code wantedStatus}.
818
*/
819
public static void checkResult(SSLEngineResult r,
820
SSLEngineResult.Status wantedStatus) {
821
SSLEngineResult.Status rs = r.getStatus();
822
if (!rs.equals(wantedStatus)) {
823
throw new AssertionError("Unexpected status " + rs.name()
824
+ ", should be " + wantedStatus.name());
825
}
826
}
827
828
/**
829
* Returns SSLContext with TESTED_SECURITY_PROTOCOL protocol and
830
* sets up keys.
831
*
832
* @return - SSLContext with a protocol specified by
833
* TESTED_SECURITY_PROTOCOL.
834
*/
835
public static SSLContext getContext() {
836
try {
837
java.security.Security.setProperty(
838
"jdk.tls.disabledAlgorithms", "");
839
java.security.Security.setProperty(
840
"jdk.certpath.disabledAlgorithms", "");
841
KeyStore ks = KeyStore.getInstance("JKS");
842
KeyStore ts = KeyStore.getInstance("JKS");
843
char[] passphrase = PASSWD.toCharArray();
844
try (FileInputStream keyFileStream =
845
new FileInputStream(KEY_FILE_NAME)) {
846
ks.load(keyFileStream, passphrase);
847
}
848
try (FileInputStream trustFileStream =
849
new FileInputStream(TRUST_FILE_NAME)) {
850
ts.load(trustFileStream, passphrase);
851
}
852
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
853
kmf.init(ks, passphrase);
854
TrustManagerFactory tmf =
855
TrustManagerFactory.getInstance("SunX509");
856
tmf.init(ts);
857
SSLContext sslCtx =
858
SSLContext.getInstance(TESTED_SECURITY_PROTOCOL);
859
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
860
return sslCtx;
861
} catch (KeyStoreException | IOException | NoSuchAlgorithmException |
862
CertificateException | UnrecoverableKeyException |
863
KeyManagementException ex) {
864
throw new Error("Unexpected exception", ex);
865
}
866
}
867
868
/**
869
* Sets up and starts kerberos KDC server.
870
*/
871
public static void setUpAndStartKDC() {
872
String servicePrincipal = "host/" + SERVER_NAME + "@" + KRB_REALM;
873
Map<String, String> principals = new HashMap<>();
874
principals.put(KRB_USER_PRINCIPAL, KRB_USER_PASSWORD);
875
principals.put(KRBTGT_PRINCIPAL, null);
876
principals.put(servicePrincipal, null);
877
System.setProperty("java.security.krb5.conf", KRB5_CONF_FILENAME);
878
startKDC(KRB_REALM, principals, KTAB_FILENAME);
879
System.setProperty("java.security.auth.login.config",
880
TEST_SRC + FS + JAAS_CONF_FILE);
881
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
882
}
883
884
/**
885
* Sets up and starts kerberos KDC server if
886
* SSLEngineTestCase.TEST_MODE is "krb".
887
*/
888
public static void setUpAndStartKDCIfNeeded() {
889
if (TEST_MODE.equals("krb")) {
890
setUpAndStartKDC();
891
}
892
}
893
894
/**
895
* Returns client ssl engine.
896
*
897
* @param context - SSLContext to get SSLEngine from.
898
* @param useSNI - flag used to enable or disable using SNI extension.
899
* Needed for Kerberos.
900
*/
901
public static SSLEngine getClientSSLEngine(
902
SSLContext context, boolean useSNI) {
903
904
SSLEngine clientEngine = context.createSSLEngine(HOST, 80);
905
clientEngine.setUseClientMode(true);
906
if (useSNI) {
907
SNIHostName serverName = new SNIHostName(SERVER_NAME);
908
List<SNIServerName> serverNames = new ArrayList<>();
909
serverNames.add(serverName);
910
SSLParameters params = clientEngine.getSSLParameters();
911
params.setServerNames(serverNames);
912
clientEngine.setSSLParameters(params);
913
}
914
return clientEngine;
915
}
916
917
/**
918
* Returns server ssl engine.
919
*
920
* @param context - SSLContext to get SSLEngine from.
921
* @param useSNI - flag used to enable or disable using SNI extension.
922
* Needed for Kerberos.
923
*/
924
public static SSLEngine getServerSSLEngine(
925
SSLContext context, boolean useSNI) {
926
927
SSLEngine serverEngine = context.createSSLEngine();
928
serverEngine.setUseClientMode(false);
929
if (useSNI) {
930
SNIMatcher matcher = SNIHostName.createSNIMatcher(SNI_PATTERN);
931
List<SNIMatcher> matchers = new ArrayList<>();
932
matchers.add(matcher);
933
SSLParameters params = serverEngine.getSSLParameters();
934
params.setSNIMatchers(matchers);
935
serverEngine.setSSLParameters(params);
936
}
937
return serverEngine;
938
}
939
940
/**
941
* Runs the test case for one cipher suite.
942
*
943
* @param cipher - Cipher suite name.
944
* @throws SSLException - If tests fails.
945
*/
946
abstract protected void testOneCipher(String cipher)
947
throws SSLException;
948
949
/**
950
* Iterates through an array of ciphers and runs the same test case for
951
* every entry.
952
*
953
* @param ciphers - Array of cipher names.
954
* @return - Number of tests failed.
955
*/
956
protected int testSomeCiphers(Ciphers ciphers) {
957
int failedNum = 0;
958
String description = ciphers.description;
959
System.out.println("===============================================");
960
System.out.println(description + " ciphers testing");
961
System.out.println("===========================================");
962
for (String cs : ciphers.ciphers) {
963
System.out.println("---------------------------------------");
964
System.out.println("Testing cipher suite " + cs);
965
System.out.println("---------------------------------------");
966
Throwable error = null;
967
968
// Reset global mutable static variables
969
net = null;
970
doUnwrapForNotHandshakingStatus = false;
971
endHandshakeLoop = false;
972
973
try {
974
testOneCipher(cs);
975
} catch (Throwable t) {
976
error = t;
977
}
978
switch (ciphers) {
979
case SUPPORTED_NON_KRB_CIPHERS:
980
case SUPPORTED_NON_KRB_NON_SHA_CIPHERS:
981
case SUPPORTED_KRB_CIPHERS:
982
case ENABLED_NON_KRB_NOT_ANON_CIPHERS:
983
case TLS13_CIPHERS:
984
if (error != null) {
985
System.out.println("Test Failed: " + cs);
986
System.err.println("Test Exception for " + cs);
987
error.printStackTrace();
988
failedNum++;
989
} else {
990
System.out.println("Test Passed: " + cs);
991
}
992
break;
993
case UNSUPPORTED_CIPHERS:
994
if (error == null) {
995
System.out.println("Test Failed: " + cs);
996
System.err.println("Test for " + cs +
997
" should have thrown " +
998
"IllegalArgumentException, but it has not!");
999
failedNum++;
1000
} else if (!(error instanceof IllegalArgumentException)) {
1001
System.out.println("Test Failed: " + cs);
1002
System.err.println("Test Exception for " + cs);
1003
error.printStackTrace();
1004
failedNum++;
1005
} else {
1006
System.out.println("Test Passed: " + cs);
1007
}
1008
break;
1009
default:
1010
throw new Error("Test issue: unexpected ciphers: "
1011
+ ciphers.name());
1012
}
1013
}
1014
1015
return failedNum;
1016
}
1017
1018
/**
1019
* Method used for the handshake routine.
1020
*
1021
* @param wrapingEngine - Engine that is expected to wrap data.
1022
* @param unwrapingEngine - Engine that is expected to unwrap data.
1023
* @param maxPacketSize - Maximum packet size for MFLN of zero
1024
* for no limit.
1025
* @param enableReplicatedPacks - Set {@code true} to enable replicated
1026
* packet sending.
1027
* @throws SSLException - thrown on engine errors.
1028
*/
1029
private static void handshakeProcess(SSLEngine wrapingEngine,
1030
SSLEngine unwrapingEngine,
1031
int maxPacketSize,
1032
boolean enableReplicatedPacks) throws SSLException {
1033
1034
HandshakeStatus wrapingHSStatus = wrapingEngine.getHandshakeStatus();
1035
HandshakeStatus unwrapingHSStatus =
1036
unwrapingEngine.getHandshakeStatus();
1037
SSLEngineResult r;
1038
String wrapper, unwrapper;
1039
if (wrapingEngine.getUseClientMode()
1040
&& !unwrapingEngine.getUseClientMode()) {
1041
wrapper = "Client";
1042
unwrapper = "Server";
1043
} else if (unwrapingEngine.getUseClientMode()
1044
&& !wrapingEngine.getUseClientMode()) {
1045
wrapper = "Server";
1046
unwrapper = "Client";
1047
} else {
1048
throw new Error("Both engines are in the same mode");
1049
}
1050
System.out.println(
1051
wrapper + " handshake (wrap) status " + wrapingHSStatus);
1052
System.out.println(
1053
unwrapper + " handshake (unwrap) status " + unwrapingHSStatus);
1054
1055
ByteBuffer netReplicatedClient = null;
1056
ByteBuffer netReplicatedServer = null;
1057
switch (wrapingHSStatus) {
1058
case NEED_WRAP:
1059
if (enableReplicatedPacks) {
1060
if (net != null) {
1061
net.flip();
1062
if (net.remaining() != 0) {
1063
if (wrapingEngine.getUseClientMode()) {
1064
netReplicatedServer = net;
1065
} else {
1066
netReplicatedClient = net;
1067
}
1068
}
1069
}
1070
}
1071
ByteBuffer app = ByteBuffer.allocate(
1072
wrapingEngine.getSession().getApplicationBufferSize());
1073
net = doWrap(wrapingEngine, wrapper, maxPacketSize, app);
1074
wrapingHSStatus = wrapingEngine.getHandshakeStatus();
1075
// No break, falling into unwrapping.
1076
case NOT_HANDSHAKING:
1077
switch (unwrapingHSStatus) {
1078
case NEED_TASK:
1079
runDelegatedTasks(unwrapingEngine);
1080
case NEED_UNWRAP:
1081
doUnWrap(unwrapingEngine, unwrapper, net);
1082
if (enableReplicatedPacks) {
1083
System.out.println(unwrapper +
1084
" unwrapping replicated packet...");
1085
if (unwrapingEngine.getHandshakeStatus()
1086
.equals(HandshakeStatus.NEED_TASK)) {
1087
runDelegatedTasks(unwrapingEngine);
1088
}
1089
ByteBuffer netReplicated;
1090
if (unwrapingEngine.getUseClientMode()) {
1091
netReplicated = netReplicatedClient;
1092
} else {
1093
netReplicated = netReplicatedServer;
1094
}
1095
if (netReplicated != null) {
1096
doUnWrap(unwrapingEngine,
1097
unwrapper, netReplicated);
1098
} else {
1099
net.flip();
1100
doUnWrap(unwrapingEngine, unwrapper, net);
1101
}
1102
}
1103
break;
1104
case NOT_HANDSHAKING:
1105
if (doUnwrapForNotHandshakingStatus) {
1106
System.out.println("Not handshake status unwrap");
1107
doUnWrap(unwrapingEngine, unwrapper, net);
1108
doUnwrapForNotHandshakingStatus = false;
1109
break;
1110
} else {
1111
if (wrapingHSStatus ==
1112
HandshakeStatus.NOT_HANDSHAKING) {
1113
System.out.println("Handshake is completed");
1114
endHandshakeLoop = true;
1115
}
1116
}
1117
break;
1118
case NEED_WRAP:
1119
SSLSession session = unwrapingEngine.getSession();
1120
int bufferSize = session.getApplicationBufferSize();
1121
ByteBuffer b = ByteBuffer.allocate(bufferSize);
1122
net = doWrap(unwrapingEngine,
1123
unwrapper, maxPacketSize, b);
1124
unwrapingHSStatus =
1125
unwrapingEngine.getHandshakeStatus();
1126
if ((wrapingHSStatus ==
1127
HandshakeStatus.NOT_HANDSHAKING) &&
1128
(unwrapingHSStatus ==
1129
HandshakeStatus.NOT_HANDSHAKING)) {
1130
1131
System.out.println("Handshake is completed");
1132
endHandshakeLoop = true;
1133
}
1134
1135
break;
1136
default:
1137
throw new Error(
1138
"Unexpected unwraping engine handshake status "
1139
+ unwrapingHSStatus.name());
1140
}
1141
break;
1142
case NEED_UNWRAP:
1143
break;
1144
case NEED_TASK:
1145
runDelegatedTasks(wrapingEngine);
1146
break;
1147
default:
1148
throw new Error("Unexpected wraping engine handshake status "
1149
+ wrapingHSStatus.name());
1150
}
1151
}
1152
1153
private static void runDelegatedTasks(SSLEngine engine) {
1154
Runnable runnable;
1155
System.out.println("Running delegated tasks...");
1156
while ((runnable = engine.getDelegatedTask()) != null) {
1157
runnable.run();
1158
}
1159
HandshakeStatus hs = engine.getHandshakeStatus();
1160
if (hs == HandshakeStatus.NEED_TASK) {
1161
throw new Error("Handshake shouldn't need additional tasks.");
1162
}
1163
}
1164
1165
/**
1166
* Start a KDC server:
1167
* - create a KDC instance
1168
* - create Kerberos principals
1169
* - save Kerberos configuration
1170
* - save keys to keytab file
1171
* - no pre-auth is required
1172
*/
1173
private static void startKDC(String realm, Map<String, String> principals,
1174
String ktab) {
1175
try {
1176
KDC kdc = KDC.create(realm, HOST, 0, true);
1177
kdc.setOption(KDC.Option.PREAUTH_REQUIRED, Boolean.FALSE);
1178
if (principals != null) {
1179
principals.entrySet().stream().forEach((entry) -> {
1180
String name = entry.getKey();
1181
String password = entry.getValue();
1182
if (password == null || password.isEmpty()) {
1183
System.out.println("KDC: add a principal '" + name
1184
+ "' with a random password");
1185
kdc.addPrincipalRandKey(name);
1186
} else {
1187
System.out.println("KDC: add a principal '" + name
1188
+ "' with '" + password + "' password");
1189
kdc.addPrincipal(name, password.toCharArray());
1190
}
1191
});
1192
}
1193
KDC.saveConfig(KRB5_CONF_FILENAME, kdc);
1194
if (ktab != null) {
1195
File ktabFile = new File(ktab);
1196
if (ktabFile.exists()) {
1197
System.out.println("KDC: append keys to an exising "
1198
+ "keytab file " + ktab);
1199
kdc.appendKtab(ktab);
1200
} else {
1201
System.out.println("KDC: create a new keytab file "
1202
+ ktab);
1203
kdc.writeKtab(ktab);
1204
}
1205
}
1206
System.out.println("KDC: started on " + HOST + ":" + kdc.getPort()
1207
+ " with '" + realm + "' realm");
1208
} catch (Exception e) {
1209
throw new RuntimeException("KDC: unexpected exception", e);
1210
}
1211
}
1212
}
1213
1214