130 |
120 |
131 // SSLEngine and SSLSocket |
121 // SSLEngine and SSLSocket |
132 abstract void encodeChangeCipherSpec() throws IOException; |
122 abstract void encodeChangeCipherSpec() throws IOException; |
133 |
123 |
134 // apply to SSLEngine only |
124 // apply to SSLEngine only |
135 Ciphertext encode(ByteBuffer[] sources, int offset, int length, |
125 Ciphertext encode( |
136 ByteBuffer destination) throws IOException { |
126 ByteBuffer[] srcs, int srcsOffset, int srcsLength, |
|
127 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException { |
|
128 |
137 throw new UnsupportedOperationException(); |
129 throw new UnsupportedOperationException(); |
138 } |
130 } |
139 |
131 |
140 // apply to SSLEngine only |
132 // apply to SSLEngine only |
141 void encodeV2NoCipher() throws IOException { |
133 void encodeV2NoCipher() throws IOException { |
142 throw new UnsupportedOperationException(); |
134 throw new UnsupportedOperationException(); |
143 } |
135 } |
144 |
136 |
145 // apply to SSLSocket only |
137 // apply to SSLSocket only |
146 void deliver(byte[] source, int offset, int length) throws IOException { |
138 void deliver( |
|
139 byte[] source, int offset, int length) throws IOException { |
147 throw new UnsupportedOperationException(); |
140 throw new UnsupportedOperationException(); |
148 } |
141 } |
149 |
142 |
150 // apply to SSLSocket only |
143 // apply to SSLSocket only |
151 void setDeliverStream(OutputStream outputStream) { |
144 void setDeliverStream(OutputStream outputStream) { |
152 throw new UnsupportedOperationException(); |
145 throw new UnsupportedOperationException(); |
153 } |
146 } |
154 |
147 |
155 // apply to SSLEngine only |
148 void changeWriteCiphers(SSLWriteCipher writeCipher, |
156 Ciphertext acquireCiphertext(ByteBuffer destination) throws IOException { |
149 boolean useChangeCipherSpec) throws IOException { |
157 throw new UnsupportedOperationException(); |
150 if (useChangeCipherSpec) { |
158 } |
151 encodeChangeCipherSpec(); |
159 |
152 } |
160 void changeWriteCiphers(Authenticator writeAuthenticator, |
|
161 CipherBox writeCipher) throws IOException { |
|
162 |
|
163 encodeChangeCipherSpec(); |
|
164 |
153 |
165 /* |
154 /* |
166 * Dispose of any intermediate state in the underlying cipher. |
155 * Dispose of any intermediate state in the underlying cipher. |
167 * For PKCS11 ciphers, this will release any attached sessions, |
156 * For PKCS11 ciphers, this will release any attached sessions, |
168 * and thus make finalization faster. |
157 * and thus make finalization faster. |
205 isClosed = true; |
198 isClosed = true; |
206 writeCipher.dispose(); |
199 writeCipher.dispose(); |
207 } |
200 } |
208 } |
201 } |
209 |
202 |
|
203 synchronized boolean isClosed() { |
|
204 return isClosed; |
|
205 } |
|
206 |
210 // |
207 // |
211 // shared helpers |
208 // shared helpers |
212 // |
209 // |
213 |
210 |
214 // Encrypt a fragment and wrap up a record. |
211 // Encrypt a fragment and wrap up a record. |
215 // |
212 // |
216 // To be consistent with the spec of SSLEngine.wrap() methods, the |
213 // To be consistent with the spec of SSLEngine.wrap() methods, the |
217 // destination ByteBuffer's position is updated to reflect the amount |
214 // destination ByteBuffer's position is updated to reflect the amount |
218 // of data produced. The limit remains the same. |
215 // of data produced. The limit remains the same. |
219 static long encrypt(Authenticator authenticator, |
216 static long encrypt( |
220 CipherBox encCipher, byte contentType, ByteBuffer destination, |
217 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, |
221 int headerOffset, int dstLim, int headerSize, |
218 int headerOffset, int dstLim, int headerSize, |
222 ProtocolVersion protocolVersion, boolean isDTLS) { |
219 ProtocolVersion protocolVersion) { |
223 |
220 boolean isDTLS = protocolVersion.isDTLS; |
224 byte[] sequenceNumber = null; |
|
225 int dstContent = destination.position(); |
|
226 |
|
227 // Acquire the current sequence number before using. |
|
228 if (isDTLS) { |
221 if (isDTLS) { |
229 sequenceNumber = authenticator.sequenceNumber(); |
222 if (protocolVersion.useTLS13PlusSpec()) { |
230 } |
223 return d13Encrypt(encCipher, |
231 |
224 contentType, destination, headerOffset, |
232 // The sequence number may be shared for different purpose. |
225 dstLim, headerSize, protocolVersion); |
233 boolean sharedSequenceNumber = false; |
226 } else { |
234 |
227 return d10Encrypt(encCipher, |
235 // "flip" but skip over header again, add MAC & encrypt |
228 contentType, destination, headerOffset, |
236 if (authenticator instanceof MAC) { |
229 dstLim, headerSize, protocolVersion); |
237 MAC signer = (MAC)authenticator; |
|
238 if (signer.MAClen() != 0) { |
|
239 byte[] hash = signer.compute(contentType, destination, false); |
|
240 |
|
241 /* |
|
242 * position was advanced to limit in MAC compute above. |
|
243 * |
|
244 * Mark next area as writable (above layers should have |
|
245 * established that we have plenty of room), then write |
|
246 * out the hash. |
|
247 */ |
|
248 destination.limit(destination.limit() + hash.length); |
|
249 destination.put(hash); |
|
250 |
|
251 // reset the position and limit |
|
252 destination.limit(destination.position()); |
|
253 destination.position(dstContent); |
|
254 |
|
255 // The signer has used and increased the sequence number. |
|
256 if (isDTLS) { |
|
257 sharedSequenceNumber = true; |
|
258 } |
|
259 } |
|
260 } |
|
261 |
|
262 if (!encCipher.isNullCipher()) { |
|
263 if (protocolVersion.useTLS11PlusSpec() && |
|
264 (encCipher.isCBCMode() || encCipher.isAEADMode())) { |
|
265 byte[] nonce = encCipher.createExplicitNonce( |
|
266 authenticator, contentType, destination.remaining()); |
|
267 destination.position(headerOffset + headerSize); |
|
268 destination.put(nonce); |
|
269 } |
|
270 if (!encCipher.isAEADMode()) { |
|
271 // The explicit IV in TLS 1.1 and later can be encrypted. |
|
272 destination.position(headerOffset + headerSize); |
|
273 } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode |
|
274 |
|
275 // Encrypt may pad, so again the limit may be changed. |
|
276 encCipher.encrypt(destination, dstLim); |
|
277 |
|
278 // The cipher has used and increased the sequence number. |
|
279 if (isDTLS && encCipher.isAEADMode()) { |
|
280 sharedSequenceNumber = true; |
|
281 } |
230 } |
282 } else { |
231 } else { |
283 destination.position(destination.limit()); |
232 if (protocolVersion.useTLS13PlusSpec()) { |
284 } |
233 return t13Encrypt(encCipher, |
|
234 contentType, destination, headerOffset, |
|
235 dstLim, headerSize, protocolVersion); |
|
236 } else { |
|
237 return t10Encrypt(encCipher, |
|
238 contentType, destination, headerOffset, |
|
239 dstLim, headerSize, protocolVersion); |
|
240 } |
|
241 } |
|
242 } |
|
243 |
|
244 static long d13Encrypt( |
|
245 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, |
|
246 int headerOffset, int dstLim, int headerSize, |
|
247 ProtocolVersion protocolVersion) { |
|
248 throw new UnsupportedOperationException("Not supported yet."); |
|
249 } |
|
250 |
|
251 private static long d10Encrypt( |
|
252 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, |
|
253 int headerOffset, int dstLim, int headerSize, |
|
254 ProtocolVersion protocolVersion) { |
|
255 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); |
|
256 encCipher.encrypt(contentType, destination); |
285 |
257 |
286 // Finish out the record header. |
258 // Finish out the record header. |
287 int fragLen = destination.limit() - headerOffset - headerSize; |
259 int fragLen = destination.limit() - headerOffset - headerSize; |
288 |
260 |
289 destination.put(headerOffset, contentType); // content type |
261 destination.put(headerOffset, contentType); // content type |
290 destination.put(headerOffset + 1, protocolVersion.major); |
262 destination.put(headerOffset + 1, protocolVersion.major); |
291 destination.put(headerOffset + 2, protocolVersion.minor); |
263 destination.put(headerOffset + 2, protocolVersion.minor); |
292 if (!isDTLS) { |
264 |
293 // fragment length |
265 // epoch and sequence_number |
294 destination.put(headerOffset + 3, (byte)(fragLen >> 8)); |
266 destination.put(headerOffset + 3, sequenceNumber[0]); |
295 destination.put(headerOffset + 4, (byte)fragLen); |
267 destination.put(headerOffset + 4, sequenceNumber[1]); |
296 } else { |
268 destination.put(headerOffset + 5, sequenceNumber[2]); |
297 // epoch and sequence_number |
269 destination.put(headerOffset + 6, sequenceNumber[3]); |
298 destination.put(headerOffset + 3, sequenceNumber[0]); |
270 destination.put(headerOffset + 7, sequenceNumber[4]); |
299 destination.put(headerOffset + 4, sequenceNumber[1]); |
271 destination.put(headerOffset + 8, sequenceNumber[5]); |
300 destination.put(headerOffset + 5, sequenceNumber[2]); |
272 destination.put(headerOffset + 9, sequenceNumber[6]); |
301 destination.put(headerOffset + 6, sequenceNumber[3]); |
273 destination.put(headerOffset + 10, sequenceNumber[7]); |
302 destination.put(headerOffset + 7, sequenceNumber[4]); |
274 |
303 destination.put(headerOffset + 8, sequenceNumber[5]); |
275 // fragment length |
304 destination.put(headerOffset + 9, sequenceNumber[6]); |
276 destination.put(headerOffset + 11, (byte)(fragLen >> 8)); |
305 destination.put(headerOffset + 10, sequenceNumber[7]); |
277 destination.put(headerOffset + 12, (byte)fragLen); |
306 |
278 |
307 // fragment length |
279 // Update destination position to reflect the amount of data produced. |
308 destination.put(headerOffset + 11, (byte)(fragLen >> 8)); |
280 destination.position(destination.limit()); |
309 destination.put(headerOffset + 12, (byte)fragLen); |
281 |
310 |
282 return Authenticator.toLong(sequenceNumber); |
311 // Increase the sequence number for next use if it is not shared. |
283 } |
312 if (!sharedSequenceNumber) { |
284 |
313 authenticator.increaseSequenceNumber(); |
285 static long t13Encrypt( |
314 } |
286 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, |
315 } |
287 int headerOffset, int dstLim, int headerSize, |
|
288 ProtocolVersion protocolVersion) { |
|
289 if (!encCipher.isNullCipher()) { |
|
290 // inner plaintext, using zero length padding. |
|
291 int endOfPt = destination.limit(); |
|
292 destination.limit(endOfPt + 1); |
|
293 destination.put(endOfPt, contentType); |
|
294 } |
|
295 |
|
296 // use the right TLSCiphertext.opaque_type and legacy_record_version |
|
297 ProtocolVersion pv = protocolVersion; |
|
298 if (!encCipher.isNullCipher()) { |
|
299 pv = ProtocolVersion.TLS12; |
|
300 contentType = ContentType.APPLICATION_DATA.id; |
|
301 } else if (protocolVersion.useTLS13PlusSpec()) { |
|
302 pv = ProtocolVersion.TLS12; |
|
303 } |
|
304 |
|
305 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); |
|
306 encCipher.encrypt(contentType, destination); |
|
307 |
|
308 // Finish out the record header. |
|
309 int fragLen = destination.limit() - headerOffset - headerSize; |
|
310 destination.put(headerOffset, contentType); |
|
311 destination.put(headerOffset + 1, pv.major); |
|
312 destination.put(headerOffset + 2, pv.minor); |
|
313 |
|
314 // fragment length |
|
315 destination.put(headerOffset + 3, (byte)(fragLen >> 8)); |
|
316 destination.put(headerOffset + 4, (byte)fragLen); |
|
317 |
|
318 // Update destination position to reflect the amount of data produced. |
|
319 destination.position(destination.limit()); |
|
320 |
|
321 return Authenticator.toLong(sequenceNumber); |
|
322 } |
|
323 |
|
324 static long t10Encrypt( |
|
325 SSLWriteCipher encCipher, byte contentType, ByteBuffer destination, |
|
326 int headerOffset, int dstLim, int headerSize, |
|
327 ProtocolVersion protocolVersion) { |
|
328 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); |
|
329 encCipher.encrypt(contentType, destination); |
|
330 |
|
331 // Finish out the record header. |
|
332 int fragLen = destination.limit() - headerOffset - headerSize; |
|
333 |
|
334 destination.put(headerOffset, contentType); // content type |
|
335 destination.put(headerOffset + 1, protocolVersion.major); |
|
336 destination.put(headerOffset + 2, protocolVersion.minor); |
|
337 |
|
338 // fragment length |
|
339 destination.put(headerOffset + 3, (byte)(fragLen >> 8)); |
|
340 destination.put(headerOffset + 4, (byte)fragLen); |
316 |
341 |
317 // Update destination position to reflect the amount of data produced. |
342 // Update destination position to reflect the amount of data produced. |
318 destination.position(destination.limit()); |
343 destination.position(destination.limit()); |
319 |
344 |
320 return Authenticator.toLong(sequenceNumber); |
345 return Authenticator.toLong(sequenceNumber); |
322 |
347 |
323 // Encrypt a fragment and wrap up a record. |
348 // Encrypt a fragment and wrap up a record. |
324 // |
349 // |
325 // Uses the internal expandable buf variable and the current |
350 // Uses the internal expandable buf variable and the current |
326 // protocolVersion variable. |
351 // protocolVersion variable. |
327 void encrypt(Authenticator authenticator, |
352 long encrypt( |
328 CipherBox encCipher, byte contentType, int headerSize) { |
353 SSLWriteCipher encCipher, byte contentType, int headerSize) { |
329 |
354 if (protocolVersion.useTLS13PlusSpec()) { |
|
355 return t13Encrypt(encCipher, contentType, headerSize); |
|
356 } else { |
|
357 return t10Encrypt(encCipher, contentType, headerSize); |
|
358 } |
|
359 } |
|
360 |
|
361 private static final class T13PaddingHolder { |
|
362 private static final byte[] zeros = new byte[16]; |
|
363 } |
|
364 |
|
365 long t13Encrypt( |
|
366 SSLWriteCipher encCipher, byte contentType, int headerSize) { |
|
367 if (!encCipher.isNullCipher()) { |
|
368 // inner plaintext |
|
369 write(contentType); |
|
370 write(T13PaddingHolder.zeros, 0, T13PaddingHolder.zeros.length); |
|
371 } |
|
372 |
|
373 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); |
|
374 int position = headerSize; |
|
375 int contentLen = count - position; |
|
376 |
|
377 // ensure the capacity |
|
378 int packetSize = encCipher.calculatePacketSize(contentLen, headerSize); |
|
379 if (packetSize > buf.length) { |
|
380 byte[] newBuf = new byte[packetSize]; |
|
381 System.arraycopy(buf, 0, newBuf, 0, count); |
|
382 buf = newBuf; |
|
383 } |
|
384 |
|
385 // use the right TLSCiphertext.opaque_type and legacy_record_version |
|
386 ProtocolVersion pv = protocolVersion; |
|
387 if (!encCipher.isNullCipher()) { |
|
388 pv = ProtocolVersion.TLS12; |
|
389 contentType = ContentType.APPLICATION_DATA.id; |
|
390 } else { |
|
391 pv = ProtocolVersion.TLS12; |
|
392 } |
|
393 |
|
394 ByteBuffer destination = ByteBuffer.wrap(buf, position, contentLen); |
|
395 count = headerSize + encCipher.encrypt(contentType, destination); |
|
396 |
|
397 // Fill out the header, write it and the message. |
|
398 int fragLen = count - headerSize; |
|
399 |
|
400 buf[0] = contentType; |
|
401 buf[1] = pv.major; |
|
402 buf[2] = pv.minor; |
|
403 buf[3] = (byte)((fragLen >> 8) & 0xFF); |
|
404 buf[4] = (byte)(fragLen & 0xFF); |
|
405 |
|
406 return Authenticator.toLong(sequenceNumber); |
|
407 } |
|
408 |
|
409 long t10Encrypt( |
|
410 SSLWriteCipher encCipher, byte contentType, int headerSize) { |
|
411 byte[] sequenceNumber = encCipher.authenticator.sequenceNumber(); |
330 int position = headerSize + writeCipher.getExplicitNonceSize(); |
412 int position = headerSize + writeCipher.getExplicitNonceSize(); |
331 |
413 int contentLen = count - position; |
332 // "flip" but skip over header again, add MAC & encrypt |
414 |
333 int macLen = 0; |
415 // ensure the capacity |
334 if (authenticator instanceof MAC) { |
416 int packetSize = encCipher.calculatePacketSize(contentLen, headerSize); |
335 MAC signer = (MAC)authenticator; |
417 if (packetSize > buf.length) { |
336 macLen = signer.MAClen(); |
418 byte[] newBuf = new byte[packetSize]; |
337 if (macLen != 0) { |
419 System.arraycopy(buf, 0, newBuf, 0, count); |
338 byte[] hash = signer.compute(contentType, |
420 buf = newBuf; |
339 buf, position, (count - position), false); |
421 } |
340 |
422 ByteBuffer destination = ByteBuffer.wrap(buf, position, contentLen); |
341 write(hash, 0, hash.length); |
423 count = headerSize + encCipher.encrypt(contentType, destination); |
342 } |
|
343 } |
|
344 |
|
345 if (!encCipher.isNullCipher()) { |
|
346 // Requires explicit IV/nonce for CBC/AEAD cipher suites for |
|
347 // TLS 1.1 or later. |
|
348 if (protocolVersion.useTLS11PlusSpec() && |
|
349 (encCipher.isCBCMode() || encCipher.isAEADMode())) { |
|
350 |
|
351 byte[] nonce = encCipher.createExplicitNonce( |
|
352 authenticator, contentType, (count - position)); |
|
353 int noncePos = position - nonce.length; |
|
354 System.arraycopy(nonce, 0, buf, noncePos, nonce.length); |
|
355 } |
|
356 |
|
357 if (!encCipher.isAEADMode()) { |
|
358 // The explicit IV in TLS 1.1 and later can be encrypted. |
|
359 position = headerSize; |
|
360 } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode |
|
361 |
|
362 // increase buf capacity if necessary |
|
363 int fragSize = count - position; |
|
364 int packetSize = |
|
365 encCipher.calculatePacketSize(fragSize, macLen, headerSize); |
|
366 if (packetSize > (buf.length - position)) { |
|
367 byte[] newBuf = new byte[position + packetSize]; |
|
368 System.arraycopy(buf, 0, newBuf, 0, count); |
|
369 buf = newBuf; |
|
370 } |
|
371 |
|
372 // Encrypt may pad, so again the count may be changed. |
|
373 count = position + |
|
374 encCipher.encrypt(buf, position, (count - position)); |
|
375 } |
|
376 |
424 |
377 // Fill out the header, write it and the message. |
425 // Fill out the header, write it and the message. |
378 int fragLen = count - headerSize; |
426 int fragLen = count - headerSize; |
379 buf[0] = contentType; |
427 buf[0] = contentType; |
380 buf[1] = protocolVersion.major; |
428 buf[1] = protocolVersion.major; |
381 buf[2] = protocolVersion.minor; |
429 buf[2] = protocolVersion.minor; |
382 buf[3] = (byte)((fragLen >> 8) & 0xFF); |
430 buf[3] = (byte)((fragLen >> 8) & 0xFF); |
383 buf[4] = (byte)(fragLen & 0xFF); |
431 buf[4] = (byte)(fragLen & 0xFF); |
|
432 |
|
433 return Authenticator.toLong(sequenceNumber); |
384 } |
434 } |
385 |
435 |
386 static ByteBuffer encodeV2ClientHello( |
436 static ByteBuffer encodeV2ClientHello( |
387 byte[] fragment, int offset, int length) throws IOException { |
437 byte[] fragment, int offset, int length) throws IOException { |
388 |
|
389 int v3SessIdLenOffset = offset + 34; // 2: client_version |
438 int v3SessIdLenOffset = offset + 34; // 2: client_version |
390 // 32: random |
439 // 32: random |
391 |
440 |
392 int v3SessIdLen = fragment[v3SessIdLenOffset]; |
441 int v3SessIdLen = fragment[v3SessIdLenOffset]; |
393 int v3CSLenOffset = v3SessIdLenOffset + 1 + v3SessIdLen; |
442 int v3CSLenOffset = v3SessIdLenOffset + 1 + v3SessIdLen; |