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