• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
3  * Please refer to the LICENSE.txt for licensing details.
4  */
5 package ch.ethz.ssh2.crypto.cipher;
6 
7 import java.io.IOException;
8 import java.io.InputStream;
9 
10 /**
11  * CipherInputStream.
12  *
13  * @author Christian Plattner
14  * @version $Id: CipherInputStream.java 11 2011-05-27 14:14:06Z dkocher@sudo.ch $
15  */
16 public class CipherInputStream
17 {
18 	BlockCipher currentCipher;
19 	InputStream bi;
20 	byte[] buffer;
21 	byte[] enc;
22 	int blockSize;
23 	int pos;
24 
25 	/*
26 	 * We cannot use java.io.BufferedInputStream, since that is not available in
27 	 * J2ME. Everything could be improved alot here.
28 	 */
29 
30 	private static final int BUFF_SIZE = 8192;
31 	byte[] input_buffer = new byte[BUFF_SIZE];
32 	int input_buffer_pos = 0;
33 	int input_buffer_size = 0;
34 
CipherInputStream(BlockCipher tc, InputStream bi)35 	public CipherInputStream(BlockCipher tc, InputStream bi)
36 	{
37 		this.bi = bi;
38 		changeCipher(tc);
39 	}
40 
fill_buffer()41 	private int fill_buffer() throws IOException
42 	{
43 		input_buffer_pos = 0;
44 		input_buffer_size = 0;
45 		input_buffer_size = bi.read(input_buffer, 0, BUFF_SIZE);
46 		return input_buffer_size;
47 	}
48 
internal_read(byte[] b, int off, int len)49 	private int internal_read(byte[] b, int off, int len) throws IOException
50 	{
51 		if (input_buffer_size < 0)
52 		{
53 			return -1;
54 		}
55 
56 		if (input_buffer_pos >= input_buffer_size)
57 		{
58 			if (fill_buffer() <= 0)
59 			{
60 				return -1;
61 			}
62 		}
63 
64 		int avail = input_buffer_size - input_buffer_pos;
65 		int thiscopy = (len > avail) ? avail : len;
66 
67 		System.arraycopy(input_buffer, input_buffer_pos, b, off, thiscopy);
68 		input_buffer_pos += thiscopy;
69 
70 		return thiscopy;
71 	}
72 
changeCipher(BlockCipher bc)73 	public void changeCipher(BlockCipher bc)
74 	{
75 		this.currentCipher = bc;
76 		blockSize = bc.getBlockSize();
77 		buffer = new byte[blockSize];
78 		enc = new byte[blockSize];
79 		pos = blockSize;
80 	}
81 
getBlock()82 	private void getBlock() throws IOException
83 	{
84 		int n = 0;
85 		while (n < blockSize)
86 		{
87 			int len = internal_read(enc, n, blockSize - n);
88 			if (len < 0)
89 			{
90 				throw new IOException("Cannot read full block, EOF reached.");
91 			}
92 			n += len;
93 		}
94 
95 		try
96 		{
97 			currentCipher.transformBlock(enc, 0, buffer, 0);
98 		}
99 		catch (Exception e)
100 		{
101 			throw new IOException("Error while decrypting block.");
102 		}
103 		pos = 0;
104 	}
105 
read(byte[] dst)106 	public int read(byte[] dst) throws IOException
107 	{
108 		return read(dst, 0, dst.length);
109 	}
110 
read(byte[] dst, int off, int len)111 	public int read(byte[] dst, int off, int len) throws IOException
112 	{
113 		int count = 0;
114 
115 		while (len > 0)
116 		{
117 			if (pos >= blockSize)
118 			{
119 				getBlock();
120 			}
121 
122 			int avail = blockSize - pos;
123 			int copy = Math.min(avail, len);
124 			System.arraycopy(buffer, pos, dst, off, copy);
125 			pos += copy;
126 			off += copy;
127 			len -= copy;
128 			count += copy;
129 		}
130 		return count;
131 	}
132 
read()133 	public int read() throws IOException
134 	{
135 		if (pos >= blockSize)
136 		{
137 			getBlock();
138 		}
139 		return buffer[pos++] & 0xff;
140 	}
141 
readPlain(byte[] b, int off, int len)142 	public int readPlain(byte[] b, int off, int len) throws IOException
143 	{
144 		if (pos != blockSize)
145 		{
146 			throw new IOException("Cannot read plain since crypto buffer is not aligned.");
147 		}
148 		int n = 0;
149 		while (n < len)
150 		{
151 			int cnt = internal_read(b, off + n, len - n);
152 			if (cnt < 0)
153 			{
154 				throw new IOException("Cannot fill buffer, EOF reached.");
155 			}
156 			n += cnt;
157 		}
158 		return n;
159 	}
160 }
161