75 private byte v2Buf[]; |
75 private byte v2Buf[]; |
76 |
76 |
77 /* |
77 /* |
78 * Construct the record to hold the maximum sized input record. |
78 * Construct the record to hold the maximum sized input record. |
79 * Data will be filled in separately. |
79 * Data will be filled in separately. |
|
80 * |
|
81 * The structure of the byte buffer looks like: |
|
82 * |
|
83 * |--------+---------+---------------------------------| |
|
84 * | header | IV | content, MAC/TAG, padding, etc. | |
|
85 * | headerPlusIVSize | |
|
86 * |
|
87 * header: the header of an SSL records |
|
88 * IV: the optional IV/nonce field, it is only required for block |
|
89 * (TLS 1.1 or later) and AEAD cipher suites. |
|
90 * |
80 */ |
91 */ |
81 InputRecord() { |
92 InputRecord() { |
82 super(new byte[maxRecordSize]); |
93 super(new byte[maxRecordSize]); |
83 setHelloVersion(ProtocolVersion.DEFAULT_HELLO); |
94 setHelloVersion(ProtocolVersion.DEFAULT_HELLO); |
84 pos = headerSize; |
95 pos = headerSize; |
131 |
142 |
132 HandshakeHash getHandshakeHash() { |
143 HandshakeHash getHandshakeHash() { |
133 return handshakeHash; |
144 return handshakeHash; |
134 } |
145 } |
135 |
146 |
136 /* |
147 void decrypt(Authenticator authenticator, |
137 * Verify and remove the MAC ... used for all records. |
148 CipherBox box) throws BadPaddingException { |
138 */ |
149 |
139 boolean checkMAC(MAC signer) { |
150 BadPaddingException bpe = null; |
140 int len = signer.MAClen(); |
151 if (!box.isNullCipher()) { |
141 if (len == 0) { // no mac |
152 try { |
142 return true; |
153 int cipheredLength = count - headerSize; |
143 } |
154 |
144 |
155 // apply explicit nonce for AEAD/CBC cipher suites if needed |
145 int offset = count - len; |
156 int nonceSize = box.applyExplicitNonce(authenticator, |
146 |
157 contentType(), buf, headerSize, cipheredLength); |
147 if (offset < headerSize) { |
158 pos = headerSize + nonceSize; |
148 // data length would be negative, something is wrong |
159 lastHashed = pos; // don't digest the explicit nonce |
149 return false; |
160 |
150 } |
161 // decrypt the content |
151 |
162 int offset = headerSize; |
152 byte[] mac = signer.compute(contentType(), buf, |
163 if (box.isAEADMode()) { |
153 headerSize, offset - headerSize); |
164 // DON'T encrypt the nonce_explicit for AEAD mode |
154 |
165 offset += nonceSize; |
155 if (len != mac.length) { |
166 } // The explicit IV for CBC mode can be decrypted. |
156 throw new RuntimeException("Internal MAC error"); |
167 |
157 } |
168 count = offset + box.decrypt(buf, offset, count - offset); |
158 |
169 |
159 for (int i = 0; i < len; i++) { |
170 // Note that we don't remove the nonce from the buffer. |
160 if (buf[offset + i] != mac[i]) { |
171 } catch (BadPaddingException e) { |
161 return false; |
172 // RFC 2246 states that decryption_failed should be used |
162 } |
173 // for this purpose. However, that allows certain attacks, |
163 } |
174 // so we just send bad record MAC. We also need to make |
164 count -= len; |
175 // sure to always check the MAC to avoid a timing attack |
165 return true; |
176 // for the same issue. See paper by Vaudenay et al and the |
166 } |
177 // update in RFC 4346/5246. |
167 |
178 // |
168 void decrypt(CipherBox box) throws BadPaddingException { |
179 // Failover to message authenticatoin code checking. |
169 int len = count - headerSize; |
180 bpe = new BadPaddingException("invalid padding"); |
170 count = headerSize + box.decrypt(buf, headerSize, len); |
181 } |
171 } |
182 } |
172 |
183 |
|
184 // Requires message authentication code for null, stream and block |
|
185 // cipher suites. |
|
186 if (authenticator instanceof MAC) { |
|
187 MAC signer = (MAC)authenticator; |
|
188 int macLen = signer.MAClen(); |
|
189 if (macLen != 0) { |
|
190 int macOffset = count - macLen; |
|
191 int contentLen = macOffset - pos; |
|
192 if (contentLen < 0) { |
|
193 // negative data length, something is wrong |
|
194 throw new BadPaddingException("bad record"); |
|
195 } |
|
196 |
|
197 count -= macLen; // Set the count before any MAC checking |
|
198 // exception occurs, so that the following |
|
199 // process can read the actual decrypted |
|
200 // content (minus the MAC) in the fragment |
|
201 // if necessary. |
|
202 byte[] hash = signer.compute(contentType(), |
|
203 buf, pos, contentLen); |
|
204 if (hash == null || macLen != hash.length) { |
|
205 // something is wrong with MAC implementation |
|
206 throw new RuntimeException("Internal MAC error"); |
|
207 } |
|
208 |
|
209 int offset = macOffset; |
|
210 for (byte b : hash) { |
|
211 if (buf[offset++] != b) { |
|
212 throw new BadPaddingException("bad record MAC"); |
|
213 } |
|
214 } |
|
215 } |
|
216 } |
|
217 |
|
218 // Is it a failover? |
|
219 if (bpe != null) { |
|
220 throw bpe; |
|
221 } |
|
222 } |
173 |
223 |
174 /* |
224 /* |
175 * Well ... hello_request messages are _never_ hashed since we can't |
225 * Well ... hello_request messages are _never_ hashed since we can't |
176 * know when they'd appear in the sequence. |
226 * know when they'd appear in the sequence. |
177 */ |
227 */ |