1/*
2 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.security.ssl;
27
28import java.io.*;
29import java.nio.*;
30import java.util.Arrays;
31
32import javax.net.ssl.SSLException;
33import sun.security.util.HexDumpEncoder;
34
35
36/**
37 * {@code OutputRecord} takes care of the management of SSL/TLS/DTLS output
38 * records, including buffering, encryption, handshake messages marshal, etc.
39 *
40 * @author David Brownell
41 */
42abstract class OutputRecord extends ByteArrayOutputStream
43            implements Record, Closeable {
44
45    /* Class and subclass dynamic debugging support */
46    static final Debug          debug = Debug.getInstance("ssl");
47
48    Authenticator               writeAuthenticator;
49    CipherBox                   writeCipher;
50
51    HandshakeHash               handshakeHash;
52    boolean                     firstMessage;
53
54    // current protocol version, sent as record version
55    ProtocolVersion             protocolVersion;
56
57    // version for the ClientHello message. Only relevant if this is a
58    // client handshake record. If set to ProtocolVersion.SSL20Hello,
59    // the V3 client hello is converted to V2 format.
60    ProtocolVersion             helloVersion;
61
62    // Is it the first application record to write?
63    boolean                     isFirstAppOutputRecord = true;
64
65    // packet size
66    int                         packetSize;
67
68    // fragment size
69    int                         fragmentSize;
70
71    // closed or not?
72    boolean                     isClosed;
73
74    /*
75     * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
76     * This is taken from the SSL V3 specification, Appendix E.
77     */
78    private static int[] V3toV2CipherMap1 =
79        {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
80    private static int[] V3toV2CipherMap3 =
81        {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
82
83    OutputRecord() {
84        this.writeCipher = CipherBox.NULL;
85        this.firstMessage = true;
86        this.fragmentSize = Record.maxDataSize;
87
88        // Please set packetSize and protocolVersion in the implementation.
89    }
90
91    void setVersion(ProtocolVersion protocolVersion) {
92        this.protocolVersion = protocolVersion;
93    }
94
95    /*
96     * Updates helloVersion of this record.
97     */
98    synchronized void setHelloVersion(ProtocolVersion helloVersion) {
99        this.helloVersion = helloVersion;
100    }
101
102    /*
103     * For handshaking, we need to be able to hash every byte above the
104     * record marking layer.  This is where we're guaranteed to see those
105     * bytes, so this is where we can hash them.
106     */
107    void setHandshakeHash(HandshakeHash handshakeHash) {
108        this.handshakeHash = handshakeHash;
109    }
110
111    /*
112     * Return true iff the record is empty -- to avoid doing the work
113     * of sending empty records over the network.
114     */
115    boolean isEmpty() {
116        return false;
117    }
118
119    boolean seqNumIsHuge() {
120        return (writeAuthenticator != null) &&
121                        writeAuthenticator.seqNumIsHuge();
122    }
123
124    // SSLEngine and SSLSocket
125    abstract void encodeAlert(byte level, byte description) throws IOException;
126
127    // SSLEngine and SSLSocket
128    abstract void encodeHandshake(byte[] buffer,
129            int offset, int length) throws IOException;
130
131    // SSLEngine and SSLSocket
132    abstract void encodeChangeCipherSpec() throws IOException;
133
134    // apply to SSLEngine only
135    Ciphertext encode(ByteBuffer[] sources, int offset, int length,
136            ByteBuffer destination) throws IOException {
137        throw new UnsupportedOperationException();
138    }
139
140    // apply to SSLEngine only
141    void encodeV2NoCipher() throws IOException {
142        throw new UnsupportedOperationException();
143    }
144
145    // apply to SSLSocket only
146    void deliver(byte[] source, int offset, int length) throws IOException {
147        throw new UnsupportedOperationException();
148    }
149
150    // apply to SSLSocket only
151    void setDeliverStream(OutputStream outputStream) {
152        throw new UnsupportedOperationException();
153    }
154
155    // apply to SSLEngine only
156    Ciphertext acquireCiphertext(ByteBuffer destination) throws IOException {
157        throw new UnsupportedOperationException();
158    }
159
160    void changeWriteCiphers(Authenticator writeAuthenticator,
161            CipherBox writeCipher) throws IOException {
162
163        encodeChangeCipherSpec();
164
165        /*
166         * Dispose of any intermediate state in the underlying cipher.
167         * For PKCS11 ciphers, this will release any attached sessions,
168         * and thus make finalization faster.
169         *
170         * Since MAC's doFinal() is called for every SSL/TLS packet, it's
171         * not necessary to do the same with MAC's.
172         */
173        writeCipher.dispose();
174
175        this.writeAuthenticator = writeAuthenticator;
176        this.writeCipher = writeCipher;
177        this.isFirstAppOutputRecord = true;
178    }
179
180    void changePacketSize(int packetSize) {
181        this.packetSize = packetSize;
182    }
183
184    void changeFragmentSize(int fragmentSize) {
185        this.fragmentSize = fragmentSize;
186    }
187
188    int getMaxPacketSize() {
189        return packetSize;
190    }
191
192    // apply to DTLS SSLEngine
193    void initHandshaker() {
194        // blank
195    }
196
197    // apply to DTLS SSLEngine
198    void launchRetransmission() {
199        // blank
200    }
201
202    @Override
203    public synchronized void close() throws IOException {
204        if (!isClosed) {
205            isClosed = true;
206            writeCipher.dispose();
207        }
208    }
209
210    //
211    // shared helpers
212    //
213
214    // Encrypt a fragment and wrap up a record.
215    //
216    // To be consistent with the spec of SSLEngine.wrap() methods, the
217    // destination ByteBuffer's position is updated to reflect the amount
218    // of data produced.  The limit remains the same.
219    static long encrypt(Authenticator authenticator,
220            CipherBox encCipher, byte contentType, ByteBuffer destination,
221            int headerOffset, int dstLim, int headerSize,
222            ProtocolVersion protocolVersion, boolean isDTLS) {
223
224        byte[] sequenceNumber = null;
225        int dstContent = destination.position();
226
227        // Acquire the current sequence number before using.
228        if (isDTLS) {
229            sequenceNumber = authenticator.sequenceNumber();
230        }
231
232        // The sequence number may be shared for different purpose.
233        boolean sharedSequenceNumber = false;
234
235        // "flip" but skip over header again, add MAC & encrypt
236        if (authenticator instanceof MAC) {
237            MAC signer = (MAC)authenticator;
238            if (signer.MAClen() != 0) {
239                byte[] hash = signer.compute(contentType, destination, false);
240
241                /*
242                 * position was advanced to limit in MAC compute above.
243                 *
244                 * Mark next area as writable (above layers should have
245                 * established that we have plenty of room), then write
246                 * out the hash.
247                 */
248                destination.limit(destination.limit() + hash.length);
249                destination.put(hash);
250
251                // reset the position and limit
252                destination.limit(destination.position());
253                destination.position(dstContent);
254
255                // The signer has used and increased the sequence number.
256                if (isDTLS) {
257                    sharedSequenceNumber = true;
258                }
259            }
260        }
261
262        if (!encCipher.isNullCipher()) {
263            if (protocolVersion.useTLS11PlusSpec() &&
264                    (encCipher.isCBCMode() || encCipher.isAEADMode())) {
265                byte[] nonce = encCipher.createExplicitNonce(
266                        authenticator, contentType, destination.remaining());
267                destination.position(headerOffset + headerSize);
268                destination.put(nonce);
269            }
270            if (!encCipher.isAEADMode()) {
271                // The explicit IV in TLS 1.1 and later can be encrypted.
272                destination.position(headerOffset + headerSize);
273            }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
274
275            // Encrypt may pad, so again the limit may be changed.
276            encCipher.encrypt(destination, dstLim);
277
278            // The cipher has used and increased the sequence number.
279            if (isDTLS && encCipher.isAEADMode()) {
280                sharedSequenceNumber = true;
281            }
282        } else {
283            destination.position(destination.limit());
284        }
285
286        // Finish out the record header.
287        int fragLen = destination.limit() - headerOffset - headerSize;
288
289        destination.put(headerOffset, contentType);         // content type
290        destination.put(headerOffset + 1, protocolVersion.major);
291        destination.put(headerOffset + 2, protocolVersion.minor);
292        if (!isDTLS) {
293            // fragment length
294            destination.put(headerOffset + 3, (byte)(fragLen >> 8));
295            destination.put(headerOffset + 4, (byte)fragLen);
296        } else {
297            // epoch and sequence_number
298            destination.put(headerOffset + 3, sequenceNumber[0]);
299            destination.put(headerOffset + 4, sequenceNumber[1]);
300            destination.put(headerOffset + 5, sequenceNumber[2]);
301            destination.put(headerOffset + 6, sequenceNumber[3]);
302            destination.put(headerOffset + 7, sequenceNumber[4]);
303            destination.put(headerOffset + 8, sequenceNumber[5]);
304            destination.put(headerOffset + 9, sequenceNumber[6]);
305            destination.put(headerOffset + 10, sequenceNumber[7]);
306
307            // fragment length
308            destination.put(headerOffset + 11, (byte)(fragLen >> 8));
309            destination.put(headerOffset + 12, (byte)fragLen);
310
311            // Increase the sequence number for next use if it is not shared.
312            if (!sharedSequenceNumber) {
313                authenticator.increaseSequenceNumber();
314            }
315        }
316
317        // Update destination position to reflect the amount of data produced.
318        destination.position(destination.limit());
319
320        return Authenticator.toLong(sequenceNumber);
321    }
322
323    // Encrypt a fragment and wrap up a record.
324    //
325    // Uses the internal expandable buf variable and the current
326    // protocolVersion variable.
327    void encrypt(Authenticator authenticator,
328            CipherBox encCipher, byte contentType, int headerSize) {
329
330        int position = headerSize + writeCipher.getExplicitNonceSize();
331
332        // "flip" but skip over header again, add MAC & encrypt
333        int macLen = 0;
334        if (authenticator instanceof MAC) {
335            MAC signer = (MAC)authenticator;
336            macLen = signer.MAClen();
337            if (macLen != 0) {
338                byte[] hash = signer.compute(contentType,
339                        buf, position, (count - position), false);
340
341                write(hash, 0, hash.length);
342            }
343        }
344
345        if (!encCipher.isNullCipher()) {
346            // Requires explicit IV/nonce for CBC/AEAD cipher suites for
347            // TLS 1.1 or later.
348            if (protocolVersion.useTLS11PlusSpec() &&
349                    (encCipher.isCBCMode() || encCipher.isAEADMode())) {
350
351                byte[] nonce = encCipher.createExplicitNonce(
352                        authenticator, contentType, (count - position));
353                int noncePos = position - nonce.length;
354                System.arraycopy(nonce, 0, buf, noncePos, nonce.length);
355            }
356
357            if (!encCipher.isAEADMode()) {
358                // The explicit IV in TLS 1.1 and later can be encrypted.
359                position = headerSize;
360            }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
361
362            // increase buf capacity if necessary
363            int fragSize = count - position;
364            int packetSize =
365                    encCipher.calculatePacketSize(fragSize, macLen, headerSize);
366            if (packetSize > (buf.length - position)) {
367                byte[] newBuf = new byte[position + packetSize];
368                System.arraycopy(buf, 0, newBuf, 0, count);
369                buf = newBuf;
370            }
371
372            // Encrypt may pad, so again the count may be changed.
373            count = position +
374                    encCipher.encrypt(buf, position, (count - position));
375        }
376
377        // Fill out the header, write it and the message.
378        int fragLen = count - headerSize;
379        buf[0] = contentType;
380        buf[1] = protocolVersion.major;
381        buf[2] = protocolVersion.minor;
382        buf[3] = (byte)((fragLen >> 8) & 0xFF);
383        buf[4] = (byte)(fragLen & 0xFF);
384    }
385
386    static ByteBuffer encodeV2ClientHello(
387            byte[] fragment, int offset, int length) throws IOException {
388
389        int v3SessIdLenOffset = offset + 34;      //  2: client_version
390                                                  // 32: random
391
392        int v3SessIdLen = fragment[v3SessIdLenOffset];
393        int v3CSLenOffset = v3SessIdLenOffset + 1 + v3SessIdLen;
394        int v3CSLen = ((fragment[v3CSLenOffset] & 0xff) << 8) +
395                       (fragment[v3CSLenOffset + 1] & 0xff);
396        int cipherSpecs = v3CSLen / 2;        // 2: cipher spec size
397
398        // Estimate the max V2ClientHello message length
399        //
400        // 11: header size
401        // (cipherSpecs * 6): cipher_specs
402        //    6: one cipher suite may need 6 bytes, see V3toV2CipherSuite.
403        // 3: placeholder for the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
404        //    signaling cipher suite
405        // 32: challenge size
406        int v2MaxMsgLen = 11 + (cipherSpecs * 6) + 3 + 32;
407
408        // Create a ByteBuffer backed by an accessible byte array.
409        byte[] dstBytes = new byte[v2MaxMsgLen];
410        ByteBuffer dstBuf = ByteBuffer.wrap(dstBytes);
411
412        /*
413         * Copy over the cipher specs. We don't care about actually
414         * translating them for use with an actual V2 server since
415         * we only talk V3.  Therefore, just copy over the V3 cipher
416         * spec values with a leading 0.
417         */
418        int v3CSOffset = v3CSLenOffset + 2;   // skip length field
419        int v2CSLen = 0;
420
421        dstBuf.position(11);
422        boolean containsRenegoInfoSCSV = false;
423        for (int i = 0; i < cipherSpecs; i++) {
424            byte byte1, byte2;
425
426            byte1 = fragment[v3CSOffset++];
427            byte2 = fragment[v3CSOffset++];
428            v2CSLen += V3toV2CipherSuite(dstBuf, byte1, byte2);
429            if (!containsRenegoInfoSCSV &&
430                    byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
431                containsRenegoInfoSCSV = true;
432            }
433        }
434
435        if (!containsRenegoInfoSCSV) {
436            v2CSLen += V3toV2CipherSuite(dstBuf, (byte)0x00, (byte)0xFF);
437        }
438
439        /*
440         * Copy in the nonce.
441         */
442        dstBuf.put(fragment, (offset + 2), 32);
443
444        /*
445         * Build the first part of the V3 record header from the V2 one
446         * that's now buffered up.  (Lengths are fixed up later).
447         */
448        int msgLen = dstBuf.position() - 2;   // Exclude the legth field itself
449        dstBuf.position(0);
450        dstBuf.put((byte)(0x80 | ((msgLen >>> 8) & 0xFF)));  // pos: 0
451        dstBuf.put((byte)(msgLen & 0xFF));                   // pos: 1
452        dstBuf.put(HandshakeMessage.ht_client_hello);        // pos: 2
453        dstBuf.put(fragment[offset]);         // major version, pos: 3
454        dstBuf.put(fragment[offset + 1]);     // minor version, pos: 4
455        dstBuf.put((byte)(v2CSLen >>> 8));                   // pos: 5
456        dstBuf.put((byte)(v2CSLen & 0xFF));                  // pos: 6
457        dstBuf.put((byte)0x00);           // session_id_length, pos: 7
458        dstBuf.put((byte)0x00);                              // pos: 8
459        dstBuf.put((byte)0x00);           // challenge_length,  pos: 9
460        dstBuf.put((byte)32);                                // pos: 10
461
462        dstBuf.position(0);
463        dstBuf.limit(msgLen + 2);
464
465        return dstBuf;
466    }
467
468    private static int V3toV2CipherSuite(ByteBuffer dstBuf,
469            byte byte1, byte byte2) {
470        dstBuf.put((byte)0);
471        dstBuf.put(byte1);
472        dstBuf.put(byte2);
473
474        if (((byte2 & 0xff) > 0xA) || (V3toV2CipherMap1[byte2] == -1)) {
475            return 3;
476        }
477
478        dstBuf.put((byte)V3toV2CipherMap1[byte2]);
479        dstBuf.put((byte)0);
480        dstBuf.put((byte)V3toV2CipherMap3[byte2]);
481
482        return 6;
483    }
484}
485