Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/sun/security/ssl/SSLEngineImpl/RehandshakeFinished.java
41152 views
1
/*
2
* Copyright (c) 2004, 2013, 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
//
25
// SunJSSE does not support dynamic system properties, no way to re-use
26
// system properties in samevm/agentvm mode.
27
//
28
29
/*
30
* @test
31
* @bug 6207322
32
* @summary SSLEngine is returning a premature FINISHED message when doing
33
* an abbreviated handshake.
34
* @run main/othervm RehandshakeFinished
35
* @author Brad Wetmore
36
*/
37
38
/*
39
* This test may need some updating if the messages change order.
40
* Currently I'm expecting that there is a simple renegotiation, with
41
* each message being contained in a single SSL packet.
42
*
43
* ClientHello
44
* Server Hello
45
* CCS
46
* FINISHED
47
* CCS
48
* FINISHED
49
*/
50
51
/**
52
* A SSLEngine usage example which simplifies the presentation
53
* by removing the I/O and multi-threading concerns.
54
*
55
* The test creates two SSLEngines, simulating a client and server.
56
* The "transport" layer consists two byte buffers: think of them
57
* as directly connected pipes.
58
*
59
* Note, this is a *very* simple example: real code will be much more
60
* involved. For example, different threading and I/O models could be
61
* used, transport mechanisms could close unexpectedly, and so on.
62
*
63
* When this application runs, notice that several messages
64
* (wrap/unwrap) pass before any application data is consumed or
65
* produced. (For more information, please see the SSL/TLS
66
* specifications.) There may several steps for a successful handshake,
67
* so it's typical to see the following series of operations:
68
*
69
* client server message
70
* ====== ====== =======
71
* wrap() ... ClientHello
72
* ... unwrap() ClientHello
73
* ... wrap() ServerHello/Certificate
74
* unwrap() ... ServerHello/Certificate
75
* wrap() ... ClientKeyExchange
76
* wrap() ... ChangeCipherSpec
77
* wrap() ... Finished
78
* ... unwrap() ClientKeyExchange
79
* ... unwrap() ChangeCipherSpec
80
* ... unwrap() Finished
81
* ... wrap() ChangeCipherSpec
82
* ... wrap() Finished
83
* unwrap() ... ChangeCipherSpec
84
* unwrap() ... Finished
85
*/
86
87
import javax.net.ssl.*;
88
import javax.net.ssl.SSLEngineResult.*;
89
import java.io.*;
90
import java.security.*;
91
import java.nio.*;
92
93
public class RehandshakeFinished {
94
95
/*
96
* Enables logging of the SSLEngine operations.
97
*/
98
private static boolean logging = true;
99
100
/*
101
* Enables the JSSE system debugging system property:
102
*
103
* -Djavax.net.debug=all
104
*
105
* This gives a lot of low-level information about operations underway,
106
* including specific handshake messages, and might be best examined
107
* after gaining some familiarity with this application.
108
*/
109
private static boolean debug = false;
110
111
static private SSLContext sslc;
112
113
private SSLEngine clientEngine; // client Engine
114
private ByteBuffer clientOut; // write side of clientEngine
115
private ByteBuffer clientIn; // read side of clientEngine
116
117
private SSLEngine serverEngine; // server Engine
118
private ByteBuffer serverOut; // write side of serverEngine
119
private ByteBuffer serverIn; // read side of serverEngine
120
121
/*
122
* For data transport, this example uses local ByteBuffers. This
123
* isn't really useful, but the purpose of this example is to show
124
* SSLEngine concepts, not how to do network transport.
125
*/
126
private ByteBuffer cTOs; // "reliable" transport client->server
127
private ByteBuffer sTOc; // "reliable" transport server->client
128
129
/*
130
* The following is to set up the keystores.
131
*/
132
private static String pathToStores = "../../../../javax/net/ssl/etc";
133
private static String keyStoreFile = "keystore";
134
private static String trustStoreFile = "truststore";
135
private static String passwd = "passphrase";
136
137
private static String keyFilename =
138
System.getProperty("test.src", "./") + "/" + pathToStores +
139
"/" + keyStoreFile;
140
private static String trustFilename =
141
System.getProperty("test.src", "./") + "/" + pathToStores +
142
"/" + trustStoreFile;
143
144
private static Exception loadException = null;
145
146
static {
147
try {
148
KeyStore ks = KeyStore.getInstance("JKS");
149
KeyStore ts = KeyStore.getInstance("JKS");
150
151
char[] passphrase = "passphrase".toCharArray();
152
153
ks.load(new FileInputStream(keyFilename), passphrase);
154
ts.load(new FileInputStream(trustFilename), passphrase);
155
156
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
157
kmf.init(ks, passphrase);
158
159
TrustManagerFactory tmf =
160
TrustManagerFactory.getInstance("SunX509");
161
tmf.init(ts);
162
163
SSLContext sslCtx = SSLContext.getInstance("TLSv1.2");
164
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
165
sslc = sslCtx;
166
} catch (Exception e) {
167
loadException = e;
168
}
169
}
170
171
/*
172
* Main entry point for this test.
173
*/
174
public static void main(String args[]) throws Exception {
175
if (debug) {
176
System.setProperty("javax.net.debug", "all");
177
}
178
179
if (loadException != null) {
180
throw loadException;
181
}
182
183
// Prime the session cache with a good session
184
// Second connection should be a simple session resumption.
185
if ((new RehandshakeFinished().runTest()) !=
186
new RehandshakeFinished().runRehandshake()) {
187
throw new Exception("Sessions not equivalent");
188
}
189
190
System.out.println("Test Passed.");
191
}
192
193
private void checkResult(SSLEngine engine, SSLEngineResult result,
194
HandshakeStatus rqdHsStatus,
195
boolean consumed, boolean produced) throws Exception {
196
197
HandshakeStatus hsStatus = result.getHandshakeStatus();
198
199
if (hsStatus == HandshakeStatus.NEED_TASK) {
200
Runnable runnable;
201
while ((runnable = engine.getDelegatedTask()) != null) {
202
runnable.run();
203
}
204
hsStatus = engine.getHandshakeStatus();
205
}
206
207
if (hsStatus != rqdHsStatus) {
208
throw new Exception("Required " + rqdHsStatus +
209
", got " + hsStatus);
210
}
211
212
int bc = result.bytesConsumed();
213
int bp = result.bytesProduced();
214
215
if (consumed) {
216
if (bc <= 0) {
217
throw new Exception("Should have consumed bytes");
218
}
219
} else {
220
if (bc > 0) {
221
throw new Exception("Should not have consumed bytes");
222
}
223
}
224
225
if (produced) {
226
if (bp <= 0) {
227
throw new Exception("Should have produced bytes");
228
}
229
} else {
230
if (bp > 0) {
231
throw new Exception("Should not have produced bytes");
232
}
233
}
234
}
235
236
private SSLSession runRehandshake() throws Exception {
237
238
log("\n\n==============================================");
239
log("Staring actual test.");
240
241
createSSLEngines();
242
createBuffers();
243
SSLEngineResult result;
244
245
log("Client's ClientHello");
246
checkResult(clientEngine,
247
clientEngine.wrap(clientOut, cTOs), HandshakeStatus.NEED_UNWRAP,
248
false, true);
249
cTOs.flip();
250
checkResult(serverEngine,
251
serverEngine.unwrap(cTOs, serverIn), HandshakeStatus.NEED_WRAP,
252
true, false);
253
cTOs.compact();
254
255
log("Server's ServerHello/ServerHelloDone");
256
checkResult(serverEngine,
257
serverEngine.wrap(serverOut, sTOc), HandshakeStatus.NEED_WRAP,
258
false, true);
259
sTOc.flip();
260
checkResult(clientEngine,
261
clientEngine.unwrap(sTOc, clientIn), HandshakeStatus.NEED_UNWRAP,
262
true, false);
263
sTOc.compact();
264
265
log("Server's CCS");
266
checkResult(serverEngine,
267
serverEngine.wrap(serverOut, sTOc), HandshakeStatus.NEED_WRAP,
268
false, true);
269
sTOc.flip();
270
checkResult(clientEngine,
271
clientEngine.unwrap(sTOc, clientIn), HandshakeStatus.NEED_UNWRAP,
272
true, false);
273
sTOc.compact();
274
275
log("Server's FINISHED");
276
checkResult(serverEngine,
277
serverEngine.wrap(serverOut, sTOc), HandshakeStatus.NEED_UNWRAP,
278
false, true);
279
sTOc.flip();
280
checkResult(clientEngine,
281
clientEngine.unwrap(sTOc, clientIn), HandshakeStatus.NEED_WRAP,
282
true, false);
283
sTOc.compact();
284
285
log("Client's CCS");
286
checkResult(clientEngine,
287
clientEngine.wrap(clientOut, cTOs), HandshakeStatus.NEED_WRAP,
288
false, true);
289
cTOs.flip();
290
checkResult(serverEngine,
291
serverEngine.unwrap(cTOs, serverIn), HandshakeStatus.NEED_UNWRAP,
292
true, false);
293
cTOs.compact();
294
295
log("Client's FINISHED should trigger FINISHED messages all around.");
296
checkResult(clientEngine,
297
clientEngine.wrap(clientOut, cTOs), HandshakeStatus.FINISHED,
298
false, true);
299
cTOs.flip();
300
checkResult(serverEngine,
301
serverEngine.unwrap(cTOs, serverIn), HandshakeStatus.FINISHED,
302
true, false);
303
cTOs.compact();
304
305
return clientEngine.getSession();
306
}
307
308
/*
309
* Run the test.
310
*
311
* Sit in a tight loop, both engines calling wrap/unwrap regardless
312
* of whether data is available or not. We do this until both engines
313
* report back they are closed.
314
*
315
* The main loop handles all of the I/O phases of the SSLEngine's
316
* lifetime:
317
*
318
* initial handshaking
319
* application data transfer
320
* engine closing
321
*
322
* One could easily separate these phases into separate
323
* sections of code.
324
*/
325
private SSLSession runTest() throws Exception {
326
boolean dataDone = false;
327
328
createSSLEngines();
329
createBuffers();
330
331
SSLEngineResult clientResult; // results from client's last operation
332
SSLEngineResult serverResult; // results from server's last operation
333
334
/*
335
* Examining the SSLEngineResults could be much more involved,
336
* and may alter the overall flow of the application.
337
*
338
* For example, if we received a BUFFER_OVERFLOW when trying
339
* to write to the output pipe, we could reallocate a larger
340
* pipe, but instead we wait for the peer to drain it.
341
*/
342
while (!isEngineClosed(clientEngine) ||
343
!isEngineClosed(serverEngine)) {
344
345
log("================");
346
347
clientResult = clientEngine.wrap(clientOut, cTOs);
348
log("client wrap: ", clientResult);
349
runDelegatedTasks(clientResult, clientEngine);
350
351
serverResult = serverEngine.wrap(serverOut, sTOc);
352
log("server wrap: ", serverResult);
353
runDelegatedTasks(serverResult, serverEngine);
354
355
cTOs.flip();
356
sTOc.flip();
357
358
log("----");
359
360
clientResult = clientEngine.unwrap(sTOc, clientIn);
361
log("client unwrap: ", clientResult);
362
runDelegatedTasks(clientResult, clientEngine);
363
364
serverResult = serverEngine.unwrap(cTOs, serverIn);
365
log("server unwrap: ", serverResult);
366
runDelegatedTasks(serverResult, serverEngine);
367
368
cTOs.compact();
369
sTOc.compact();
370
371
/*
372
* After we've transfered all application data between the client
373
* and server, we close the clientEngine's outbound stream.
374
* This generates a close_notify handshake message, which the
375
* server engine receives and responds by closing itself.
376
*/
377
if (!dataDone && (clientOut.limit() == serverIn.position()) &&
378
(serverOut.limit() == clientIn.position())) {
379
380
/*
381
* A sanity check to ensure we got what was sent.
382
*/
383
checkTransfer(serverOut, clientIn);
384
checkTransfer(clientOut, serverIn);
385
386
log("\tClosing clientEngine's *OUTBOUND*...");
387
clientEngine.closeOutbound();
388
dataDone = true;
389
}
390
}
391
392
return clientEngine.getSession();
393
}
394
395
/*
396
* Using the SSLContext created during object creation,
397
* create/configure the SSLEngines we'll use for this test.
398
*/
399
private void createSSLEngines() throws Exception {
400
/*
401
* Configure the serverEngine to act as a server in the SSL/TLS
402
* handshake. Also, require SSL client authentication.
403
*/
404
serverEngine = sslc.createSSLEngine();
405
serverEngine.setUseClientMode(false);
406
serverEngine.setNeedClientAuth(true);
407
408
/*
409
* Similar to above, but using client mode instead.
410
*/
411
clientEngine = sslc.createSSLEngine("client", 80);
412
clientEngine.setUseClientMode(true);
413
}
414
415
/*
416
* Create and size the buffers appropriately.
417
*/
418
private void createBuffers() {
419
420
/*
421
* We'll assume the buffer sizes are the same
422
* between client and server.
423
*/
424
SSLSession session = clientEngine.getSession();
425
int appBufferMax = session.getApplicationBufferSize();
426
int netBufferMax = session.getPacketBufferSize();
427
428
/*
429
* We'll make the input buffers a bit bigger than the max needed
430
* size, so that unwrap()s following a successful data transfer
431
* won't generate BUFFER_OVERFLOWS.
432
*
433
* We'll use a mix of direct and indirect ByteBuffers for
434
* tutorial purposes only. In reality, only use direct
435
* ByteBuffers when they give a clear performance enhancement.
436
*/
437
clientIn = ByteBuffer.allocate(appBufferMax + 50);
438
serverIn = ByteBuffer.allocate(appBufferMax + 50);
439
440
cTOs = ByteBuffer.allocateDirect(netBufferMax);
441
sTOc = ByteBuffer.allocateDirect(netBufferMax);
442
443
clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
444
serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes());
445
}
446
447
/*
448
* If the result indicates that we have outstanding tasks to do,
449
* go ahead and run them in this thread.
450
*/
451
private static void runDelegatedTasks(SSLEngineResult result,
452
SSLEngine engine) throws Exception {
453
454
if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
455
Runnable runnable;
456
while ((runnable = engine.getDelegatedTask()) != null) {
457
log("\trunning delegated task...");
458
runnable.run();
459
}
460
HandshakeStatus hsStatus = engine.getHandshakeStatus();
461
if (hsStatus == HandshakeStatus.NEED_TASK) {
462
throw new Exception(
463
"handshake shouldn't need additional tasks");
464
}
465
log("\tnew HandshakeStatus: " + hsStatus);
466
}
467
}
468
469
private static boolean isEngineClosed(SSLEngine engine) {
470
return (engine.isOutboundDone() && engine.isInboundDone());
471
}
472
473
/*
474
* Simple check to make sure everything came across as expected.
475
*/
476
private static void checkTransfer(ByteBuffer a, ByteBuffer b)
477
throws Exception {
478
a.flip();
479
b.flip();
480
481
if (!a.equals(b)) {
482
throw new Exception("Data didn't transfer cleanly");
483
} else {
484
log("\tData transferred cleanly");
485
}
486
487
a.position(a.limit());
488
b.position(b.limit());
489
a.limit(a.capacity());
490
b.limit(b.capacity());
491
}
492
493
/*
494
* Logging code
495
*/
496
private static boolean resultOnce = true;
497
498
private static void log(String str, SSLEngineResult result) {
499
if (!logging) {
500
return;
501
}
502
if (resultOnce) {
503
resultOnce = false;
504
System.out.println("The format of the SSLEngineResult is: \n" +
505
"\t\"getStatus() / getHandshakeStatus()\" +\n" +
506
"\t\"bytesConsumed() / bytesProduced()\"\n");
507
}
508
HandshakeStatus hsStatus = result.getHandshakeStatus();
509
log(str +
510
result.getStatus() + "/" + hsStatus + ", " +
511
result.bytesConsumed() + "/" + result.bytesProduced() +
512
" bytes");
513
if (hsStatus == HandshakeStatus.FINISHED) {
514
log("\t...ready for application data");
515
}
516
}
517
518
private static void log(String str) {
519
if (logging) {
520
System.out.println(str);
521
}
522
}
523
}
524
525