Source Code Cross Referenced for Record.java in  » Portal » Open-Portal » com » sun » portal » kssl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Portal » Open Portal » com.sun.portal.kssl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)Record.java	1.23 02/07/24 @(#)
003:         *
004:         * Copyright (c) 2000-2002 Sun Microsystems, Inc.  All rights reserved.
005:         * PROPRIETARY/CONFIDENTIAL
006:         * Use is subject to license terms.
007:         */
008:
009:        package com.sun.portal.kssl;
010:
011:        import java.io.InputStream;
012:        import java.io.DataInputStream;
013:        import java.io.OutputStream;
014:        import java.io.IOException;
015:        import com.sun.portal.ksecurity.MessageDigest;
016:        import com.sun.portal.ksecurity.SecretKey;
017:        import com.sun.portal.ksecurity.KeyBuilder;
018:
019:        /**
020:         * Implements an SSL record layer that sits atop a TCP connection
021:         * and beneath the user-visible interface to an SSL socket. It 
022:         * maintains all the state information necessary to encode/decode
023:         * application data.
024:         */
025:        class Record {
026:            /*
027:             * TODO: We should try to avoid multiple buffer copies by defining a 
028:             * new message class that allocates a large enough buffer to begin with 
029:             * so new headers can be prepended and MAC/padding can be appended by 
030:             * simple pointer manipulation.
031:             */
032:
033:            /*
034:             * SSLRecord types: CCS (Change Cipher Spec), ALRT (Alert),
035:             * HNDSHK (Handshake) and APP (Application Data)
036:             */
037:            /** Change Cipher Spec (20). */
038:            static final byte CCS = 20;
039:            /** Alert (21). */
040:            static final byte ALRT = 21;
041:            /** Handshake (22). */
042:            static final byte HNDSHK = 22;
043:            /** Application data (23). */
044:            static final byte APP = 23;
045:
046:            // There are two severity levels for alerts
047:            /** Warning severity level for alerts (1). */
048:            static final byte WARNING = 1;
049:            /** Fatal severity level for alerts (2). */
050:            static final byte FATAL = 2;
051:
052:            // Next, we have various Alert types
053:            /** Close notification alert type (0). */
054:            static final byte CLOSE_NTFY = 0;
055:            /** Unexpected message alert type (10). */
056:            static final byte UNEXP_MSG = 10;
057:            /** Bad MAC alert type (20). */
058:            static final byte BAD_MAC = 20;
059:            // static final byte DECOMP_FAIL = 30;  we do not support compression
060:            /** Handshake failure alert type (40). */
061:            static final byte HNDSHK_FAIL = 40;
062:            /** No certificate found alert type (41). */
063:            static final byte NO_CERT = 41;
064:            /** Bad certificate alert type (42). */
065:            static final byte BAD_CERT = 42;
066:            /** Unsupported certificate alert type (43). */
067:            static final byte UNSUP_CERT = 43;
068:            /** Certificate revoked alert type (44). */
069:            static final byte CERT_REVKD = 44;
070:            /** Certificate expired alaert type (45). */
071:            static final byte CERT_EXPRD = 45;
072:            /** Unknown certificate feature alert type (46). */
073:            static final byte CERT_UNKWN = 46;
074:            /** Bad parameter alert type (47). */
075:            static final byte BAD_PARAM = 47;
076:
077:            /*
078:             * Possible roles for this SSL record layer (client or server).
079:             */
080:            /** Server role for SSL record layout (0). */
081:            static final byte SERVER = 0;
082:            /** Client role for SSL record layout (1). */
083:            static final byte CLIENT = 1;
084:
085:            /** 
086:             * PAD1 is a 48-byte array filled with 0x36. It is used in
087:             * MAC computations.
088:             */
089:            static final byte[] PAD1 = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
090:                    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
091:                    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
092:                    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
093:                    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
094:                    0x36, 0x36 };
095:
096:            /** 
097:             * PAD2 is a 48-byte array filled with 0x5c. It is used in
098:             * MAC computations.
099:             */
100:            static final byte[] PAD2 = { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
101:                    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
102:                    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
103:                    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
104:                    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
105:                    0x5c, 0x5c };
106:            /** Size of record header */
107:            private final int HEADER_SIZE = 5;
108:            /** Underlying input stream beneath the record layer. */
109:            private InputStream in;
110:            /** Underlying output stream beneath the record layer. */
111:            private OutputStream out;
112:
113:            // Connection state information
114:            /** Client MAC seceret. */
115:            private byte[] cMACKey;
116:            /** Server MAC secret. */
117:            private byte[] sMACKey;
118:            /** Client write key for bulk encryption. */
119:            private byte[] cKey;
120:            /** Server write key for bulk encryption. */
121:            private byte[] sKey;
122:            /** Client write IV for block encryption. */
123:            private byte[] cIV;
124:            /** Server write IV for block encryption. */
125:            private byte[] sIV;
126:            /** Client write sequence number. */
127:            private long cSeq = (long) 0;
128:            /** Server write sequence number. */
129:            private long sSeq = (long) 0;
130:            /** Current role (either client or server). */
131:            private byte role;
132:            /** Flag indicating change cipher spec received. */
133:            private byte rActive = 0;
134:            /** Flag indicating change cipher spec has been sent. */
135:            private byte wActive = 0;
136:
137:            /** Current digest. */
138:            private MessageDigest d = null;
139:            /** Length of the digest generated by d. */
140:            private byte dLen = 0;
141:            /** Length of PAD1/PAD2 used in MACs. */
142:            private int padLen = 0;
143:            /** Client write cipher. */
144:            private Cipher cc = null;
145:            /** Server write cipher/client decryptor. */
146:            private Cipher sc = null;
147:            /** Clients bulk encryption secret key. */
148:            private SecretKey cBulkKey = null;
149:            /** Servers bulk encryption secret key. */
150:            private SecretKey sBulkKey = null;
151:            /** The SSL version in one byte (0x30=3.0). */
152:            private byte ver;
153:            /**
154:             * Flag indicating type of cipher (1 for a block 
155:             * cipher, 0 otherwise).
156:             */
157:            private byte isBlk = 0;
158:            /** Cipher block length. */
159:            private int cblk = 1;
160:            /** Current input header. */
161:            private byte[] inputHeader = new byte[HEADER_SIZE];
162:            /** Current input data. */
163:            byte[] inputData;
164:            /** Offset of the plain text in the input buffer */
165:            int plainTextOffset;
166:            /** Length of the plain text in the input buffer */
167:            int plainTextLength = -1;
168:
169:            /**
170:             * Creates a new SSL record layer.
171:             * <P />
172:             * @param who  role (either CLIENT or SERVER) of this side in
173:             *             the SSL negotiation     
174:             * @param ins  input stream belonging to the underlying TCP connection
175:             * @param outs output stream belonging to the underlying TCP connection
176:             */
177:            Record(byte who, InputStream ins, OutputStream outs) {
178:                in = ins;
179:                out = outs;
180:                ver = (byte) 0x30; // TODO: This is hardcoded for now
181:                role = who;
182:            }
183:
184:            /**
185:             * Frees record layer data structures.
186:             */
187:            void destroy() {
188:                in = null;
189:                out = null;
190:                cMACKey = sMACKey = null;
191:                cIV = sIV = null;
192:                d = null;
193:                cc = sc = null;
194:                cBulkKey = sBulkKey = null;
195:            }
196:
197:            /**
198:             * Increments the client-side or server-side write sequence 
199:             * number depending on the specified argument.
200:             * <P />
201:             * @param who one of CLIENT or SERVER
202:             * @exception IOException if the sequence numbers rolls around
203:             */
204:            private void bump(byte who) throws IOException {
205:                if (who == CLIENT) {
206:                    if (++cSeq == (long) 0)
207:                        throw new IOException("Clnt seq rolled over");
208:                } else {
209:                    if (++sSeq == (long) 0)
210:                        throw new IOException("Srvr seq rolled over");
211:                }
212:            }
213:
214:            /**
215:             * Chops up a master secret into the client and server MAC secrets, 
216:             * bulk encryption keys and IVs. Also initializes the Cipher and 
217:             * MessageDigest objects used in record encoding/decoding. 
218:             * <P />
219:             * @param crand 32-byte random value chosen by the client
220:             * @param srand 32-byte random value chosen by the server
221:             * @param suite negotiated cipher suite
222:             * @param master master secret resulting from the key exchange
223:             * @exception Exception if the negotiated cipher suite involves an 
224:             * unsupported hash or cipher algorithm
225:             */
226:            void init(byte[] crand, byte[] srand, byte suite, byte[] master)
227:                    throws Exception {
228:                /* 
229:                 * The following should suffice to generate a total of
230:                 * 16*7 = 112 bytes of key material. 3DES_SHA requires
231:                 * 2*(20 + 24 + 8) = 104 bytes.
232:                 */
233:                byte[] expansion[] = { { 0x41 }, // 'A'
234:                        { 0x42, 0x42 }, // 'BB'
235:                        { 0x43, 0x43, 0x43 }, // 'CCC'
236:                        { 0x44, 0x44, 0x44, 0x44 }, // 'DDDD'
237:                        { 0x45, 0x45, 0x45, 0x45, 0x45 }, // 'EEEEE'
238:                        { 0x46, 0x46, 0x46, 0x46, 0x46, 0x46 }, // 'FFFFFF'
239:                        { 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47 }, // 'GGGGGGG'
240:                };
241:
242:                /* 
243:                 * The actual size of our computed key block is the closest 
244:                 * 16-byte multiple and depends on the choice of hashing
245:                 * and encryption algorithms.
246:                 */
247:                int keyMat = 5;
248:                //Support for new Ciphers  
249:                int ivSize = 0;
250:                switch (suite) {
251:                case CipherSuites.ARCFOUR_128_MD5:
252:                    keyMat = 16;
253:                    d = MessageDigest.getInstance(MessageDigest.ALG_MD5, false);
254:                    dLen = 16;
255:                    padLen = 48;
256:                    break;
257:
258:                // fall through
259:                case CipherSuites.ARCFOUR_40_MD5:
260:                    d = MessageDigest.getInstance(MessageDigest.ALG_MD5, false);
261:                    dLen = 16;
262:                    padLen = 48;
263:                    break;
264:
265:                case CipherSuites.ARCFOUR_128_SHA:
266:                    keyMat = 16;
267:                    d = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
268:                    dLen = 20;
269:                    padLen = 40;
270:                    break;
271:
272:                //Support for new Ciphers  
273:                case CipherSuites.DES_CBC_SHA:
274:                    ivSize = 8;
275:                    keyMat = 8;
276:                    d = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
277:                    dLen = 20;
278:                    padLen = 40;
279:                    break;
280:
281:                case CipherSuites.TRIPLEDES_CBC_SHA:
282:                    ivSize = 8;
283:                    keyMat = 24;
284:                    d = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
285:                    dLen = 20;
286:                    padLen = 40;
287:                    break;
288:
289:                default:
290:                    throw new RuntimeException("Unsupported suite");
291:                }
292:
293:                /*
294:                 * key_block =
295:                 *    MD5(master + SHA('A' + master +
296:                 *                     ServerHello.random + ClientHello.random)) +
297:                 *    MD5(master + SHA('BB' + master +
298:                 *                     ServerHello.random + ClientHello.random)) +
299:                 *    MD5(master + SHA('CCC' + master +
300:                 *                     ServerHello.random + ClientHello.random)) +
301:                 *    [..]
302:                 *
303:                 * We set 
304:                 *     tmp = master + ServerHello.random + ClientHello.random
305:                 */
306:                byte[] tmp = new byte[master.length + srand.length
307:                        + crand.length];
308:                System.arraycopy(master, 0, tmp, 0, master.length);
309:                System.arraycopy(srand, 0, tmp, master.length, srand.length);
310:                System.arraycopy(crand, 0, tmp, (master.length + srand.length),
311:                        crand.length);
312:                /* 
313:                 * Key block size is the closest 16-byte multiple larger than
314:                 *       2x(hash_size + key_material + IV_size)
315:                 * int keyMat = CipherSuite.cipherList[
316:                 * CipherSuite.suiteList[suite][2]][2];
317:                 * int ivSize = CipherSuite.cipherList[
318:                 *          CipherSuite.suiteList[suite][2]][4];
319:                 */
320:                //Support for new Ciphers  
321:                //int ivSize = 0; // stream ciphers do not use IVs
322:                int i = (dLen + keyMat + ivSize) << 1;
323:                byte[] kBlk = new byte[((i + 15) >>> 4) << 4];
324:                MessageDigest md = MessageDigest.getInstance(
325:                        MessageDigest.ALG_MD5, false);
326:                MessageDigest sd = MessageDigest.getInstance(
327:                        MessageDigest.ALG_SHA, false);
328:
329:                for (i = 0; i < (kBlk.length >>> 4); i++) {
330:                    md.update(master, 0, master.length);
331:                    sd.update(expansion[i], 0, expansion[i].length);
332:                    byte[] res = new byte[20];
333:                    sd.doFinal(tmp, 0, tmp.length, res, 0);
334:                    md.doFinal(res, 0, 20, kBlk, i << 4);
335:                }
336:
337:                // At this point, we have a key block in kBlk. Chop it up!
338:                cMACKey = new byte[dLen];
339:                sMACKey = new byte[dLen];
340:                System.arraycopy(kBlk, 0, cMACKey, 0, cMACKey.length);
341:                System.arraycopy(kBlk, cMACKey.length, sMACKey, 0,
342:                        sMACKey.length);
343:
344:                cKey = new byte[keyMat];
345:                sKey = new byte[keyMat];
346:                System
347:                        .arraycopy(kBlk, 2 * cMACKey.length, cKey, 0,
348:                                cKey.length);
349:                System.arraycopy(kBlk, (2 * cMACKey.length + cKey.length),
350:                        sKey, 0, sKey.length);
351:
352:                cIV = new byte[ivSize];
353:                sIV = new byte[ivSize];
354:                if (suite == CipherSuites.ARCFOUR_128_MD5
355:                        || suite == CipherSuites.ARCFOUR_128_SHA) {
356:                    /*
357:                     * NOTE: We know ivSze is always zero for ARCFOUR cipher suites
358:                     * so this is commented out. It wasn't removed in case we need
359:                     * to add support for DES or another block cipher.
360:                     *  if (ivSize != 0) {
361:                     *      // bulk encryption uses a block cipher, so initialize IVs
362:                     *       System.arraycopy(kBlk, 2*(cMACKey.length + cKey.length), 
363:                     *           cIV, 0, ivSize);
364:                     *        System.arraycopy(kBlk, 2*(cMACKey.length + cKey.length)
365:                     *                 + ivSize, sIV, 0, ivSize);
366:                     * }
367:                     */
368:                }
369:                //Support for new Ciphers  
370:                else if ((suite == CipherSuites.DES_CBC_SHA)
371:                        || (suite == CipherSuites.TRIPLEDES_CBC_SHA)) {
372:                    if (ivSize != 0) {
373:                        // bulk encryption uses a block cipher, so initialize IVs
374:                        System.arraycopy(kBlk,
375:                                2 * (cMACKey.length + cKey.length), cIV, 0,
376:                                ivSize);
377:                        System.arraycopy(kBlk, 2
378:                                * (cMACKey.length + cKey.length) + ivSize, sIV,
379:                                0, ivSize);
380:                    }
381:                } else {
382:                    /* 
383:                     * TODO: The only other option is ARCFOUR_40_MD5
384:                     * 
385:                     * Expand the keys for exportable cipher suites
386:                     *  final_client_write_key = MD5(client_write_key +
387:                     *                                ClientHello.random +
388:                     *                               ServerHello.random);
389:                     *  final_server_write_key = MD5(server_write_key +
390:                     *                               ServerHello.random +
391:                     *                               ClientHello.random);
392:                     */
393:                    byte[] res = new byte[16];
394:                    md.update(cKey, 0, cKey.length);
395:                    md.update(crand, 0, crand.length);
396:                    md.doFinal(srand, 0, srand.length, res, 0);
397:
398:                    /* 
399:                     * NOTE: For both ARCFOUR_128_MD5 and ARCFOUR_40_MD5, 
400:                     * expanded key is 16
401:                     */
402:                    byte[] fcKey = new byte[16];
403:                    System.arraycopy(res, 0, fcKey, 0, fcKey.length);
404:
405:                    md.update(sKey, 0, sKey.length);
406:                    md.update(srand, 0, srand.length);
407:                    md.doFinal(crand, 0, crand.length, res, 0);
408:                    byte[] fsKey = new byte[fcKey.length];
409:                    System.arraycopy(res, 0, fsKey, 0, fsKey.length);
410:
411:                    cKey = fcKey;
412:                    sKey = fsKey;
413:
414:                    /* 
415:                     * ... and compute IVs in a special way
416:                     * client_write_IV = MD5(ClientHello.random + ServerHello.random)
417:                     * server_write_IV = MD5(ServerHello.random + ClientHello.random)
418:                     * 
419:                     * NOTE: We know for the chosen ciphersuites, ivSize is zero
420:                     * so this code is commented out for now
421:                     */
422:                    //Support for new Ciphers  
423:                    if (ivSize != 0) {
424:                        md.update(crand, (short) 0, (short) crand.length);
425:                        md.doFinal(srand, (short) 0, (short) srand.length, res,
426:                                (short) 0);
427:                        System.arraycopy(res, 0, cIV, 0, ivSize);
428:
429:                        md.update(srand, (short) 0, (short) srand.length);
430:                        md.doFinal(crand, (short) 0, (short) crand.length, res,
431:                                (short) 0);
432:                        System.arraycopy(res, 0, sIV, 0, ivSize);
433:                    }
434:
435:                }
436:
437:                /*
438:                 * Now initialize the ciphers and keys. FOr now this is always
439:                 * ARCFOUR and we comment out support for other ciphers.
440:                 */
441:                if (suite == CipherSuites.DES_CBC_SHA) {
442:                    cBulkKey = (SecretKey) KeyBuilder.buildKey(
443:                            KeyBuilder.TYPE_DES, (short) (cKey.length << 3),
444:                            false);
445:                    cBulkKey.setKey(cKey, (short) 0);
446:                    cc = Cipher.getInstance(Cipher.ALG_DES, false);
447:                    cc.init(cBulkKey, Cipher.MODE_ENCRYPT, cIV, 0, cIV.length);
448:
449:                    sBulkKey = (SecretKey) KeyBuilder.buildKey(
450:                            KeyBuilder.TYPE_DES, (short) (sKey.length << 3),
451:                            false);
452:                    sBulkKey.setKey(sKey, (short) 0);
453:                    sc = Cipher.getInstance(Cipher.ALG_DES, false);
454:                    sc.init(sBulkKey, Cipher.MODE_DECRYPT, sIV, 0, sIV.length);
455:
456:                    cblk = 8;
457:                    isBlk = 1;
458:
459:                } else if (suite == CipherSuites.TRIPLEDES_CBC_SHA) {
460:                    cBulkKey = (SecretKey) KeyBuilder.buildKey(
461:                            KeyBuilder.TYPE_TRIPLEDES,
462:                            (short) (cKey.length << 3), false);
463:                    cBulkKey.setKey(cKey, (short) 0);
464:                    cc = Cipher.getInstance(Cipher.ALG_TRIPLEDES, false);
465:                    cc.init(cBulkKey, Cipher.MODE_ENCRYPT, cIV, 0, cIV.length);
466:
467:                    sBulkKey = (SecretKey) KeyBuilder.buildKey(
468:                            KeyBuilder.TYPE_TRIPLEDES,
469:                            (short) (sKey.length << 3), false);
470:                    sBulkKey.setKey(sKey, (short) 0);
471:                    sc = Cipher.getInstance(Cipher.ALG_TRIPLEDES, false);
472:                    sc.init(sBulkKey, Cipher.MODE_DECRYPT, sIV, 0, sIV.length);
473:
474:                    cblk = 8;
475:                    isBlk = 1;
476:
477:                } else {
478:                    cBulkKey = (SecretKey) KeyBuilder.buildKey(
479:                            KeyBuilder.TYPE_ARCFOUR,
480:                            (short) (cKey.length << 3), false);
481:                    cBulkKey.setKey(cKey, (short) 0);
482:                    cc = Cipher.getInstance(Cipher.ALG_ARCFOUR, false);
483:                    cc.init(cBulkKey, Cipher.MODE_ENCRYPT);
484:
485:                    sBulkKey = (SecretKey) KeyBuilder.buildKey(
486:                            KeyBuilder.TYPE_ARCFOUR,
487:                            (short) (sKey.length << 3), false);
488:                    sBulkKey.setKey(sKey, (short) 0);
489:                    sc = Cipher.getInstance(Cipher.ALG_ARCFOUR, false);
490:                    sc.init(sBulkKey, Cipher.MODE_DECRYPT);
491:                    cblk = 1;
492:                    isBlk = 0;
493:
494:                }
495:
496:            }
497:
498:            /**
499:             * Computes the MAC for an SSLCompressed structure.
500:             * <P />
501:             * @param who one of CLIENT or SERVER to indicate whether 
502:             * client-side or server-side MAC secrets and sequence numbers
503:             * ought to be used in the MAC computation
504:             * @param type SSL record type of the SSLCompressed structure
505:             * @param buf byte array containing the SSLCompressed fragment
506:             * @param off starting offset of the fragment in buf
507:             * @param len length of the fragment
508:             * @return a byte array containing the MAC
509:             */
510:            private synchronized byte[] getMAC(byte who, byte type, byte[] buf,
511:                    int off, int len) {
512:                /* 
513:                 * MAC = hash(MAC_secret + PAD2 +
514:                 *            hash(MAC_secret + PAD1 + seq_num + type + len +
515:                 *                 compressed_fragment));
516:                 */
517:                // Compute the inner hash first
518:                byte[] mKey; // MAC_write_secret for use in outer hash
519:                byte[] res = null;
520:                if (who == CLIENT) {
521:                    d.update(cMACKey, 0, cMACKey.length);
522:                    d.update(PAD1, 0, padLen);
523:                    res = Utils.longToBytes(cSeq);
524:                    d.update(res, 0, res.length);
525:
526:                    mKey = cMACKey; // save the right MAC_write_secret
527:                } else {
528:                    d.update(sMACKey, 0, sMACKey.length);
529:                    d.update(PAD1, 0, padLen);
530:                    res = Utils.longToBytes(sSeq);
531:                    d.update(res, 0, res.length);
532:                    mKey = sMACKey; // save the right MAC_write_secret
533:                }
534:
535:                res = new byte[3];
536:                res[0] = type;
537:                res[1] = (byte) (len >>> 8);
538:                res[2] = (byte) (len & 0xff);
539:                d.update(res, 0, res.length);
540:                byte[] mac = new byte[d.getLength()];
541:                d.doFinal(buf, off, len, mac, 0);
542:                // Now, the outer hash
543:                d.update(mKey, 0, mKey.length);
544:                d.update(PAD2, 0, padLen);
545:                byte[] val = new byte[mac.length];
546:                d.doFinal(mac, 0, mac.length, val, 0);
547:                return val;
548:            }
549:
550:            /**
551:             * Converts a byte array containing an SSLPlaintext structure
552:             * to the corresponding SSLCiphertext structure and sends it on
553:             * the underlying OutputStream. The process typically involves 
554:             * the addition of a MAC followed by encryption.
555:             * <P />
556:             * @param ptxt byte array containing SSLPlaintext
557:             * @return the number of bytes written to the OutputStream
558:             */
559:            private byte[] encode(byte[] ptxt) throws IOException {
560:                /*
561:                 * Since we only support NULL compression, SSLPlaintext
562:                 * the same as SSLCompressed.
563:                 */
564:                byte[] fragNMAC = null; // fragment plus MAC
565:
566:                if (d != null) {
567:                    fragNMAC = new byte[ptxt.length - 5 + dLen];
568:                    System.arraycopy(ptxt, 5, fragNMAC, 0, ptxt.length - 5);
569:                    System.arraycopy(getMAC(role, ptxt[0], ptxt, 5,
570:                            (ptxt.length - 5)), 0, fragNMAC, (ptxt.length - 5),
571:                            dLen);
572:                } else {
573:                    fragNMAC = new byte[ptxt.length - 5];
574:                    System.arraycopy(ptxt, 5, fragNMAC, 0, ptxt.length - 5);
575:                }
576:
577:                // ... now we need to encrypt fragNMAC and possibly update IVs
578:                byte[] efragNMAC = null;
579:                if (cc != null) {
580:                    try {
581:                        /*
582:                         * NOTE: For now, we always have a stream cipher so this
583:                         * is commented out.
584:                         */
585:                        // We have a stream cipher
586:                        //Support for new Ciphers                        
587:                        /*efragNMAC = fragNMAC;
588:                        cc.update(fragNMAC, 0, fragNMAC.length, efragNMAC, 0);*/
589:                        if (isBlk == 1) {
590:                            // Compute total padding
591:                            int pLen = cblk - (fragNMAC.length % cblk);
592:                            byte[] tmp = new byte[fragNMAC.length + pLen];
593:                            System.arraycopy(fragNMAC, 0, tmp, 0,
594:                                    fragNMAC.length);
595:                            for (int i = fragNMAC.length; i < tmp.length; i++) {
596:                                tmp[i] = (byte) (pLen - 1);
597:                            }
598:
599:                            efragNMAC = new byte[tmp.length];
600:                            cc.update(tmp, (short) 0, (short) tmp.length,
601:                                    efragNMAC, (short) 0);
602:
603:                        } else {
604:
605:                            /*
606:                             * NOTE: For now, we always have a stream cipher so this
607:                             * is commented out.
608:                             */
609:                            // We have a stream cipher
610:                            efragNMAC = fragNMAC;
611:                            cc.update(fragNMAC, 0, fragNMAC.length, efragNMAC,
612:                                    0);
613:                        }
614:                    } catch (Exception e) {
615:                        throw new IOException("Encode caught " + e);
616:                    }
617:                } else {
618:                    // Cipher algorithm is NULL
619:                    efragNMAC = fragNMAC;
620:                }
621:
622:                /*
623:                 * Utils.logln(Utils.LOG_DEBUG, 
624:                 *             "efragNMAC: " + Utils.hexEncode(efragNMAC));
625:                 */
626:
627:                byte[] rec = new byte[efragNMAC.length + 5];
628:                System.arraycopy(ptxt, 0, rec, 0, 3);
629:                rec[3] = (byte) (efragNMAC.length >>> 8);
630:                rec[4] = (byte) (efragNMAC.length & 0xff);
631:                System.arraycopy(efragNMAC, 0, rec, 5, efragNMAC.length);
632:                // We have encoded one more record, increment seq number
633:                bump(role);
634:
635:                return rec;
636:            }
637:
638:            /**
639:             * Converts a byte array containing an SSLCiphertext structure
640:             * to the corresponding SSLPlaintext structure. The process
641:             * typically involves decryption followed by MAC verification
642:             * and MAC stripping.
643:             *
644:             * @return Length of the decrypted data in the input buffer.
645:             *
646:             * @exception IOException if a problem is encountered during decryption
647:             * or MAC verification
648:             */
649:            private int decode() throws IOException {
650:                int padLen = 0;
651:                int dataLen;
652:
653:                if (sc != null) {
654:                    // Cipher algorithm is not NULL (ctxt needs to be decrypted)
655:
656:                    try {
657:                        /*
658:                         * NOTE: For now, we only have ARCFOUR, a stream cipher
659:                         * so there is no IV or padding that a block cipher has.
660:                         *
661:                         * Otherwise we would have to find the plaintext offset
662:                         * after we decrypt.
663:                         */
664:
665:                        // We have a stream cipher (NOTE: assuming CLIENT role)
666:                        // We can decode in place w/o using additional memory
667:                        //Support for new Ciphers        
668:                        sc.update(inputData, 0, inputData.length, inputData, 0);
669:                        if (isBlk == 1) {
670:                            padLen = (inputData[inputData.length - 1] & 0xff) + 1;
671:                            if ((padLen < 0) || (padLen > cblk)) {
672:                                throw new IOException("bad padding <padLen="
673:                                        + padLen + ">");
674:                            }
675:                        }
676:
677:                    } catch (Exception e) {
678:                        throw new IOException("Decode caught " + e);
679:                    }
680:                }
681:
682:                dataLen = inputData.length - dLen - padLen;
683:
684:                if (d != null) {
685:                    byte[] expMAC = null; // expected MAC
686:                    expMAC = getMAC((byte) (1 - role), inputHeader[0], // the type
687:                            inputData, 0, dataLen);
688:                    if (!Utils.byteMatch(expMAC, 0, inputData,
689:                            (inputData.length - padLen - dLen), dLen)) {
690:                        alert(FATAL, BAD_MAC);
691:                        throw new IOException("Bad MAC");
692:                    }
693:                }
694:
695:                // We have received one more record, bump peer's write sequence number.
696:                bump((byte) (1 - role));
697:
698:                return dataLen;
699:            }
700:
701:            /**
702:             * Reads and returns a record (including the 5-byte header) of 
703:             * the specified type. If the caller asks for application data 
704:             * and a close_notify warning alert is found as the next available
705:             * record, this method returns null to signal the end of the 
706:             * input stream.
707:             *
708:             * @param type desired SSL record type
709:             *
710:             * @exception IOException if an unexpected record type or SSL alert is
711:             * found in the underlying sockets input stream 
712:             */
713:            void rdRec(byte type) throws IOException {
714:                inputData = null;
715:                plainTextOffset = 0;
716:                plainTextLength = -1;
717:
718:                //long startTime = System.currentTimeMillis();
719:                rdRec();
720:                //System.out.println("Time taken to read record -> " + (System.currentTimeMillis() - startTime));
721:
722:                if ((inputData == null) || (inputHeader[0] == type)) {
723:                    // success
724:                    return;
725:                }
726:
727:                plainTextLength = -1;
728:
729:                switch (inputHeader[0]) {
730:                case CCS:
731:                    // Can change_cipher_spec can be passed to handshake clients?
732:                    // if (type == HNDSHK) return r; // fall through otherwise
733:                case HNDSHK:
734:                case APP:
735:                default:
736:                    alert(FATAL, UNEXP_MSG);
737:                    throw new IOException("Unexpected SSL record, type: "
738:                            + inputHeader[0]);
739:
740:                case ALRT:
741:                    // An Alert record needs to be atleast 2 bytes of data
742:                    if (inputData.length < 2) {
743:                        throw new IOException("Bad alert length");
744:                    }
745:
746:                    if ((inputData[0] == WARNING)
747:                            && (inputData[1] == CLOSE_NTFY) && (type == APP)) {
748:                        /*
749:                         * We got a close_notify warning
750:                         * We do not send a close notify here, but in
751:                         * closing the stream we perform
752:                         *    alert(WARNING, CLOSE_NTFY).
753:                         */
754:                        return; // signal end of InputStream
755:                    }
756:
757:                    if ((inputData[0] < WARNING) || (inputData[0] > FATAL)) {
758:                        throw new IOException("Bad alert level");
759:                    }
760:
761:                    throw new IOException("Alert (" + inputData[0] + ","
762:                            + inputData[1] + ")");
763:                }
764:            }
765:
766:            /**
767:             * Returns the next record read from the record layer (the 5-byte
768:             * SSL record header is included).
769:             *
770:             * @exception IOException if an I/O error occurs
771:             */
772:            private void rdRec() throws IOException {
773:                int hlen;
774:                int b;
775:                int rlen;
776:                int cnt;
777:
778:                b = in.read(inputHeader, 0, 1);
779:                if (b == -1) {
780:                    /*
781:                     * Peer closed SSL connection without close_notify
782:                     */
783:                    return;
784:                }
785:                hlen = inputHeader.length;
786:                cnt = 1;
787:
788:                while (cnt < hlen) {
789:                    //            long startTime = System.currentTimeMillis();
790:                    b = in.read(inputHeader, cnt, hlen - cnt);
791:                    //            System.out.println("Inside while. Time taken -> " + (System.currentTimeMillis() - startTime));
792:                    if (b == -1) {
793:                        throw new IOException(
794:                                "SSL connection ended abnormally "
795:                                        + "while reading record header");
796:                    }
797:                    cnt += b;
798:                }
799:
800:                /*        System.out.println("\nHeader sent from JSS Server: ");
801:                 for(int i=0; i < 5; ++i) {
802:                 System.out.println("Header[" + i + "] -> " + inputHeader[i]);
803:                 }
804:                 */
805:                // Check record type and version
806:                if ((inputHeader[0] < CCS) || (inputHeader[0] > APP)
807:                        || (inputHeader[1] != (byte) (ver >>> 4))
808:                        || (inputHeader[2] != (byte) (ver & 0x0f))) {
809:                    alert(FATAL, UNEXP_MSG);
810:                    throw new IOException("Bad record type (" + inputHeader[0]
811:                            + ") or version (" + inputHeader[1] + "."
812:                            + inputHeader[2] + ")");
813:                }
814:
815:                rlen = ((inputHeader[3] & 0xff) << 8) + (inputHeader[4] & 0xff);
816:                inputData = new byte[rlen];
817:                cnt = 0;
818:                b = 0;
819:                while (cnt < rlen) {
820:                    //long startTime = System.currentTimeMillis();
821:                    b = in.read(inputData, cnt, rlen - cnt);
822:                    //System.out.println("Time taken to read data -> " + (System.currentTimeMillis() - startTime));
823:                    if (b == -1) {
824:                        throw new IOException(
825:                                "SSL connection ended abnormally "
826:                                        + "after reading record byte "
827:                                        + (cnt + inputHeader.length));
828:                    }
829:
830:                    cnt += b;
831:                }
832:
833:                if (rActive == 1) {
834:                    //long startTime = System.currentTimeMillis();
835:                    plainTextLength = decode();
836:                    //  System.out.println("Time taken to decode data -> " + (System.currentTimeMillis() - startTime));
837:                } else {
838:                    plainTextLength = rlen;
839:                }
840:
841:                if (inputHeader[0] == CCS) {
842:                    rActive = 1;
843:                }
844:            }
845:
846:            /**
847:             * Writes an SSL record to the underlying socket's output stream.
848:             * <P />
849:             * @param type record type (one of CCS, ALRT, HNDSHK or APP)
850:             * @param buf byte array containing the record body (i.e. everything
851:             * but the 5-byte header)
852:             * @param off starting offset of the record body inside buf
853:             * @param len length of the record body, the maximum is 2^14 +2048 as
854:             *            defined by RFC 2246
855:             * @exception IOException if an I/O error occurs.
856:             */
857:            /*
858:             * REVISIT: We currently do not handle fragmentation and only 
859:             * increment sequence numbers when encoding/decoding are 
860:             * turned on. Is it necessary to maintain these counts for
861:             * handshake messages as well???
862:             */
863:            void wrRec(byte type, byte[] buf, int off, int len)
864:                    throws IOException {
865:                // Create a new byte array with room for the header
866:                byte[] rec = new byte[len + 5];
867:                // Fill the record header with type, version and length
868:                rec[0] = type;
869:                rec[1] = (byte) (ver >>> 4);
870:                rec[2] = (byte) (ver & 0x0f);
871:                rec[3] = (byte) (len >>> 8);
872:                rec[4] = (byte) (len & 0xff);
873:
874:                /*        System.out.println("\nHeader sent from KSSL client: ");
875:                 for(int i=0; i < 5; ++i) {
876:                 System.out.println("Header[" + i + "] -> " + rec[i]);
877:                 }
878:                 */
879:                // Fill the rest of the record
880:                System.arraycopy(buf, off, rec, 5, len);
881:                if (wActive == 1) {
882:                    out.write(encode(rec));
883:                } else {
884:                    out.write(rec);
885:                }
886:                if (type == CCS)
887:                    wActive = 1;
888:                out.flush();
889:            }
890:
891:            /**
892:             * Sends an alert message of the specified level and type to the SSL peer.
893:             * <p />
894:             * @param level one of WARNING or FATAL)
895:             * @param type one of CLOSE_NTFY, UNEXP_MSG, BAD_MAC, DECOMP_FAIL,
896:             *             HNDSHK_FAIL, NO_CERT, BAD_CERT, UNSUP_CERT, CERT_REVKD,
897:             *             CERT_EXPRD, CERT_UNKWN, BAD_PARAM
898:             */
899:            public void alert(byte level, byte type) {
900:                byte[] tmp = new byte[2];
901:                tmp[0] = level;
902:                tmp[1] = type;
903:
904:                try {
905:                    wrRec(ALRT, tmp, 0, 2);
906:                } catch (IOException e) {
907:                    // ignore, we do not want to step on the real error
908:                }
909:            }
910:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.