1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48:
49: import ;
50: import ;
51: import ;
52:
53: import ;
54: import ;
55: import ;
56: import ;
57:
58: import ;
59:
60: public class InputSecurityParameters
61: {
62: private static final SystemLogger logger = SystemLogger.SYSTEM;
63: private final Cipher cipher;
64: private final Mac mac;
65: private final Inflater inflater;
66: private SessionImpl session;
67: private final CipherSuite suite;
68: private long sequence;
69:
70: public InputSecurityParameters (final Cipher cipher, final Mac mac,
71: final Inflater inflater,
72: final SessionImpl session,
73: final CipherSuite suite)
74: {
75: this.cipher = cipher;
76: this.mac = mac;
77: this.inflater = inflater;
78: this.session = session;
79: this.suite = suite;
80: sequence = 0;
81: }
82:
83:
99: public int decrypt(Record record, ByteBuffer[] output, int offset, int length)
100: throws DataFormatException, IllegalBlockSizeException,
101: MacException, SSLException, ShortBufferException
102: {
103: return decrypt(record, output, offset, length, null);
104: }
105:
106:
119: public int decrypt(Record record, ByteBufferOutputStream outputStream)
120: throws DataFormatException, IllegalBlockSizeException,
121: MacException, SSLException, ShortBufferException
122: {
123: return decrypt(record, null, 0, 0, outputStream);
124: }
125:
126: private int decrypt(Record record, ByteBuffer[] output, int offset, int length,
127: ByteBufferOutputStream outputStream)
128: throws DataFormatException, IllegalBlockSizeException,
129: MacException, SSLException, ShortBufferException
130: {
131: boolean badPadding = false;
132: ByteBuffer fragment;
133: if (cipher != null)
134: {
135: ByteBuffer input = record.fragment();
136: fragment = ByteBuffer.allocate(input.remaining());
137: cipher.update(input, fragment);
138: }
139: else
140: fragment = record.fragment();
141:
142: if (Debug.DEBUG_DECRYPTION)
143: logger.logv(Component.SSL_RECORD_LAYER, "decrypted fragment:\n{0}",
144: Util.hexDump((ByteBuffer) fragment.duplicate().position(0), " >> "));
145:
146: int fragmentLength = record.length();
147: int maclen = 0;
148: if (mac != null)
149: maclen = mac.getMacLength();
150: fragmentLength -= maclen;
151:
152: int padlen = 0;
153: int padRemoveLen = 0;
154: if (!suite.isStreamCipher ())
155: {
156: padlen = fragment.get(record.length() - 1) & 0xFF;
157: padRemoveLen = padlen + 1;
158: if (Debug.DEBUG)
159: logger.logv(Component.SSL_RECORD_LAYER, "padlen:{0}", padlen);
160:
161: if (record.version() == ProtocolVersion.SSL_3)
162: {
163:
164:
165: if (padlen > cipher.getBlockSize ())
166: badPadding = true;
167: }
168: else if (record.version().compareTo(ProtocolVersion.TLS_1) >= 0)
169: {
170:
171:
172: byte[] pad = new byte[padlen];
173: ((ByteBuffer) fragment.duplicate().position(record.length() - padlen - 1)).get(pad);
174: for (int i = 0; i < pad.length; i++)
175: if ((pad[i] & 0xFF) != padlen)
176: badPadding = true;
177: if (Debug.DEBUG)
178: logger.logv(Component.SSL_RECORD_LAYER, "TLSv1.x padding\n{0}",
179: new ByteArray(pad));
180: }
181:
182: if (Debug.DEBUG)
183: logger.logv(Component.SSL_RECORD_LAYER, "padding bad? {0}",
184: badPadding);
185: if (!badPadding)
186: fragmentLength = fragmentLength - padRemoveLen;
187: }
188:
189: int ivlen = 0;
190: if (session.version.compareTo(ProtocolVersion.TLS_1_1) >= 0
191: && !suite.isStreamCipher())
192: ivlen = cipher.getBlockSize();
193:
194:
195: if (mac != null)
196: {
197: mac.update((byte) (sequence >>> 56));
198: mac.update((byte) (sequence >>> 48));
199: mac.update((byte) (sequence >>> 40));
200: mac.update((byte) (sequence >>> 32));
201: mac.update((byte) (sequence >>> 24));
202: mac.update((byte) (sequence >>> 16));
203: mac.update((byte) (sequence >>> 8));
204: mac.update((byte) sequence);
205: mac.update((byte) record.getContentType().getValue());
206: ProtocolVersion version = record.version();
207: if (version != ProtocolVersion.SSL_3)
208: {
209: mac.update((byte) version.major());
210: mac.update((byte) version.minor());
211: }
212: mac.update((byte) ((fragmentLength - ivlen) >>> 8));
213: mac.update((byte) (fragmentLength - ivlen));
214: ByteBuffer content =
215: (ByteBuffer) fragment.duplicate().position(ivlen).limit(fragmentLength);
216: mac.update(content);
217: byte[] mac1 = mac.doFinal ();
218: byte[] mac2 = new byte[maclen];
219: mac.reset();
220: ((ByteBuffer) fragment.duplicate().position(fragmentLength)).get(mac2);
221: if (Debug.DEBUG)
222: logger.logv(Component.SSL_RECORD_LAYER, "mac1:{0} mac2:{1}",
223: Util.toHexString(mac1, ':'), Util.toHexString(mac2, ':'));
224: if (!Arrays.equals (mac1, mac2))
225: badPadding = true;
226: }
227:
228:
229:
230: if (badPadding)
231: throw new MacException ();
232:
233:
234: int produced = 0;
235: if (inflater != null)
236: {
237: ByteBufferOutputStream out = new ByteBufferOutputStream(fragmentLength);
238: byte[] inbuffer = new byte[1024];
239: byte[] outbuffer = new byte[1024];
240: boolean done = false;
241: if (record.version().compareTo(ProtocolVersion.TLS_1_1) >= 0
242: && !suite.isStreamCipher())
243: fragment.position (cipher.getBlockSize());
244: else
245: fragment.position(0);
246: fragment.limit(fragmentLength);
247:
248: while (!done)
249: {
250: int l;
251: if (inflater.needsInput())
252: {
253: l = Math.min(inbuffer.length, fragment.remaining());
254: fragment.get(inbuffer, 0, l);
255: inflater.setInput(inbuffer);
256: }
257:
258: l = inflater.inflate(outbuffer);
259: out.write(outbuffer, 0, l);
260: done = !fragment.hasRemaining() && inflater.finished();
261: }
262:
263: ByteBuffer outbuf = out.buffer();
264: if (outputStream != null)
265: {
266: byte[] buf = new byte[1024];
267: while (outbuf.hasRemaining())
268: {
269: int l = Math.min(outbuf.remaining(), buf.length);
270: outbuf.get(buf, 0, l);
271: outputStream.write(buf, 0, l);
272: produced += l;
273: }
274: }
275: else
276: {
277: int i = offset;
278: while (outbuf.hasRemaining() && i < offset + length)
279: {
280: int l = Math.min(output[i].remaining(), outbuf.remaining());
281: ByteBuffer b = (ByteBuffer)
282: outbuf.duplicate().limit(outbuf.position() + l);
283: output[i++].put(b);
284: outbuf.position(outbuf.position() + l);
285: produced += l;
286: }
287: if (outbuf.hasRemaining())
288: throw new BufferOverflowException();
289: }
290: }
291: else
292: {
293: ByteBuffer outbuf = (ByteBuffer)
294: fragment.duplicate().position(0).limit(record.length() - maclen - padRemoveLen);
295: if (record.version().compareTo(ProtocolVersion.TLS_1_1) >= 0
296: && !suite.isStreamCipher())
297: outbuf.position(cipher.getBlockSize());
298: if (outputStream != null)
299: {
300: byte[] buf = new byte[1024];
301: while (outbuf.hasRemaining())
302: {
303: int l = Math.min(outbuf.remaining(), buf.length);
304: outbuf.get(buf, 0, l);
305: outputStream.write(buf, 0, l);
306: produced += l;
307: }
308: }
309: else
310: {
311: int i = offset;
312: while (outbuf.hasRemaining() && i < offset + length)
313: {
314: int l = Math.min(output[i].remaining(), outbuf.remaining());
315: ByteBuffer b = (ByteBuffer) outbuf.duplicate().limit(outbuf.position() + l);
316: output[i++].put(b);
317: outbuf.position(outbuf.position() + l);
318: produced += l;
319: }
320: if (outbuf.hasRemaining())
321: throw new BufferOverflowException();
322: }
323: }
324:
325: sequence++;
326:
327: return produced;
328: }
329:
330: CipherSuite cipherSuite ()
331: {
332: return suite;
333: }
334: }