1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44:
45: import ;
46:
47: import ;
48: import ;
49:
50: import ;
51: import ;
52: import ;
53: import ;
54:
55: public class OutputSecurityParameters
56: {
57: private static final SystemLogger logger = SystemLogger.SYSTEM;
58: private final Cipher cipher;
59: private final Mac mac;
60: private final Deflater deflater;
61: private final SessionImpl session;
62: private final CipherSuite suite;
63: private long sequence;
64:
65: public OutputSecurityParameters (final Cipher cipher, final Mac mac,
66: final Deflater deflater, SessionImpl session,
67: CipherSuite suite)
68: {
69: this.cipher = cipher;
70: this.mac = mac;
71: this.deflater = deflater;
72: this.session = session;
73: this.suite = suite;
74: sequence = 0;
75: }
76:
77:
84: public int[] encrypt (final ByteBuffer[] input, int offset, int length,
85: final ContentType contentType, final ByteBuffer output)
86: throws DataFormatException, IllegalBlockSizeException, ShortBufferException
87: {
88: if (offset < 0 || offset >= input.length
89: || length <= 0 || offset + length > input.length)
90: throw new IndexOutOfBoundsException();
91:
92: if (Debug.DEBUG)
93: for (int i = offset; i < offset+length; i++)
94: logger.logv(Component.SSL_RECORD_LAYER, "encrypting record [{0}]: {1}",
95: i-offset, input[i]);
96:
97: int maclen = 0;
98: if (mac != null)
99: maclen = session.isTruncatedMac() ? 10 : mac.getMacLength ();
100:
101: int ivlen = 0;
102: byte[] iv = null;
103: if (session.version.compareTo(ProtocolVersion.TLS_1_1) >= 0
104: && !suite.isStreamCipher())
105: {
106: ivlen = cipher.getBlockSize();
107: iv = new byte[ivlen];
108: session.random().nextBytes(iv);
109: }
110:
111: int padaddlen = 0;
112: if (!suite.isStreamCipher()
113: && session.version.compareTo(ProtocolVersion.TLS_1) >= 0)
114: {
115: padaddlen = (session.random().nextInt(255 / cipher.getBlockSize())
116: * cipher.getBlockSize());
117: }
118:
119: int fragmentLength = 0;
120: ByteBuffer[] fragments = null;
121:
122: if (deflater != null)
123: {
124: ByteBufferOutputStream deflated = new ByteBufferOutputStream();
125:
126: byte[] inbuf = new byte[1024];
127: byte[] outbuf = new byte[1024];
128: int written = 0;
129:
130:
131:
132:
133: int limit = output.remaining() - (maclen + ivlen + padaddlen) - 1024;
134:
135: for (int i = offset; i < length && written < limit; i++)
136: {
137: ByteBuffer in = input[i];
138: while (in.hasRemaining() && written < limit)
139: {
140: int l = Math.min(in.remaining(), inbuf.length);
141: l = Math.min(limit - written, l);
142: in.get(inbuf, 0, l);
143: deflater.setInput(inbuf, 0, l);
144: l = deflater.deflate(outbuf);
145: deflated.write(outbuf, 0, l);
146: written += l;
147: }
148: }
149: deflater.finish();
150: while (!deflater.finished())
151: {
152: int l = deflater.deflate(outbuf);
153: deflated.write(outbuf, 0, l);
154: written += l;
155: }
156: fragments = new ByteBuffer[] { deflated.buffer() };
157: fragmentLength = ((int) deflater.getBytesWritten()) + maclen + ivlen;
158: deflater.reset();
159: offset = 0;
160: length = 1;
161: }
162: else
163: {
164: int limit = output.remaining() - (maclen + ivlen + padaddlen);
165: fragments = input;
166: for (int i = offset; i < length && fragmentLength < limit; i++)
167: {
168: int l = Math.min(limit - fragmentLength, fragments[i].remaining());
169: fragmentLength += l;
170: }
171: fragmentLength += maclen + ivlen;
172: }
173:
174:
175: int padlen = 0;
176: byte[] pad = null;
177: if (!suite.isStreamCipher())
178: {
179: int bs = cipher.getBlockSize();
180: padlen = bs - (fragmentLength % bs);
181: if (Debug.DEBUG)
182: logger.logv(Component.SSL_RECORD_LAYER,
183: "framentLen:{0} padlen:{1} blocksize:{2}",
184: fragmentLength, padlen, bs);
185: if (session.version.compareTo(ProtocolVersion.TLS_1) >= 0)
186: {
187:
188:
189:
190: padlen += padaddlen;
191: while (padlen > 255)
192: padlen -= bs;
193: pad = new byte[padlen];
194: for (int i = 0; i < padlen; i++)
195: pad[i] = (byte) (padlen - 1);
196: }
197: else
198: {
199:
200:
201: pad = new byte[padlen];
202: session.random().nextBytes(pad);
203: pad[padlen - 1] = (byte) (padlen - 1);
204: }
205: fragmentLength += pad.length;
206: }
207:
208:
209: byte[] macValue = null;
210: if (mac != null)
211: {
212: mac.update((byte) (sequence >>> 56));
213: mac.update((byte) (sequence >>> 48));
214: mac.update((byte) (sequence >>> 40));
215: mac.update((byte) (sequence >>> 32));
216: mac.update((byte) (sequence >>> 24));
217: mac.update((byte) (sequence >>> 16));
218: mac.update((byte) (sequence >>> 8));
219: mac.update((byte) sequence);
220: mac.update((byte) contentType.getValue());
221: if (session.version != ProtocolVersion.SSL_3)
222: {
223: mac.update((byte) session.version.major ());
224: mac.update((byte) session.version.minor ());
225: }
226: int toWrite = fragmentLength - maclen - ivlen - padlen;
227: mac.update((byte) (toWrite >>> 8));
228: mac.update((byte) toWrite);
229: int written = 0;
230: for (int i = offset; i < length && written < toWrite; i++)
231: {
232: ByteBuffer fragment = fragments[i].duplicate();
233: int l = Math.min(fragment.remaining(), toWrite - written);
234: fragment.limit(fragment.position() + l);
235: mac.update(fragment);
236: }
237: macValue = mac.doFinal();
238: }
239:
240: Record outrecord = new Record(output);
241: outrecord.setContentType(contentType);
242: outrecord.setVersion(session.version);
243: outrecord.setLength(fragmentLength);
244:
245: int consumed = 0;
246: ByteBuffer outfragment = outrecord.fragment();
247:
248: if (cipher != null)
249: {
250: if (iv != null)
251: cipher.update(ByteBuffer.wrap(iv), outfragment);
252: int toWrite = fragmentLength - maclen - ivlen - padlen;
253: for (int i = offset; i < offset + length && consumed < toWrite; i++)
254: {
255: ByteBuffer fragment = fragments[i].slice();
256: int l = Math.min(fragment.remaining(), toWrite - consumed);
257: fragment.limit(fragment.position() + l);
258: cipher.update(fragment, outfragment);
259: fragments[i].position(fragments[i].position() + l);
260: consumed += l;
261: }
262: if (macValue != null)
263: cipher.update(ByteBuffer.wrap(macValue), outfragment);
264: if (pad != null)
265: cipher.update(ByteBuffer.wrap(pad), outfragment);
266: }
267: else
268: {
269:
270: int toWrite = fragmentLength - maclen;
271: for (int i = offset; i < offset + length && consumed < toWrite; i++)
272: {
273: ByteBuffer fragment = fragments[i];
274: int l = Math.min(fragment.remaining(), toWrite - consumed);
275: fragment.limit(fragment.position() + l);
276: outfragment.put(fragment);
277: consumed += l;
278: }
279: if (macValue != null)
280: outfragment.put(macValue);
281: }
282:
283:
284: output.position(output.position() + outrecord.length() + 5);
285: sequence++;
286:
287: return new int[] { consumed, fragmentLength + 5 };
288: }
289:
290: CipherSuite suite()
291: {
292: return suite;
293: }