1:
37:
38:
39: package ;
40:
41: import gnu.javax.net.ssl.provider.ClientHandshake.State.*;
42: import gnu.javax.net.ssl.provider.KeyExchangeAlgorithm.*;
43:
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54:
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73:
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83: import ;
84: import ;
85: import ;
86:
87:
90: public class ClientHandshake extends AbstractHandshake
91: {
92: static enum State
93: {
94: WRITE_CLIENT_HELLO (false, true),
95: READ_SERVER_HELLO (true, false),
96: READ_CERTIFICATE (true, false),
97: READ_SERVER_KEY_EXCHANGE (true, false),
98: READ_CERTIFICATE_REQUEST (true, false),
99: READ_SERVER_HELLO_DONE (true, false),
100: WRITE_CERTIFICATE (false, true),
101: WRITE_CLIENT_KEY_EXCHANGE (false, true),
102: WRITE_CERTIFICATE_VERIFY (false, true),
103: WRITE_FINISHED (false, true),
104: READ_FINISHED (true, false),
105: DONE (false, false);
106:
107: private final boolean isWriteState;
108: private final boolean isReadState;
109:
110: private State(boolean isReadState, boolean isWriteState)
111: {
112: this.isReadState = isReadState;
113: this.isWriteState = isWriteState;
114: }
115:
116: boolean isReadState()
117: {
118: return isReadState;
119: }
120:
121: boolean isWriteState()
122: {
123: return isWriteState;
124: }
125: }
126:
127: private State state;
128: private ByteBuffer outBuffer;
129: private boolean continuedSession;
130: private SessionImpl continued;
131: private KeyPair dhPair;
132: private String keyAlias;
133: private PrivateKey privateKey;
134: private MaxFragmentLength maxFragmentLengthSent;
135: private boolean truncatedHMacSent;
136: private ProtocolVersion sentVersion;
137:
138:
139: private CertVerifier certVerifier;
140: private ParamsVerifier paramsVerifier;
141: private DelegatedTask keyExchange;
142: private CertLoader certLoader;
143: private GenCertVerify genCertVerify;
144:
145: public ClientHandshake(SSLEngineImpl engine) throws NoSuchAlgorithmException
146: {
147: super(engine);
148: state = WRITE_CLIENT_HELLO;
149: continuedSession = false;
150: }
151:
152:
155: @Override protected HandshakeStatus implHandleInput() throws SSLException
156: {
157: if (state == DONE)
158: return HandshakeStatus.FINISHED;
159:
160: if (state.isWriteState()
161: || (outBuffer != null && outBuffer.hasRemaining()))
162: return HandshakeStatus.NEED_WRAP;
163:
164:
165: ByteBuffer buffer = handshakeBuffer.duplicate ();
166: buffer.flip();
167: buffer.position(handshakeOffset);
168:
169: Handshake handshake = new Handshake(buffer.slice(),
170: engine.session().suite,
171: engine.session().version);
172:
173: if (Debug.DEBUG)
174: logger.logv(Component.SSL_HANDSHAKE, "processing in state {0}:\n{1}",
175: state, handshake);
176:
177: switch (state)
178: {
179:
180: case READ_SERVER_HELLO:
181: {
182: if (handshake.type() != Handshake.Type.SERVER_HELLO)
183: throw new AlertException(new Alert(Alert.Level.FATAL,
184: Alert.Description.UNEXPECTED_MESSAGE));
185: ServerHello hello = (ServerHello) handshake.body();
186: serverRandom = hello.random().copy();
187: engine.session().suite = hello.cipherSuite();
188: engine.session().version = hello.version();
189: compression = hello.compressionMethod();
190: Session.ID serverId = new Session.ID(hello.sessionId());
191: if (continued != null
192: && continued.id().equals(serverId))
193: {
194: continuedSession = true;
195: engine.setSession(continued);
196: }
197: else if (engine.getEnableSessionCreation())
198: {
199: ((AbstractSessionContext) engine.contextImpl
200: .engineGetClientSessionContext()).put(engine.session());
201: }
202: ExtensionList extensions = hello.extensions();
203: if (extensions != null)
204: {
205: for (Extension extension : extensions)
206: {
207: Extension.Type type = extension.type();
208: if (type == null)
209: continue;
210: switch (type)
211: {
212: case MAX_FRAGMENT_LENGTH:
213: MaxFragmentLength mfl
214: = (MaxFragmentLength) extension.value();
215: if (maxFragmentLengthSent == mfl)
216: engine.session().setApplicationBufferSize(mfl.maxLength());
217: break;
218:
219: case TRUNCATED_HMAC:
220: if (truncatedHMacSent)
221: engine.session().setTruncatedMac(true);
222: break;
223: }
224: }
225: }
226:
227: KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm();
228: if (continuedSession)
229: {
230: byte[][] keys = generateKeys(clientRandom, serverRandom,
231: engine.session());
232: setupSecurityParameters(keys, true, engine, compression);
233: state = READ_FINISHED;
234: }
235: else if (kex == RSA || kex == DH_DSS || kex == DH_RSA
236: || kex == DHE_DSS || kex == DHE_RSA || kex == RSA_PSK)
237: state = READ_CERTIFICATE;
238: else if (kex == DH_anon || kex == PSK || kex == DHE_PSK)
239: state = READ_SERVER_KEY_EXCHANGE;
240: else
241: state = READ_CERTIFICATE_REQUEST;
242: }
243: break;
244:
245:
246: case READ_CERTIFICATE:
247: {
248: if (handshake.type() != Handshake.Type.CERTIFICATE)
249: {
250:
251: if (engine.session().suite.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS)
252: throw new AlertException(new Alert(Level.FATAL,
253: Description.UNEXPECTED_MESSAGE));
254: state = READ_SERVER_KEY_EXCHANGE;
255: }
256: Certificate cert = (Certificate) handshake.body();
257: X509Certificate[] chain = null;
258: try
259: {
260: chain = cert.certificates().toArray(new X509Certificate[0]);
261: }
262: catch (CertificateException ce)
263: {
264: throw new AlertException(new Alert(Level.FATAL,
265: Description.BAD_CERTIFICATE),
266: ce);
267: }
268: catch (NoSuchAlgorithmException nsae)
269: {
270: throw new AlertException(new Alert(Level.FATAL,
271: Description.UNSUPPORTED_CERTIFICATE),
272: nsae);
273: }
274: engine.session().setPeerCertificates(chain);
275: certVerifier = new CertVerifier(true, chain);
276: tasks.add(certVerifier);
277:
278:
279: KeyExchangeAlgorithm kea = engine.session().suite.keyExchangeAlgorithm();
280: if (kea == RSA || kea == RSA_PSK)
281: {
282: keyExchange = new RSAGen(kea == RSA);
283: tasks.add(keyExchange);
284: if (kea == RSA)
285: state = READ_CERTIFICATE_REQUEST;
286: else
287: state = READ_SERVER_KEY_EXCHANGE;
288: }
289: else
290: state = READ_SERVER_KEY_EXCHANGE;
291: }
292: break;
293:
294:
295: case READ_SERVER_KEY_EXCHANGE:
296: {
297: CipherSuite s = engine.session().suite;
298: KeyExchangeAlgorithm kexalg = s.keyExchangeAlgorithm();
299:
300: if (kexalg != DHE_DSS && kexalg != DHE_RSA && kexalg != DH_anon
301: && kexalg != DHE_PSK && kexalg != PSK && kexalg != RSA_PSK)
302: throw new AlertException(new Alert(Level.FATAL,
303: Description.UNEXPECTED_MESSAGE));
304:
305: if (handshake.type() != Handshake.Type.SERVER_KEY_EXCHANGE)
306: {
307: if (kexalg != RSA_PSK && kexalg != PSK)
308: throw new AlertException(new Alert(Level.FATAL,
309: Description.UNEXPECTED_MESSAGE));
310: state = READ_CERTIFICATE_REQUEST;
311: return HandshakeStatus.NEED_UNWRAP;
312: }
313:
314: ServerKeyExchange skex = (ServerKeyExchange) handshake.body();
315: ByteBuffer paramsBuffer = null;
316: if (kexalg == DHE_DSS || kexalg == DHE_RSA || kexalg == DH_anon)
317: {
318: ServerDHParams dhParams = (ServerDHParams) skex.params();
319: ByteBuffer b = dhParams.buffer();
320: paramsBuffer = ByteBuffer.allocate(b.remaining());
321: paramsBuffer.put(b);
322: }
323:
324: if (s.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS)
325: {
326: byte[] signature = skex.signature().signature();
327: paramsVerifier = new ParamsVerifier(paramsBuffer, signature);
328: tasks.add(paramsVerifier);
329: }
330:
331: if (kexalg == DHE_DSS || kexalg == DHE_RSA || kexalg == DH_anon)
332: {
333: ServerDHParams dhParams = (ServerDHParams) skex.params();
334: DHPublicKey serverKey = new GnuDHPublicKey(null,
335: dhParams.p(),
336: dhParams.g(),
337: dhParams.y());
338: DHParameterSpec params = new DHParameterSpec(dhParams.p(),
339: dhParams.g());
340: keyExchange = new ClientDHGen(serverKey, params, true);
341: tasks.add(keyExchange);
342: }
343: if (kexalg == DHE_PSK)
344: {
345: ServerDHE_PSKParameters pskParams = (ServerDHE_PSKParameters)
346: skex.params();
347: ServerDHParams dhParams = pskParams.params();
348: DHPublicKey serverKey = new GnuDHPublicKey(null,
349: dhParams.p(),
350: dhParams.g(),
351: dhParams.y());
352: DHParameterSpec params = new DHParameterSpec(dhParams.p(),
353: dhParams.g());
354: keyExchange = new ClientDHGen(serverKey, params, false);
355: tasks.add(keyExchange);
356: }
357: state = READ_CERTIFICATE_REQUEST;
358: }
359: break;
360:
361:
362: case READ_CERTIFICATE_REQUEST:
363: {
364: if (handshake.type() != Handshake.Type.CERTIFICATE_REQUEST)
365: {
366: state = READ_SERVER_HELLO_DONE;
367: return HandshakeStatus.NEED_UNWRAP;
368: }
369:
370: CertificateRequest req = (CertificateRequest) handshake.body();
371: ClientCertificateTypeList types = req.types();
372: LinkedList<String> typeList = new LinkedList<String>();
373: for (ClientCertificateType t : types)
374: typeList.add(t.name());
375:
376: X500PrincipalList issuers = req.authorities();
377: LinkedList<X500Principal> issuerList = new LinkedList<X500Principal>();
378: for (X500Principal p : issuers)
379: issuerList.add(p);
380:
381: certLoader = new CertLoader(typeList, issuerList);
382: tasks.add(certLoader);
383: }
384: break;
385:
386:
387: case READ_SERVER_HELLO_DONE:
388: {
389: if (handshake.type() != Handshake.Type.SERVER_HELLO_DONE)
390: throw new AlertException(new Alert(Level.FATAL,
391: Description.UNEXPECTED_MESSAGE));
392: state = WRITE_CERTIFICATE;
393: }
394: break;
395:
396:
397: case READ_FINISHED:
398: {
399: if (handshake.type() != Handshake.Type.FINISHED)
400: throw new AlertException(new Alert(Level.FATAL,
401: Description.UNEXPECTED_MESSAGE));
402:
403: Finished serverFinished = (Finished) handshake.body();
404: MessageDigest md5copy = null;
405: MessageDigest shacopy = null;
406: try
407: {
408: md5copy = (MessageDigest) md5.clone();
409: shacopy = (MessageDigest) sha.clone();
410: }
411: catch (CloneNotSupportedException cnse)
412: {
413:
414:
415: throw new SSLException(cnse);
416: }
417: Finished clientFinished =
418: new Finished(generateFinished(md5copy, shacopy,
419: false, engine.session()),
420: engine.session().version);
421:
422: if (Debug.DEBUG)
423: logger.logv(Component.SSL_HANDSHAKE, "clientFinished: {0}",
424: clientFinished);
425:
426: if (engine.session().version == ProtocolVersion.SSL_3)
427: {
428: if (!Arrays.equals(clientFinished.md5Hash(),
429: serverFinished.md5Hash())
430: || !Arrays.equals(clientFinished.shaHash(),
431: serverFinished.shaHash()))
432: {
433: engine.session().invalidate();
434: throw new SSLException("session verify failed");
435: }
436: }
437: else
438: {
439: if (!Arrays.equals(clientFinished.verifyData(),
440: serverFinished.verifyData()))
441: {
442: engine.session().invalidate();
443: throw new SSLException("session verify failed");
444: }
445: }
446:
447: if (continuedSession)
448: {
449: engine.changeCipherSpec();
450: state = WRITE_FINISHED;
451: }
452: else
453: state = DONE;
454: }
455: break;
456:
457: default:
458: throw new IllegalStateException("invalid state: " + state);
459: }
460:
461: handshakeOffset += handshake.length() + 4;
462:
463: if (!tasks.isEmpty())
464: return HandshakeStatus.NEED_TASK;
465: if (state.isWriteState()
466: || (outBuffer != null && outBuffer.hasRemaining()))
467: return HandshakeStatus.NEED_WRAP;
468: if (state.isReadState())
469: return HandshakeStatus.NEED_UNWRAP;
470:
471: return HandshakeStatus.FINISHED;
472: }
473:
474:
477: @Override protected HandshakeStatus implHandleOutput(ByteBuffer fragment)
478: throws SSLException
479: {
480: if (Debug.DEBUG)
481: logger.logv(Component.SSL_HANDSHAKE, "output to {0}; state:{1}; outBuffer:{2}",
482: fragment, state, outBuffer);
483:
484:
485: if (outBuffer != null && outBuffer.hasRemaining())
486: {
487: int l = Math.min(fragment.remaining(), outBuffer.remaining());
488: fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
489: outBuffer.position(outBuffer.position() + l);
490: }
491:
492: if (!fragment.hasRemaining())
493: {
494: if (state.isWriteState() || outBuffer.hasRemaining())
495: return HandshakeStatus.NEED_WRAP;
496: else
497: return HandshakeStatus.NEED_UNWRAP;
498: }
499:
500: outer_loop:
501: while (fragment.remaining() >= 4 && state.isWriteState())
502: {
503: if (Debug.DEBUG)
504: logger.logv(Component.SSL_HANDSHAKE, "loop state={0}", state);
505:
506: switch (state)
507: {
508: case WRITE_CLIENT_HELLO:
509: {
510: ClientHelloBuilder hello = new ClientHelloBuilder();
511: AbstractSessionContext ctx = (AbstractSessionContext)
512: engine.contextImpl.engineGetClientSessionContext();
513: continued = (SessionImpl) ctx.getSession(engine.getPeerHost(),
514: engine.getPeerPort());
515: engine.session().setId(new Session.ID(new byte[0]));
516: Session.ID sid = engine.session().id();
517:
518:
519: if (continued != null)
520: sid = continued.id();
521:
522: hello.setSessionId(sid.id());
523: sentVersion = chooseVersion();
524: hello.setVersion(sentVersion);
525: hello.setCipherSuites(getSuites());
526: hello.setCompressionMethods(getCompressionMethods());
527: Random r = hello.random();
528: r.setGmtUnixTime(Util.unixTime());
529: byte[] nonce = new byte[28];
530: engine.session().random().nextBytes(nonce);
531: r.setRandomBytes(nonce);
532: clientRandom = r.copy();
533: if (enableExtensions())
534: {
535: List<Extension> extensions = new LinkedList<Extension>();
536: MaxFragmentLength fraglen = maxFragmentLength();
537: if (fraglen != null)
538: {
539: extensions.add(new Extension(Extension.Type.MAX_FRAGMENT_LENGTH,
540: fraglen));
541: maxFragmentLengthSent = fraglen;
542: }
543:
544: String host = engine.getPeerHost();
545: if (host != null)
546: {
547: ServerName name
548: = new ServerName(NameType.HOST_NAME, host);
549: ServerNameList names
550: = new ServerNameList(Collections.singletonList(name));
551: extensions.add(new Extension(Extension.Type.SERVER_NAME,
552: names));
553: }
554:
555: if (truncatedHMac())
556: {
557: extensions.add(new Extension(Extension.Type.TRUNCATED_HMAC,
558: new TruncatedHMAC()));
559: truncatedHMacSent = true;
560: }
561:
562: ExtensionList elist = new ExtensionList(extensions);
563: hello.setExtensions(elist.buffer());
564: }
565: else
566: hello.setDisableExtensions(true);
567:
568: if (Debug.DEBUG)
569: logger.logv(Component.SSL_HANDSHAKE, "{0}", hello);
570:
571: fragment.putInt((Handshake.Type.CLIENT_HELLO.getValue() << 24)
572: | (hello.length() & 0xFFFFFF));
573: outBuffer = hello.buffer();
574: int l = Math.min(fragment.remaining(), outBuffer.remaining());
575: fragment.put((ByteBuffer) outBuffer.duplicate()
576: .limit(outBuffer.position() + l));
577: outBuffer.position(outBuffer.position() + l);
578:
579: state = READ_SERVER_HELLO;
580: }
581: break;
582:
583: case WRITE_CERTIFICATE:
584: {
585: java.security.cert.Certificate[] chain
586: = engine.session().getLocalCertificates();
587: if (chain != null)
588: {
589: CertificateBuilder cert
590: = new CertificateBuilder(CertificateType.X509);
591: try
592: {
593: cert.setCertificates(Arrays.asList(chain));
594: }
595: catch (CertificateException ce)
596: {
597: throw new AlertException(new Alert(Level.FATAL,
598: Description.INTERNAL_ERROR),
599: ce);
600: }
601:
602: outBuffer = cert.buffer();
603:
604: fragment.putInt((Handshake.Type.CERTIFICATE.getValue() << 24)
605: | (cert.length() & 0xFFFFFF));
606:
607: int l = Math.min(fragment.remaining(), outBuffer.remaining());
608: fragment.put((ByteBuffer) outBuffer.duplicate()
609: .limit(outBuffer.position() + l));
610: outBuffer.position(outBuffer.position() + l);
611: }
612: state = WRITE_CLIENT_KEY_EXCHANGE;
613: }
614: break;
615:
616: case WRITE_CLIENT_KEY_EXCHANGE:
617: {
618: KeyExchangeAlgorithm kea = engine.session().suite.keyExchangeAlgorithm();
619: ClientKeyExchangeBuilder ckex
620: = new ClientKeyExchangeBuilder(engine.session().suite,
621: engine.session().version);
622: if (kea == DHE_DSS || kea == DHE_RSA || kea == DH_anon
623: || kea == DH_DSS || kea == DH_RSA)
624: {
625: assert(dhPair != null);
626: DHPublicKey pubkey = (DHPublicKey) dhPair.getPublic();
627: ClientDiffieHellmanPublic pub
628: = new ClientDiffieHellmanPublic(pubkey.getY());
629: ckex.setExchangeKeys(pub.buffer());
630: }
631: if (kea == RSA || kea == RSA_PSK)
632: {
633: assert(keyExchange instanceof RSAGen);
634: assert(keyExchange.hasRun());
635: if (keyExchange.thrown() != null)
636: throw new AlertException(new Alert(Level.FATAL,
637: Description.HANDSHAKE_FAILURE),
638: keyExchange.thrown());
639: EncryptedPreMasterSecret epms
640: = new EncryptedPreMasterSecret(((RSAGen) keyExchange).encryptedSecret(),
641: engine.session().version);
642: if (kea == RSA)
643: ckex.setExchangeKeys(epms.buffer());
644: else
645: {
646: String identity = getPSKIdentity();
647: if (identity == null)
648: throw new SSLException("no pre-shared-key identity;"
649: + " set the security property"
650: + " \"jessie.client.psk.identity\"");
651: ClientRSA_PSKParameters params =
652: new ClientRSA_PSKParameters(identity, epms.buffer());
653: ckex.setExchangeKeys(params.buffer());
654: generatePSKSecret(identity, preMasterSecret, true);
655: }
656: }
657: if (kea == DHE_PSK)
658: {
659: assert(keyExchange instanceof ClientDHGen);
660: assert(dhPair != null);
661: String identity = getPSKIdentity();
662: if (identity == null)
663: throw new SSLException("no pre-shared key identity; set"
664: + " the security property"
665: + " \"jessie.client.psk.identity\"");
666: DHPublicKey pubkey = (DHPublicKey) dhPair.getPublic();
667: ClientDHE_PSKParameters params =
668: new ClientDHE_PSKParameters(identity,
669: new ClientDiffieHellmanPublic(pubkey.getY()));
670: ckex.setExchangeKeys(params.buffer());
671: generatePSKSecret(identity, preMasterSecret, true);
672: }
673: if (kea == PSK)
674: {
675: String identity = getPSKIdentity();
676: if (identity == null)
677: throw new SSLException("no pre-shared key identity; set"
678: + " the security property"
679: + " \"jessie.client.psk.identity\"");
680: generatePSKSecret(identity, null, true);
681: ClientPSKParameters params = new ClientPSKParameters(identity);
682: ckex.setExchangeKeys(params.buffer());
683: }
684: if (kea == NONE)
685: {
686: Inflater inflater = null;
687: Deflater deflater = null;
688: if (compression == CompressionMethod.ZLIB)
689: {
690: inflater = new Inflater();
691: deflater = new Deflater();
692: }
693: inParams = new InputSecurityParameters(null, null, inflater,
694: engine.session(),
695: engine.session().suite);
696: outParams = new OutputSecurityParameters(null, null, deflater,
697: engine.session(),
698: engine.session().suite);
699: engine.session().privateData.masterSecret = new byte[0];
700: }
701:
702: if (Debug.DEBUG)
703: logger.logv(Component.SSL_HANDSHAKE, "{0}", ckex);
704:
705: outBuffer = ckex.buffer();
706: if (Debug.DEBUG)
707: logger.logv(Component.SSL_HANDSHAKE, "client kex buffer {0}", outBuffer);
708: fragment.putInt((Handshake.Type.CLIENT_KEY_EXCHANGE.getValue() << 24)
709: | (ckex.length() & 0xFFFFFF));
710: int l = Math.min(fragment.remaining(), outBuffer.remaining());
711: fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
712: outBuffer.position(outBuffer.position() + l);
713:
714: if (privateKey != null)
715: {
716: genCertVerify = new GenCertVerify(md5, sha);
717: tasks.add(genCertVerify);
718: state = WRITE_CERTIFICATE_VERIFY;
719: }
720: else
721: {
722: engine.changeCipherSpec();
723: state = WRITE_FINISHED;
724: }
725: }
726:
727:
728: break outer_loop;
729:
730: case WRITE_CERTIFICATE_VERIFY:
731: {
732: assert(genCertVerify != null);
733: assert(genCertVerify.hasRun());
734: CertificateVerify verify = new CertificateVerify(genCertVerify.signed(),
735: engine.session().suite.signatureAlgorithm());
736:
737: outBuffer = verify.buffer();
738: fragment.putInt((Handshake.Type.CERTIFICATE_VERIFY.getValue() << 24)
739: | (verify.length() & 0xFFFFFF));
740: int l = Math.min(fragment.remaining(), outBuffer.remaining());
741: fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
742: outBuffer.position(outBuffer.position() + l);
743:
744:
745:
746: engine.changeCipherSpec();
747: state = WRITE_FINISHED;
748: }
749: break outer_loop;
750:
751: case WRITE_FINISHED:
752: {
753: MessageDigest md5copy = null;
754: MessageDigest shacopy = null;
755: try
756: {
757: md5copy = (MessageDigest) md5.clone();
758: shacopy = (MessageDigest) sha.clone();
759: }
760: catch (CloneNotSupportedException cnse)
761: {
762:
763:
764: throw new SSLException(cnse);
765: }
766: outBuffer
767: = generateFinished(md5copy, shacopy, true,
768: engine.session());
769:
770: fragment.putInt((Handshake.Type.FINISHED.getValue() << 24)
771: | outBuffer.remaining() & 0xFFFFFF);
772:
773: int l = Math.min(outBuffer.remaining(), fragment.remaining());
774: fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
775: outBuffer.position(outBuffer.position() + l);
776:
777: if (continuedSession)
778: state = DONE;
779: else
780: state = READ_FINISHED;
781: }
782: break;
783:
784: default:
785: throw new IllegalStateException("invalid state: " + state);
786: }
787: }
788:
789: if (!tasks.isEmpty())
790: return HandshakeStatus.NEED_TASK;
791: if (state.isWriteState() ||
792: (outBuffer != null && outBuffer.hasRemaining()))
793: return HandshakeStatus.NEED_WRAP;
794: if (state.isReadState())
795: return HandshakeStatus.NEED_UNWRAP;
796:
797: return HandshakeStatus.FINISHED;
798: }
799:
800:
803: @Override HandshakeStatus status()
804: {
805: if (state.isReadState())
806: return HandshakeStatus.NEED_UNWRAP;
807: if (state.isWriteState())
808: return HandshakeStatus.NEED_WRAP;
809: return HandshakeStatus.FINISHED;
810: }
811:
812: @Override void checkKeyExchange() throws SSLException
813: {
814:
815: }
816:
817:
820: @Override void handleV2Hello(ByteBuffer hello) throws SSLException
821: {
822: throw new SSLException("this should be impossible");
823: }
824:
825: private ProtocolVersion chooseVersion() throws SSLException
826: {
827:
828: ProtocolVersion version = null;
829: for (String ver : engine.getEnabledProtocols())
830: {
831: try
832: {
833: ProtocolVersion v = ProtocolVersion.forName(ver);
834: if (version == null || version.compareTo(v) < 0)
835: version = v;
836: }
837: catch (Exception x)
838: {
839: continue;
840: }
841: }
842:
843: if (version == null)
844: throw new SSLException("no suitable enabled versions");
845:
846: return version;
847: }
848:
849: private List<CipherSuite> getSuites() throws SSLException
850: {
851: List<CipherSuite> suites = new LinkedList<CipherSuite>();
852: for (String s : engine.getEnabledCipherSuites())
853: {
854: CipherSuite suite = CipherSuite.forName(s);
855: if (suite != null)
856: suites.add(suite);
857: }
858: if (suites.isEmpty())
859: throw new SSLException("no cipher suites enabled");
860: return suites;
861: }
862:
863: private List<CompressionMethod> getCompressionMethods()
864: {
865: List<CompressionMethod> methods = new LinkedList<CompressionMethod>();
866: GetSecurityPropertyAction gspa = new GetSecurityPropertyAction("jessie.enable.compression");
867: if (Boolean.valueOf(AccessController.doPrivileged(gspa)))
868: methods.add(CompressionMethod.ZLIB);
869: methods.add(CompressionMethod.NULL);
870: return methods;
871: }
872:
873: private boolean enableExtensions()
874: {
875: GetSecurityPropertyAction action
876: = new GetSecurityPropertyAction("jessie.client.enable.extensions");
877: return Boolean.valueOf(AccessController.doPrivileged(action));
878: }
879:
880: private MaxFragmentLength maxFragmentLength()
881: {
882: GetSecurityPropertyAction action
883: = new GetSecurityPropertyAction("jessie.client.maxFragmentLength");
884: String s = AccessController.doPrivileged(action);
885: if (s != null)
886: {
887: try
888: {
889: int len = Integer.parseInt(s);
890: switch (len)
891: {
892: case 9:
893: case (1 << 9): return MaxFragmentLength.LEN_2_9;
894: case 10:
895: case (1 << 10): return MaxFragmentLength.LEN_2_10;
896: case 11:
897: case (1 << 11): return MaxFragmentLength.LEN_2_11;
898: case 12:
899: case (1 << 12): return MaxFragmentLength.LEN_2_12;
900: }
901: }
902: catch (NumberFormatException nfe)
903: {
904: }
905: }
906: return null;
907: }
908:
909: private boolean truncatedHMac()
910: {
911: GetSecurityPropertyAction action
912: = new GetSecurityPropertyAction("jessie.client.truncatedHMac");
913: return Boolean.valueOf(AccessController.doPrivileged(action));
914: }
915:
916: private String getPSKIdentity()
917: {
918: GetSecurityPropertyAction action
919: = new GetSecurityPropertyAction("jessie.client.psk.identity");
920: return AccessController.doPrivileged(action);
921: }
922:
923:
924:
925: class ParamsVerifier extends DelegatedTask
926: {
927: private final ByteBuffer paramsBuffer;
928: private final byte[] signature;
929: private boolean verified;
930:
931: ParamsVerifier(ByteBuffer paramsBuffer, byte[] signature)
932: {
933: this.paramsBuffer = paramsBuffer;
934: this.signature = signature;
935: }
936:
937: public void implRun()
938: throws InvalidKeyException, NoSuchAlgorithmException,
939: SSLPeerUnverifiedException, SignatureException
940: {
941: java.security.Signature s
942: = java.security.Signature.getInstance(engine.session().suite
943: .signatureAlgorithm().algorithm());
944: s.initVerify(engine.session().getPeerCertificates()[0]);
945: s.update(paramsBuffer);
946: verified = s.verify(signature);
947: synchronized (this)
948: {
949: notifyAll();
950: }
951: }
952:
953: boolean verified()
954: {
955: return verified;
956: }
957: }
958:
959: class ClientDHGen extends DelegatedTask
960: {
961: private final DHPublicKey serverKey;
962: private final DHParameterSpec params;
963: private final boolean full;
964:
965: ClientDHGen(DHPublicKey serverKey, DHParameterSpec params, boolean full)
966: {
967: this.serverKey = serverKey;
968: this.params = params;
969: this.full = full;
970: }
971:
972: public void implRun()
973: throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
974: SSLException
975: {
976: if (Debug.DEBUG)
977: logger.log(Component.SSL_DELEGATED_TASK, "running client DH phase");
978: if (paramsVerifier != null)
979: {
980: synchronized (paramsVerifier)
981: {
982: try
983: {
984: while (!paramsVerifier.hasRun())
985: paramsVerifier.wait(500);
986: }
987: catch (InterruptedException ie)
988: {
989:
990: }
991: }
992: }
993: KeyPairGenerator gen = KeyPairGenerator.getInstance("DH");
994: gen.initialize(params, engine.session().random());
995: dhPair = gen.generateKeyPair();
996: if (Debug.DEBUG_KEY_EXCHANGE)
997: logger.logv(Component.SSL_KEY_EXCHANGE,
998: "client keys public:{0} private:{1}", dhPair.getPublic(),
999: dhPair.getPrivate());
1000:
1001: initDiffieHellman((DHPrivateKey) dhPair.getPrivate(), engine.session().random());
1002:
1003:
1004: DHPhase phase = new DHPhase(serverKey, full);
1005: phase.run();
1006: if (phase.thrown() != null)
1007: throw new SSLException(phase.thrown());
1008: }
1009:
1010: DHPublicKey serverKey()
1011: {
1012: return serverKey;
1013: }
1014: }
1015:
1016: class CertLoader extends DelegatedTask
1017: {
1018: private final List<String> keyTypes;
1019: private final List<X500Principal> issuers;
1020:
1021: CertLoader(List<String> keyTypes, List<X500Principal> issuers)
1022: {
1023: this.keyTypes = keyTypes;
1024: this.issuers = issuers;
1025: }
1026:
1027: public void implRun()
1028: {
1029: X509ExtendedKeyManager km = engine.contextImpl.keyManager;
1030: if (km == null)
1031: return;
1032: keyAlias = km.chooseEngineClientAlias(keyTypes.toArray(new String[keyTypes.size()]),
1033: issuers.toArray(new X500Principal[issuers.size()]),
1034: engine);
1035: engine.session().setLocalCertificates(km.getCertificateChain(keyAlias));
1036: privateKey = km.getPrivateKey(keyAlias);
1037: }
1038: }
1039:
1040: class RSAGen extends DelegatedTask
1041: {
1042: private byte[] encryptedPreMasterSecret;
1043: private final boolean full;
1044:
1045: RSAGen()
1046: {
1047: this(true);
1048: }
1049:
1050: RSAGen(boolean full)
1051: {
1052: this.full = full;
1053: }
1054:
1055: public void implRun()
1056: throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException,
1057: NoSuchAlgorithmException, NoSuchPaddingException,
1058: SSLException
1059: {
1060: if (certVerifier != null)
1061: {
1062: synchronized (certVerifier)
1063: {
1064: try
1065: {
1066: while (!certVerifier.hasRun())
1067: certVerifier.wait(500);
1068: }
1069: catch (InterruptedException ie)
1070: {
1071:
1072: }
1073: }
1074: }
1075: preMasterSecret = new byte[48];
1076: engine.session().random().nextBytes(preMasterSecret);
1077: preMasterSecret[0] = (byte) sentVersion.major();
1078: preMasterSecret[1] = (byte) sentVersion.minor();
1079: Cipher rsa = Cipher.getInstance("RSA");
1080: java.security.cert.Certificate cert
1081: = engine.session().getPeerCertificates()[0];
1082: if (cert instanceof X509Certificate)
1083: {
1084: boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage();
1085: if (keyUsage != null && !keyUsage[2])
1086: throw new InvalidKeyException("certificate's keyUsage does not permit keyEncipherment");
1087: }
1088: rsa.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
1089: encryptedPreMasterSecret = rsa.doFinal(preMasterSecret);
1090:
1091:
1092: if (full)
1093: {
1094: generateMasterSecret(clientRandom, serverRandom, engine.session());
1095: byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
1096: setupSecurityParameters(keys, true, engine, compression);
1097: }
1098: }
1099:
1100: byte[] encryptedSecret()
1101: {
1102: return encryptedPreMasterSecret;
1103: }
1104: }
1105:
1106: class GenCertVerify extends DelegatedTask
1107: {
1108: private final MessageDigest md5, sha;
1109: private byte[] signed;
1110:
1111: GenCertVerify(MessageDigest md5, MessageDigest sha)
1112: {
1113: try
1114: {
1115: this.md5 = (MessageDigest) md5.clone();
1116: this.sha = (MessageDigest) sha.clone();
1117: }
1118: catch (CloneNotSupportedException cnse)
1119: {
1120:
1121: throw new Error(cnse);
1122: }
1123: }
1124:
1125: public void implRun()
1126: throws InvalidKeyException, NoSuchAlgorithmException, SignatureException
1127: {
1128: byte[] toSign;
1129: if (engine.session().version == ProtocolVersion.SSL_3)
1130: {
1131: toSign = genV3CertificateVerify(md5, sha, engine.session());
1132: }
1133: else
1134: {
1135: if (engine.session().suite.signatureAlgorithm() == SignatureAlgorithm.RSA)
1136: toSign = Util.concat(md5.digest(), sha.digest());
1137: else
1138: toSign = sha.digest();
1139: }
1140:
1141: java.security.Signature sig =
1142: java.security.Signature.getInstance(engine.session().suite.signatureAlgorithm().name());
1143: sig.initSign(privateKey);
1144: sig.update(toSign);
1145: signed = sig.sign();
1146: }
1147:
1148: byte[] signed()
1149: {
1150: return signed;
1151: }
1152: }
1153: }