278 private ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT; |
278 private ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT; |
279 |
279 |
280 /* |
280 /* |
281 * Crypto state that's reinitialized when the session changes. |
281 * Crypto state that's reinitialized when the session changes. |
282 */ |
282 */ |
283 private MAC readMAC, writeMAC; |
283 private Authenticator readAuthenticator, writeAuthenticator; |
284 private CipherBox readCipher, writeCipher; |
284 private CipherBox readCipher, writeCipher; |
285 // NOTE: compression state would be saved here |
285 // NOTE: compression state would be saved here |
286 |
286 |
287 /* |
287 /* |
288 * security parameters for secure renegotiation. |
288 * security parameters for secure renegotiation. |
375 * default read and write side cipher and MAC support |
375 * default read and write side cipher and MAC support |
376 * |
376 * |
377 * Note: compression support would go here too |
377 * Note: compression support would go here too |
378 */ |
378 */ |
379 readCipher = CipherBox.NULL; |
379 readCipher = CipherBox.NULL; |
380 readMAC = MAC.NULL; |
380 readAuthenticator = MAC.NULL; |
381 writeCipher = CipherBox.NULL; |
381 writeCipher = CipherBox.NULL; |
382 writeMAC = MAC.NULL; |
382 writeAuthenticator = MAC.NULL; |
383 |
383 |
384 // default security parameters for secure renegotiation |
384 // default security parameters for secure renegotiation |
385 secureRenegotiation = false; |
385 secureRenegotiation = false; |
386 clientVerifyData = new byte[0]; |
386 clientVerifyData = new byte[0]; |
387 serverVerifyData = new byte[0]; |
387 serverVerifyData = new byte[0]; |
584 |
584 |
585 CipherBox oldCipher = readCipher; |
585 CipherBox oldCipher = readCipher; |
586 |
586 |
587 try { |
587 try { |
588 readCipher = handshaker.newReadCipher(); |
588 readCipher = handshaker.newReadCipher(); |
589 readMAC = handshaker.newReadMAC(); |
589 readAuthenticator = handshaker.newReadAuthenticator(); |
590 } catch (GeneralSecurityException e) { |
590 } catch (GeneralSecurityException e) { |
591 // "can't happen" |
591 // "can't happen" |
592 throw new SSLException("Algorithm missing: ", e); |
592 throw new SSLException("Algorithm missing: ", e); |
593 } |
593 } |
594 |
594 |
620 |
620 |
621 CipherBox oldCipher = writeCipher; |
621 CipherBox oldCipher = writeCipher; |
622 |
622 |
623 try { |
623 try { |
624 writeCipher = handshaker.newWriteCipher(); |
624 writeCipher = handshaker.newWriteCipher(); |
625 writeMAC = handshaker.newWriteMAC(); |
625 writeAuthenticator = handshaker.newWriteAuthenticator(); |
626 } catch (GeneralSecurityException e) { |
626 } catch (GeneralSecurityException e) { |
627 // "can't happen" |
627 // "can't happen" |
628 throw new SSLException("Algorithm missing: ", e); |
628 throw new SSLException("Algorithm missing: ", e); |
629 } |
629 } |
630 |
630 |
956 * encryption for privacy, and an integrity check ensuring |
956 * encryption for privacy, and an integrity check ensuring |
957 * data origin authentication. We do them both here, and |
957 * data origin authentication. We do them both here, and |
958 * throw a fatal alert if the integrity check fails. |
958 * throw a fatal alert if the integrity check fails. |
959 */ |
959 */ |
960 try { |
960 try { |
961 decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB); |
961 decryptedBB = inputRecord.decrypt( |
|
962 readAuthenticator, readCipher, readBB); |
962 } catch (BadPaddingException e) { |
963 } catch (BadPaddingException e) { |
963 byte alertType = (inputRecord.contentType() == |
964 byte alertType = (inputRecord.contentType() == |
964 Record.ct_handshake) ? |
965 Record.ct_handshake) ? |
965 Alerts.alert_handshake_failure : |
966 Alerts.alert_handshake_failure : |
966 Alerts.alert_bad_record_mac; |
967 Alerts.alert_bad_record_mac; |
967 fatal(alertType, e.getMessage(), e); |
968 fatal(alertType, e.getMessage(), e); |
968 } |
969 } |
969 |
|
970 |
970 |
971 // if (!inputRecord.decompress(c)) |
971 // if (!inputRecord.decompress(c)) |
972 // fatal(Alerts.alert_decompression_failure, |
972 // fatal(Alerts.alert_decompression_failure, |
973 // "decompression failure"); |
973 // "decompression failure"); |
974 |
974 |
1115 * of the last record cannot be wrapped. |
1115 * of the last record cannot be wrapped. |
1116 */ |
1116 */ |
1117 hsStatus = getHSStatus(hsStatus); |
1117 hsStatus = getHSStatus(hsStatus); |
1118 if (connectionState < cs_ERROR && !isInboundDone() && |
1118 if (connectionState < cs_ERROR && !isInboundDone() && |
1119 (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { |
1119 (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { |
1120 if (checkSequenceNumber(readMAC, |
1120 if (checkSequenceNumber(readAuthenticator, |
1121 inputRecord.contentType())) { |
1121 inputRecord.contentType())) { |
1122 hsStatus = getHSStatus(null); |
1122 hsStatus = getHSStatus(null); |
1123 } |
1123 } |
1124 } |
1124 } |
1125 } // synchronized (this) |
1125 } // synchronized (this) |
1268 private HandshakeStatus writeRecord(EngineOutputRecord eor, |
1268 private HandshakeStatus writeRecord(EngineOutputRecord eor, |
1269 EngineArgs ea) throws IOException { |
1269 EngineArgs ea) throws IOException { |
1270 |
1270 |
1271 // eventually compress as well. |
1271 // eventually compress as well. |
1272 HandshakeStatus hsStatus = |
1272 HandshakeStatus hsStatus = |
1273 writer.writeRecord(eor, ea, writeMAC, writeCipher); |
1273 writer.writeRecord(eor, ea, writeAuthenticator, writeCipher); |
1274 |
1274 |
1275 /* |
1275 /* |
1276 * We only need to check the sequence number state for |
1276 * We only need to check the sequence number state for |
1277 * non-handshaking record. |
1277 * non-handshaking record. |
1278 * |
1278 * |
1285 * of the last record cannot be wrapped. |
1285 * of the last record cannot be wrapped. |
1286 */ |
1286 */ |
1287 hsStatus = getHSStatus(hsStatus); |
1287 hsStatus = getHSStatus(hsStatus); |
1288 if (connectionState < cs_ERROR && !isOutboundDone() && |
1288 if (connectionState < cs_ERROR && !isOutboundDone() && |
1289 (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { |
1289 (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { |
1290 if (checkSequenceNumber(writeMAC, eor.contentType())) { |
1290 if (checkSequenceNumber(writeAuthenticator, eor.contentType())) { |
1291 hsStatus = getHSStatus(null); |
1291 hsStatus = getHSStatus(null); |
1292 } |
1292 } |
1293 } |
1293 } |
1294 |
1294 |
1295 /* |
1295 /* |
1324 /* |
1324 /* |
1325 * Non-application OutputRecords go through here. |
1325 * Non-application OutputRecords go through here. |
1326 */ |
1326 */ |
1327 void writeRecord(EngineOutputRecord eor) throws IOException { |
1327 void writeRecord(EngineOutputRecord eor) throws IOException { |
1328 // eventually compress as well. |
1328 // eventually compress as well. |
1329 writer.writeRecord(eor, writeMAC, writeCipher); |
1329 writer.writeRecord(eor, writeAuthenticator, writeCipher); |
1330 |
1330 |
1331 /* |
1331 /* |
1332 * Check the sequence number state |
1332 * Check the sequence number state |
1333 * |
1333 * |
1334 * Note that in order to maintain the connection I/O |
1334 * Note that in order to maintain the connection I/O |
1338 * when there is enough sequence number space left to |
1338 * when there is enough sequence number space left to |
1339 * handle a few more records, so the sequence number |
1339 * handle a few more records, so the sequence number |
1340 * of the last record cannot be wrapped. |
1340 * of the last record cannot be wrapped. |
1341 */ |
1341 */ |
1342 if ((connectionState < cs_ERROR) && !isOutboundDone()) { |
1342 if ((connectionState < cs_ERROR) && !isOutboundDone()) { |
1343 checkSequenceNumber(writeMAC, eor.contentType()); |
1343 checkSequenceNumber(writeAuthenticator, eor.contentType()); |
1344 } |
1344 } |
1345 } |
1345 } |
1346 |
1346 |
1347 // |
1347 // |
1348 // Close code |
1348 // Close code |
1356 * implementation would need to wrap a sequence number, it must |
1356 * implementation would need to wrap a sequence number, it must |
1357 * renegotiate instead." |
1357 * renegotiate instead." |
1358 * |
1358 * |
1359 * Return true if the handshake status may be changed. |
1359 * Return true if the handshake status may be changed. |
1360 */ |
1360 */ |
1361 private boolean checkSequenceNumber(MAC mac, byte type) |
1361 private boolean checkSequenceNumber(Authenticator authenticator, byte type) |
1362 throws IOException { |
1362 throws IOException { |
1363 |
1363 |
1364 /* |
1364 /* |
1365 * Don't bother to check the sequence number for error or |
1365 * Don't bother to check the sequence number for error or |
1366 * closed connections, or NULL MAC |
1366 * closed connections, or NULL MAC |
1367 */ |
1367 */ |
1368 if (connectionState >= cs_ERROR || mac == MAC.NULL) { |
1368 if (connectionState >= cs_ERROR || authenticator == MAC.NULL) { |
1369 return false; |
1369 return false; |
1370 } |
1370 } |
1371 |
1371 |
1372 /* |
1372 /* |
1373 * Conservatively, close the connection immediately when the |
1373 * Conservatively, close the connection immediately when the |
1374 * sequence number is close to overflow |
1374 * sequence number is close to overflow |
1375 */ |
1375 */ |
1376 if (mac.seqNumOverflow()) { |
1376 if (authenticator.seqNumOverflow()) { |
1377 /* |
1377 /* |
1378 * TLS protocols do not define a error alert for sequence |
1378 * TLS protocols do not define a error alert for sequence |
1379 * number overflow. We use handshake_failure error alert |
1379 * number overflow. We use handshake_failure error alert |
1380 * for handshaking and bad_record_mac for other records. |
1380 * for handshaking and bad_record_mac for other records. |
1381 */ |
1381 */ |
1394 * Ask for renegotiation when need to renew sequence number. |
1394 * Ask for renegotiation when need to renew sequence number. |
1395 * |
1395 * |
1396 * Don't bother to kickstart the renegotiation when the local is |
1396 * Don't bother to kickstart the renegotiation when the local is |
1397 * asking for it. |
1397 * asking for it. |
1398 */ |
1398 */ |
1399 if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) { |
1399 if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) { |
1400 if (debug != null && Debug.isOn("ssl")) { |
1400 if (debug != null && Debug.isOn("ssl")) { |
1401 System.out.println(Thread.currentThread().getName() + |
1401 System.out.println(Thread.currentThread().getName() + |
1402 ", request renegotiation " + |
1402 ", request renegotiation " + |
1403 "to avoid sequence number overflow"); |
1403 "to avoid sequence number overflow"); |
1404 } |
1404 } |