1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49:
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
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:
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83: import ;
84:
85:
90: public abstract class AbstractHandshake
91: {
92: protected static final SystemLogger logger = SystemLogger.SYSTEM;
93:
94:
97: protected static final byte[] SERVER_FINISHED
98: = new byte[] {
99: 115, 101, 114, 118, 101, 114, 32, 102, 105, 110, 105, 115,
100: 104, 101, 100
101: };
102:
103:
106: protected static final byte[] CLIENT_FINISHED
107: = new byte[] {
108: 99, 108, 105, 101, 110, 116, 32, 102, 105, 110, 105, 115,
109: 104, 101, 100
110: };
111:
112:
115: private static final byte[] KEY_EXPANSION =
116: new byte[] { 107, 101, 121, 32, 101, 120, 112,
117: 97, 110, 115, 105, 111, 110 };
118:
119:
122: private static final byte[] MASTER_SECRET
123: = new byte[] {
124: 109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116
125: };
126:
127:
130: private static final byte[] CLIENT_WRITE_KEY
131: = new byte[] {
132: 99, 108, 105, 101, 110, 116, 32, 119, 114, 105, 116, 101, 32, 107,
133: 101, 121
134: };
135:
136:
139: private static final byte[] SERVER_WRITE_KEY
140: = new byte[] {
141: 115, 101, 114, 118, 101, 114, 32, 119, 114, 105, 116, 101, 32, 107,
142: 101, 121
143: };
144:
145: private static final byte[] IV_BLOCK
146: = new byte[] {
147: 73, 86, 32, 98, 108, 111, 99, 107
148: };
149:
150:
153: private static final byte[] SENDER_CLIENT
154: = new byte[] { 0x43, 0x4C, 0x4E, 0x54 };
155:
156:
159: private static final byte[] SENDER_SERVER
160: = new byte[] { 0x53, 0x52, 0x56, 0x52 };
161:
162:
166: protected static final byte[] PAD1 = new byte[48];
167:
168:
172: protected static final byte[] PAD2 = new byte[48];
173:
174: static
175: {
176: Arrays.fill(PAD1, SSLHMac.PAD1);
177: Arrays.fill(PAD2, SSLHMac.PAD2);
178: }
179:
180:
184: protected ByteBuffer handshakeBuffer;
185:
186:
190: protected int handshakeOffset;
191:
192: protected MessageDigest sha;
193: protected MessageDigest md5;
194:
195: protected final SSLEngineImpl engine;
196: protected KeyAgreement keyAgreement;
197: protected byte[] preMasterSecret;
198: protected InputSecurityParameters inParams;
199: protected OutputSecurityParameters outParams;
200: protected LinkedList<DelegatedTask> tasks;
201: protected Random serverRandom;
202: protected Random clientRandom;
203: protected CompressionMethod compression;
204:
205: protected AbstractHandshake(SSLEngineImpl engine)
206: throws NoSuchAlgorithmException
207: {
208: this.engine = engine;
209: sha = MessageDigest.getInstance("SHA-1");
210: md5 = MessageDigest.getInstance("MD5");
211: tasks = new LinkedList<DelegatedTask>();
212: }
213:
214:
224: public final HandshakeStatus handleInput (ByteBuffer fragment)
225: throws SSLException
226: {
227: if (!tasks.isEmpty())
228: return HandshakeStatus.NEED_TASK;
229:
230: HandshakeStatus status = status();
231: if (status != HandshakeStatus.NEED_UNWRAP)
232: return status;
233:
234:
235: if (!pollHandshake(fragment))
236: return HandshakeStatus.NEED_UNWRAP;
237:
238: while (hasMessage() && status != HandshakeStatus.NEED_WRAP)
239: {
240: int pos = handshakeOffset;
241: status = implHandleInput();
242: int len = handshakeOffset - pos;
243: if (len == 0)
244: {
245:
246:
247: continue;
248: }
249: if (doHash())
250: {
251: if (Debug.DEBUG)
252: logger.logv(Component.SSL_HANDSHAKE, "hashing output\n{0}",
253: Util.hexDump((ByteBuffer) handshakeBuffer
254: .duplicate().position(pos)
255: .limit(pos+len), " >> "));
256: sha.update((ByteBuffer) handshakeBuffer.duplicate()
257: .position(pos).limit(pos+len));
258: md5.update((ByteBuffer) handshakeBuffer.duplicate()
259: .position(pos).limit(pos+len));
260: }
261: }
262: return status;
263: }
264:
265:
272: protected abstract HandshakeStatus implHandleInput()
273: throws SSLException;
274:
275:
286: public final HandshakeStatus handleOutput (ByteBuffer fragment)
287: throws SSLException
288: {
289: if (!tasks.isEmpty())
290: return HandshakeStatus.NEED_TASK;
291:
292: int orig = fragment.position();
293: SSLEngineResult.HandshakeStatus status = implHandleOutput(fragment);
294: if (doHash())
295: {
296: if (Debug.DEBUG)
297: logger.logv(Component.SSL_HANDSHAKE, "hashing output:\n{0}",
298: Util.hexDump((ByteBuffer) fragment.duplicate().flip().position(orig), " >> "));
299: sha.update((ByteBuffer) fragment.duplicate().flip().position(orig));
300: md5.update((ByteBuffer) fragment.duplicate().flip().position(orig));
301: }
302: return status;
303: }
304:
305:
314: protected abstract SSLEngineResult.HandshakeStatus implHandleOutput (ByteBuffer fragment)
315: throws SSLException;
316:
317:
328: final InputSecurityParameters getInputParams() throws SSLException
329: {
330: checkKeyExchange();
331: return inParams;
332: }
333:
334:
342: final OutputSecurityParameters getOutputParams() throws SSLException
343: {
344: checkKeyExchange();
345: return outParams;
346: }
347:
348:
353: final Runnable getTask()
354: {
355: if (tasks.isEmpty())
356: return null;
357: return tasks.removeFirst();
358: }
359:
360:
368: abstract HandshakeStatus status();
369:
370:
381: abstract void checkKeyExchange() throws SSLException;
382:
383:
388: abstract void handleV2Hello(ByteBuffer hello) throws SSLException;
389:
390:
402: protected boolean pollHandshake (final ByteBuffer fragment)
403: {
404:
405: if (handshakeBuffer == null
406: || handshakeBuffer.remaining() < fragment.remaining())
407: {
408:
409:
410: int len = ((handshakeBuffer == null) ? 0
411: : handshakeBuffer.position() - handshakeOffset);
412:
413:
414: len += fragment.remaining();
415: reallocateBuffer(len);
416: }
417:
418: if (Debug.DEBUG)
419: logger.logv(Component.SSL_HANDSHAKE, "inserting {0} into {1}",
420: fragment, handshakeBuffer);
421:
422:
423: handshakeBuffer.put(fragment);
424:
425: return hasMessage();
426: }
427:
428: protected boolean doHash()
429: {
430: return true;
431: }
432:
433:
437: protected boolean hasMessage()
438: {
439: if (handshakeBuffer == null)
440: return false;
441: ByteBuffer tmp = handshakeBuffer.duplicate();
442: tmp.flip();
443: tmp.position(handshakeOffset);
444: if (Debug.DEBUG)
445: logger.logv(Component.SSL_HANDSHAKE, "current buffer: {0}; test buffer {1}",
446: handshakeBuffer, tmp);
447: if (tmp.remaining() < 4)
448: return false;
449: Handshake handshake = new Handshake(tmp.slice());
450: if (Debug.DEBUG)
451: logger.logv(Component.SSL_HANDSHAKE, "handshake len:{0} remaining:{1}",
452: handshake.length(), tmp.remaining());
453: return (handshake.length() <= tmp.remaining() - 4);
454: }
455:
456:
461: private void reallocateBuffer (final int totalLen)
462: {
463: int len = handshakeBuffer == null ? -1
464: : handshakeBuffer.capacity() - (handshakeBuffer.limit() - handshakeOffset);
465: if (len >= totalLen)
466: {
467:
468:
469: if (handshakeOffset > 0)
470: {
471: handshakeBuffer.flip().position(handshakeOffset);
472: handshakeBuffer.compact();
473: handshakeOffset = 0;
474: }
475: return;
476: }
477:
478:
479:
480: len = 1024;
481: while (len < totalLen)
482: len = len << 1;
483: ByteBuffer newBuf = ByteBuffer.allocate (len);
484:
485:
486: if (handshakeBuffer != null)
487: {
488: handshakeBuffer.flip ();
489: handshakeBuffer.position(handshakeOffset);
490: newBuf.put(handshakeBuffer);
491: }
492: handshakeBuffer = newBuf;
493:
494:
495:
496: handshakeOffset = 0;
497: }
498:
499:
520: protected byte[] genV3CertificateVerify(MessageDigest md5,
521: MessageDigest sha,
522: SessionImpl session)
523: {
524: byte[] md5value = null;
525: if (session.suite.signatureAlgorithm() == SignatureAlgorithm.RSA)
526: {
527: md5.update(session.privateData.masterSecret);
528: md5.update(PAD1, 0, 48);
529: byte[] tmp = md5.digest();
530: md5.reset();
531: md5.update(session.privateData.masterSecret);
532: md5.update(PAD2, 0, 48);
533: md5.update(tmp);
534: md5value = md5.digest();
535: }
536:
537: sha.update(session.privateData.masterSecret);
538: sha.update(PAD1, 0, 40);
539: byte[] tmp = sha.digest();
540: sha.reset();
541: sha.update(session.privateData.masterSecret);
542: sha.update(PAD2, 0, 40);
543: sha.update(tmp);
544: byte[] shavalue = sha.digest();
545:
546: if (md5value != null)
547: return Util.concat(md5value, shavalue);
548:
549: return shavalue;
550: }
551:
552:
560: protected byte[][] generateKeys(Random clientRandom, Random serverRandom,
561: SessionImpl session)
562: {
563: int maclen = 20;
564: if (session.suite.macAlgorithm() == MacAlgorithm.MD5)
565: maclen = 16;
566: int ivlen = 0;
567: if (session.suite.cipherAlgorithm() == CipherAlgorithm.DES
568: || session.suite.cipherAlgorithm() == CipherAlgorithm.DESede)
569: ivlen = 8;
570: if (session.suite.cipherAlgorithm() == CipherAlgorithm.AES)
571: ivlen = 16;
572: int keylen = session.suite.keyLength();
573:
574: byte[][] keys = new byte[6][];
575: keys[0] = new byte[maclen];
576: keys[1] = new byte[maclen];
577: keys[2] = new byte[keylen];
578: keys[3] = new byte[keylen];
579: keys[4] = new byte[ivlen];
580: keys[5] = new byte[ivlen];
581:
582: IRandom prf = null;
583: if (session.version == ProtocolVersion.SSL_3)
584: {
585: byte[] seed = new byte[clientRandom.length()
586: + serverRandom.length()];
587: serverRandom.buffer().get(seed, 0, serverRandom.length());
588: clientRandom.buffer().get(seed, serverRandom.length(),
589: clientRandom.length());
590: prf = new SSLRandom();
591: HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2);
592: attr.put(SSLRandom.SECRET, session.privateData.masterSecret);
593: attr.put(SSLRandom.SEED, seed);
594: prf.init(attr);
595: }
596: else
597: {
598: byte[] seed = new byte[KEY_EXPANSION.length
599: + clientRandom.length()
600: + serverRandom.length()];
601: System.arraycopy(KEY_EXPANSION, 0, seed, 0, KEY_EXPANSION.length);
602: serverRandom.buffer().get(seed, KEY_EXPANSION.length,
603: serverRandom.length());
604: clientRandom.buffer().get(seed, (KEY_EXPANSION.length
605: + serverRandom.length()),
606: clientRandom.length());
607:
608: prf = new TLSRandom();
609: HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2);
610: attr.put(TLSRandom.SECRET, session.privateData.masterSecret);
611: attr.put(TLSRandom.SEED, seed);
612: prf.init(attr);
613: }
614:
615: try
616: {
617: prf.nextBytes(keys[0], 0, keys[0].length);
618: prf.nextBytes(keys[1], 0, keys[1].length);
619: prf.nextBytes(keys[2], 0, keys[2].length);
620: prf.nextBytes(keys[3], 0, keys[3].length);
621:
622: if (session.suite.isExportable())
623: {
624: if (session.version == ProtocolVersion.SSL_3)
625: {
626: MessageDigest md5 = MessageDigest.getInstance("MD5");
627: md5.update(clientRandom.buffer());
628: md5.update(serverRandom.buffer());
629: byte[] d = md5.digest();
630: System.arraycopy(d, 0, keys[4], 0, keys[4].length);
631:
632: md5.reset();
633: md5.update(serverRandom.buffer());
634: md5.update(clientRandom.buffer());
635: d = md5.digest();
636: System.arraycopy(d, 0, keys[5], 0, keys[5].length);
637:
638: md5.reset();
639: md5.update(keys[2]);
640: md5.update(clientRandom.buffer());
641: md5.update(serverRandom.buffer());
642: keys[2] = Util.trim(md5.digest(), 8);
643:
644: md5.reset();
645: md5.update(keys[3]);
646: md5.update(serverRandom.buffer());
647: md5.update(clientRandom.buffer());
648: keys[3] = Util.trim(md5.digest(), 8);
649: }
650: else
651: {
652: TLSRandom prf2 = new TLSRandom();
653: HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2);
654: attr.put(TLSRandom.SECRET, keys[2]);
655: byte[] seed = new byte[CLIENT_WRITE_KEY.length +
656: clientRandom.length() +
657: serverRandom.length()];
658: System.arraycopy(CLIENT_WRITE_KEY, 0, seed, 0,
659: CLIENT_WRITE_KEY.length);
660: clientRandom.buffer().get(seed, CLIENT_WRITE_KEY.length,
661: clientRandom.length());
662: serverRandom.buffer().get(seed, CLIENT_WRITE_KEY.length
663: + clientRandom.length(),
664: serverRandom.length());
665: attr.put(TLSRandom.SEED, seed);
666: prf2.init(attr);
667: keys[2] = new byte[8];
668: prf2.nextBytes(keys[2], 0, keys[2].length);
669:
670: attr.put(TLSRandom.SECRET, keys[3]);
671: seed = new byte[SERVER_WRITE_KEY.length +
672: serverRandom.length() +
673: clientRandom.length()];
674: System.arraycopy(SERVER_WRITE_KEY, 0, seed, 0,
675: SERVER_WRITE_KEY.length);
676: serverRandom.buffer().get(seed, SERVER_WRITE_KEY.length,
677: serverRandom.length());
678: clientRandom.buffer().get(seed, SERVER_WRITE_KEY.length
679: + serverRandom.length(),
680: + clientRandom.length());
681: attr.put(TLSRandom.SEED, seed);
682: prf2.init(attr);
683: keys[3] = new byte[8];
684: prf2.nextBytes(keys[3], 0, keys[3].length);
685:
686: attr.put(TLSRandom.SECRET, new byte[0]);
687: seed = new byte[IV_BLOCK.length +
688: clientRandom.length() +
689: serverRandom.length()];
690: System.arraycopy(IV_BLOCK, 0, seed, 0, IV_BLOCK.length);
691: clientRandom.buffer().get(seed, IV_BLOCK.length,
692: clientRandom.length());
693: serverRandom.buffer().get(seed, IV_BLOCK.length
694: + clientRandom.length(),
695: serverRandom.length());
696: attr.put(TLSRandom.SEED, seed);
697: prf2.init(attr);
698: prf2.nextBytes(keys[4], 0, keys[4].length);
699: prf2.nextBytes(keys[5], 0, keys[5].length);
700: }
701: }
702: else
703: {
704: prf.nextBytes(keys[4], 0, keys[4].length);
705: prf.nextBytes(keys[5], 0, keys[5].length);
706: }
707: }
708: catch (LimitReachedException lre)
709: {
710:
711: throw new Error(lre);
712: }
713: catch (NoSuchAlgorithmException nsae)
714: {
715: throw new Error(nsae);
716: }
717:
718: if (Debug.DEBUG_KEY_EXCHANGE)
719: logger.logv(Component.SSL_KEY_EXCHANGE,
720: "keys generated;\n [0]: {0}\n [1]: {1}\n [2]: {2}\n" +
721: " [3]: {3}\n [4]: {4}\n [5]: {5}",
722: Util.toHexString(keys[0], ':'),
723: Util.toHexString(keys[1], ':'),
724: Util.toHexString(keys[2], ':'),
725: Util.toHexString(keys[3], ':'),
726: Util.toHexString(keys[4], ':'),
727: Util.toHexString(keys[5], ':'));
728: return keys;
729: }
730:
731:
743: protected ByteBuffer generateFinished(MessageDigest md5,
744: MessageDigest sha,
745: boolean isClient,
746: SessionImpl session)
747: {
748: ByteBuffer finishedBuffer = null;
749: if (session.version.compareTo(ProtocolVersion.TLS_1) >= 0)
750: {
751: finishedBuffer = ByteBuffer.allocate(12);
752: TLSRandom prf = new TLSRandom();
753: byte[] md5val = md5.digest();
754: byte[] shaval = sha.digest();
755: if (Debug.DEBUG)
756: logger.logv(Component.SSL_HANDSHAKE, "finished md5:{0} sha:{1}",
757: Util.toHexString(md5val, ':'),
758: Util.toHexString(shaval, ':'));
759: byte[] seed = new byte[CLIENT_FINISHED.length
760: + md5val.length
761: + shaval.length];
762: if (isClient)
763: System.arraycopy(CLIENT_FINISHED, 0, seed, 0, CLIENT_FINISHED.length);
764: else
765: System.arraycopy(SERVER_FINISHED, 0, seed, 0, SERVER_FINISHED.length);
766: System.arraycopy(md5val, 0,
767: seed, CLIENT_FINISHED.length,
768: md5val.length);
769: System.arraycopy(shaval, 0,
770: seed, CLIENT_FINISHED.length + md5val.length,
771: shaval.length);
772: HashMap<String, Object> params = new HashMap<String, Object>(2);
773: params.put(TLSRandom.SECRET, session.privateData.masterSecret);
774: params.put(TLSRandom.SEED, seed);
775: prf.init(params);
776: byte[] buf = new byte[12];
777: prf.nextBytes(buf, 0, buf.length);
778: finishedBuffer.put(buf).position(0);
779: }
780: else
781: {
782:
783:
784:
785:
786:
787:
788:
789:
790:
791:
792:
793:
794:
795:
796:
797:
798:
799: finishedBuffer = ByteBuffer.allocate(36);
800:
801: md5.update(isClient ? SENDER_CLIENT : SENDER_SERVER);
802: md5.update(session.privateData.masterSecret);
803: md5.update(PAD1);
804:
805: byte[] tmp = md5.digest();
806: md5.reset();
807: md5.update(session.privateData.masterSecret);
808: md5.update(PAD2);
809: md5.update(tmp);
810: finishedBuffer.put(md5.digest());
811:
812: sha.update(isClient ? SENDER_CLIENT : SENDER_SERVER);
813: sha.update(session.privateData.masterSecret);
814: sha.update(PAD1, 0, 40);
815:
816: tmp = sha.digest();
817: sha.reset();
818: sha.update(session.privateData.masterSecret);
819: sha.update(PAD2, 0, 40);
820: sha.update(tmp);
821: finishedBuffer.put(sha.digest()).position(0);
822: }
823: return finishedBuffer;
824: }
825:
826: protected void initDiffieHellman(DHPrivateKey dhKey, SecureRandom random)
827: throws SSLException
828: {
829: try
830: {
831: keyAgreement = KeyAgreement.getInstance("DH");
832: keyAgreement.init(dhKey, random);
833: }
834: catch (InvalidKeyException ike)
835: {
836: throw new SSLException(ike);
837: }
838: catch (NoSuchAlgorithmException nsae)
839: {
840: throw new SSLException(nsae);
841: }
842: }
843:
844: protected void generateMasterSecret(Random clientRandom,
845: Random serverRandom,
846: SessionImpl session)
847: throws SSLException
848: {
849: assert(clientRandom != null);
850: assert(serverRandom != null);
851: assert(session != null);
852:
853: if (Debug.DEBUG_KEY_EXCHANGE)
854: logger.logv(Component.SSL_KEY_EXCHANGE, "preMasterSecret:\n{0}",
855: new ByteArray(preMasterSecret));
856:
857: if (session.version == ProtocolVersion.SSL_3)
858: {
859: try
860: {
861: MessageDigest _md5 = MessageDigest.getInstance("MD5");
862: MessageDigest _sha = MessageDigest.getInstance("SHA");
863: session.privateData.masterSecret = new byte[48];
864:
865: _sha.update((byte) 'A');
866: _sha.update(preMasterSecret);
867: _sha.update(clientRandom.buffer());
868: _sha.update(serverRandom.buffer());
869: _md5.update(preMasterSecret);
870: _md5.update(_sha.digest());
871: _md5.digest(session.privateData.masterSecret, 0, 16);
872:
873: _sha.update((byte) 'B');
874: _sha.update((byte) 'B');
875: _sha.update(preMasterSecret);
876: _sha.update(clientRandom.buffer());
877: _sha.update(serverRandom.buffer());
878: _md5.update(preMasterSecret);
879: _md5.update(_sha.digest());
880: _md5.digest(session.privateData.masterSecret, 16, 16);
881:
882: _sha.update((byte) 'C');
883: _sha.update((byte) 'C');
884: _sha.update((byte) 'C');
885: _sha.update(preMasterSecret);
886: _sha.update(clientRandom.buffer());
887: _sha.update(serverRandom.buffer());
888: _md5.update(preMasterSecret);
889: _md5.update(_sha.digest());
890: _md5.digest(session.privateData.masterSecret, 32, 16);
891: }
892: catch (DigestException de)
893: {
894: throw new SSLException(de);
895: }
896: catch (NoSuchAlgorithmException nsae)
897: {
898: throw new SSLException(nsae);
899: }
900: }
901: else
902: {
903: byte[] seed = new byte[clientRandom.length()
904: + serverRandom.length()
905: + MASTER_SECRET.length];
906: System.arraycopy(MASTER_SECRET, 0, seed, 0, MASTER_SECRET.length);
907: clientRandom.buffer().get(seed, MASTER_SECRET.length,
908: clientRandom.length());
909: serverRandom.buffer().get(seed,
910: MASTER_SECRET.length + clientRandom.length(),
911: serverRandom.length());
912: TLSRandom prf = new TLSRandom();
913: HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2);
914: attr.put(TLSRandom.SECRET, preMasterSecret);
915: attr.put(TLSRandom.SEED, seed);
916: prf.init(attr);
917:
918: session.privateData.masterSecret = new byte[48];
919: prf.nextBytes(session.privateData.masterSecret, 0, 48);
920: }
921:
922: if (Debug.DEBUG_KEY_EXCHANGE)
923: logger.log(Component.SSL_KEY_EXCHANGE, "master_secret: {0}",
924: new ByteArray(session.privateData.masterSecret));
925:
926:
927: for (int i = 0; i < preMasterSecret.length; i++)
928: preMasterSecret[i] = 0;
929: }
930:
931: protected void setupSecurityParameters(byte[][] keys, boolean isClient,
932: SSLEngineImpl engine,
933: CompressionMethod compression)
934: throws SSLException
935: {
936: assert(keys.length == 6);
937: assert(engine != null);
938: assert(compression != null);
939:
940: try
941: {
942: CipherSuite s = engine.session().suite;
943: Cipher inCipher = s.cipher();
944: Mac inMac = s.mac(engine.session().version);
945: Inflater inflater = (compression == CompressionMethod.ZLIB
946: ? new Inflater() : null);
947: inCipher.init(Cipher.DECRYPT_MODE,
948: new SecretKeySpec(keys[isClient ? 3 : 2],
949: s.cipherAlgorithm().toString()),
950: new IvParameterSpec(keys[isClient ? 5 : 4]));
951: inMac.init(new SecretKeySpec(keys[isClient ? 1 : 0],
952: inMac.getAlgorithm()));
953: inParams = new InputSecurityParameters(inCipher, inMac,
954: inflater,
955: engine.session(), s);
956:
957: Cipher outCipher = s.cipher();
958: Mac outMac = s.mac(engine.session().version);
959: Deflater deflater = (compression == CompressionMethod.ZLIB
960: ? new Deflater() : null);
961: outCipher.init(Cipher.ENCRYPT_MODE,
962: new SecretKeySpec(keys[isClient ? 2 : 3],
963: s.cipherAlgorithm().toString()),
964: new IvParameterSpec(keys[isClient ? 4 : 5]));
965: outMac.init(new SecretKeySpec(keys[isClient ? 0 : 1],
966: outMac.getAlgorithm()));
967: outParams = new OutputSecurityParameters(outCipher, outMac,
968: deflater,
969: engine.session(), s);
970: }
971: catch (InvalidAlgorithmParameterException iape)
972: {
973: throw new SSLException(iape);
974: }
975: catch (InvalidKeyException ike)
976: {
977: throw new SSLException(ike);
978: }
979: catch (NoSuchAlgorithmException nsae)
980: {
981: throw new SSLException(nsae);
982: }
983: catch (NoSuchPaddingException nspe)
984: {
985: throw new SSLException(nspe);
986: }
987: }
988:
989: protected void generatePSKSecret(String identity, byte[] otherkey,
990: boolean isClient)
991: throws SSLException
992: {
993: SecretKey key = null;
994: try
995: {
996: key = engine.contextImpl.pskManager.getKey(identity);
997: }
998: catch (KeyManagementException kme)
999: {
1000: }
1001: if (key != null)
1002: {
1003: byte[] keyb = key.getEncoded();
1004: if (otherkey == null)
1005: {
1006: otherkey = new byte[keyb.length];
1007: }
1008: preMasterSecret = new byte[otherkey.length + keyb.length + 4];
1009: preMasterSecret[0] = (byte) (otherkey.length >>> 8);
1010: preMasterSecret[1] = (byte) otherkey.length;
1011: System.arraycopy(otherkey, 0, preMasterSecret, 2, otherkey.length);
1012: preMasterSecret[otherkey.length + 2]
1013: = (byte) (keyb.length >>> 8);
1014: preMasterSecret[otherkey.length + 3]
1015: = (byte) keyb.length;
1016: System.arraycopy(keyb, 0, preMasterSecret,
1017: otherkey.length + 4, keyb.length);
1018: }
1019: else
1020: {
1021:
1022: preMasterSecret = new byte[8];
1023: preMasterSecret[1] = 2;
1024: preMasterSecret[5] = 2;
1025: preMasterSecret[6] = (byte) engine.session().random().nextInt();
1026: preMasterSecret[7] = (byte) engine.session().random().nextInt();
1027: }
1028:
1029: if (Debug.DEBUG_KEY_EXCHANGE)
1030: logger.logv(Component.SSL_KEY_EXCHANGE, "PSK identity {0} key {1}",
1031: identity, key);
1032:
1033: generateMasterSecret(clientRandom, serverRandom,
1034: engine.session());
1035: byte[][] keys = generateKeys(clientRandom, serverRandom,
1036: engine.session());
1037: setupSecurityParameters(keys, isClient, engine, compression);
1038: }
1039:
1040: protected class DHPhase extends DelegatedTask
1041: {
1042: private final DHPublicKey key;
1043: private final boolean full;
1044:
1045: protected DHPhase(DHPublicKey key)
1046: {
1047: this(key, true);
1048: }
1049:
1050: protected DHPhase(DHPublicKey key, boolean full)
1051: {
1052: this.key = key;
1053: this.full = full;
1054: }
1055:
1056: protected void implRun() throws InvalidKeyException, SSLException
1057: {
1058: keyAgreement.doPhase(key, true);
1059: preMasterSecret = keyAgreement.generateSecret();
1060: if (full)
1061: {
1062: generateMasterSecret(clientRandom, serverRandom, engine.session());
1063: byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
1064: setupSecurityParameters(keys, engine.getUseClientMode(), engine, compression);
1065: }
1066: }
1067: }
1068:
1069: protected class CertVerifier extends DelegatedTask
1070: {
1071: private final boolean clientSide;
1072: private final X509Certificate[] chain;
1073: private boolean verified;
1074:
1075: protected CertVerifier(boolean clientSide, X509Certificate[] chain)
1076: {
1077: this.clientSide = clientSide;
1078: this.chain = chain;
1079: }
1080:
1081: boolean verified()
1082: {
1083: return verified;
1084: }
1085:
1086: protected void implRun()
1087: {
1088: X509TrustManager tm = engine.contextImpl.trustManager;
1089: if (clientSide)
1090: {
1091: try
1092: {
1093: tm.checkServerTrusted(chain, null);
1094: verified = true;
1095: }
1096: catch (CertificateException ce)
1097: {
1098: if (Debug.DEBUG)
1099: logger.log(Component.SSL_DELEGATED_TASK, "cert verify", ce);
1100:
1101: CallbackHandler verify = new DefaultCallbackHandler();
1102: GetSecurityPropertyAction gspa
1103: = new GetSecurityPropertyAction("jessie.certificate.handler");
1104: String clazz = AccessController.doPrivileged(gspa);
1105: try
1106: {
1107: ClassLoader cl =
1108: AccessController.doPrivileged(new PrivilegedExceptionAction<ClassLoader>()
1109: {
1110: public ClassLoader run() throws Exception
1111: {
1112: return ClassLoader.getSystemClassLoader();
1113: }
1114: });
1115: verify = (CallbackHandler) cl.loadClass(clazz).newInstance();
1116: }
1117: catch (Exception x)
1118: {
1119:
1120: if (Debug.DEBUG)
1121: logger.log(Component.SSL_DELEGATED_TASK,
1122: "callback handler loading", x);
1123: }
1124:
1125: CertificateCallback confirm =
1126: new CertificateCallback(chain[0],
1127: "The server's certificate could not be verified. There is no proof " +
1128: "that this server is who it claims to be, or that their certificate " +
1129: "is valid. Do you wish to continue connecting? ");
1130:
1131: try
1132: {
1133: verify.handle(new Callback[] { confirm });
1134: verified = confirm.getSelectedIndex() == ConfirmationCallback.YES;
1135: }
1136: catch (Exception x)
1137: {
1138: if (Debug.DEBUG)
1139: logger.log(Component.SSL_DELEGATED_TASK,
1140: "callback handler exception", x);
1141: verified = false;
1142: }
1143: }
1144: }
1145: else
1146: {
1147: try
1148: {
1149: tm.checkClientTrusted(chain, null);
1150: }
1151: catch (CertificateException ce)
1152: {
1153: verified = false;
1154: }
1155: }
1156:
1157: if (verified)
1158: engine.session().setPeerVerified(true);
1159: }
1160: }
1161:
1162: protected class DHE_PSKGen extends DelegatedTask
1163: {
1164: private final DHPublicKey dhKey;
1165: private final SecretKey psKey;
1166: private final boolean isClient;
1167:
1168: protected DHE_PSKGen(DHPublicKey dhKey, SecretKey psKey, boolean isClient)
1169: {
1170: this.dhKey = dhKey;
1171: this.psKey = psKey;
1172: this.isClient = isClient;
1173: }
1174:
1175:
1178: @Override protected void implRun() throws Throwable
1179: {
1180: keyAgreement.doPhase(dhKey, true);
1181: byte[] dhSecret = keyAgreement.generateSecret();
1182: byte[] psSecret = null;
1183: if (psKey != null)
1184: psSecret = psKey.getEncoded();
1185: else
1186: {
1187: psSecret = new byte[8];
1188: engine.session().random().nextBytes(psSecret);
1189: }
1190:
1191: preMasterSecret = new byte[dhSecret.length + psSecret.length + 4];
1192: preMasterSecret[0] = (byte) (dhSecret.length >>> 8);
1193: preMasterSecret[1] = (byte) dhSecret.length;
1194: System.arraycopy(dhSecret, 0, preMasterSecret, 2, dhSecret.length);
1195: preMasterSecret[dhSecret.length + 2] = (byte) (psSecret.length >>> 8);
1196: preMasterSecret[dhSecret.length + 3] = (byte) psSecret.length;
1197: System.arraycopy(psSecret, 0, preMasterSecret, dhSecret.length + 4,
1198: psSecret.length);
1199:
1200: generateMasterSecret(clientRandom, serverRandom, engine.session());
1201: byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
1202: setupSecurityParameters(keys, isClient, engine, compression);
1203: }
1204: }
1205: }