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