src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java

Print this page
8167680 DTLS implementation bugs
   1 /*
   2  * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 977         } catch (BadPaddingException e) {
 978             /*
 979              * The basic SSLv3 record protection involves (optional)
 980              * encryption for privacy, and an integrity check ensuring
 981              * data origin authentication.  We do them both here, and
 982              * throw a fatal alert if the integrity check fails.
 983              */
 984             byte alertType = (connectionState != cs_DATA) ?
 985                     Alerts.alert_handshake_failure :
 986                     Alerts.alert_bad_record_mac;
 987             fatal(alertType, e.getMessage(), e);
 988         } catch (SSLHandshakeException she) {
 989             // may be record sequence number overflow
 990             fatal(Alerts.alert_handshake_failure, she);
 991         } catch (IOException ioe) {
 992             fatal(Alerts.alert_unexpected_message, ioe);
 993         }
 994 
 995         // plainText should never be null for TLS protocols
 996         HandshakeStatus hsStatus = null;
 997         if (!isDTLS || plainText != null) {















 998             hsStatus = processInputRecord(plainText, appData, offset, length);
 999         }
1000 
1001         if (hsStatus == null) {
1002             hsStatus = getHSStatus(null);
1003         }
1004 
1005         if (plainText == null) {
1006             plainText = new Plaintext();
1007         }
1008         plainText.handshakeStatus = hsStatus;
1009 
1010         return plainText;
1011     }
1012 
1013     /*
1014      * Process the record.
1015      */
1016     private synchronized HandshakeStatus processInputRecord(
1017             Plaintext plainText,
1018             ByteBuffer[] appData, int offset, int length) throws IOException {
1019 
1020         HandshakeStatus hsStatus = null;
1021         switch (plainText.contentType) {
1022             case Record.ct_handshake:
1023                 /*
1024                  * Handshake messages always go to a pending session
1025                  * handshaker ... if there isn't one, create one.  This
1026                  * must work asynchronously, for renegotiation.


1361         int deltaApp = appRemains;
1362         for (int i = offset; i < offset + length; i++) {
1363             deltaApp -= appData[i].remaining();
1364         }
1365 
1366         return new SSLEngineResult(
1367                 status, hsStatus, deltaApp, deltaNet, ciphertext.recordSN);
1368     }
1369 
1370     /*
1371      * Central point to write/get all of the outgoing data.
1372      */
1373     private Ciphertext writeRecord(ByteBuffer[] appData,
1374             int offset, int length, ByteBuffer netData) throws IOException {
1375 
1376         Ciphertext ciphertext = null;
1377         try {
1378             // Acquire the buffered to-be-delivered records or retransmissions.
1379             //
1380             // May have buffered records, or need retransmission if handshaking.
1381             if (!outputRecord.isEmpty() || (handshaker != null)) {

1382                 ciphertext = outputRecord.acquireCiphertext(netData);
1383             }
1384 
1385             if ((ciphertext == null) && (appData != null)) {
1386                 ciphertext = outputRecord.encode(
1387                         appData, offset, length, netData);
1388             }
1389         } catch (SSLHandshakeException she) {
1390             // may be record sequence number overflow
1391             fatal(Alerts.alert_handshake_failure, she);
1392 
1393             return Ciphertext.CIPHERTEXT_NULL;   // make the complier happy
1394         } catch (IOException e) {
1395             fatal(Alerts.alert_unexpected_message, e);
1396 
1397             return Ciphertext.CIPHERTEXT_NULL;   // make the complier happy
1398         }
1399 
1400         if (ciphertext == null) {
1401             return Ciphertext.CIPHERTEXT_NULL;
1402         }
1403 
1404         HandshakeStatus hsStatus = null;
1405         Ciphertext.RecordType recordType = ciphertext.recordType;
1406         if ((handshaker != null) &&
1407                 (recordType.contentType == Record.ct_handshake) &&
1408                 (recordType.handshakeType == HandshakeMessage.ht_finished) &&
1409                 handshaker.isDone() && outputRecord.isEmpty()) {
1410 



1411             hsStatus = finishHandshake();
1412             connectionState = cs_DATA;





















1413         }   // Otherwise, the followed call to getHSStatus() will help.
1414 
1415         /*
1416          * We only need to check the sequence number state for
1417          * non-handshaking record.
1418          *
1419          * Note that in order to maintain the handshake status
1420          * properly, we check the sequence number after the last
1421          * record writing process. As we request renegotiation
1422          * or close the connection for wrapped sequence number
1423          * when there is enough sequence number space left to
1424          * handle a few more records, so the sequence number
1425          * of the last record cannot be wrapped.
1426          */
1427         hsStatus = getHSStatus(hsStatus);
1428         if (connectionState < cs_ERROR && !isOutboundDone() &&
1429                 (hsStatus == HandshakeStatus.NOT_HANDSHAKING) &&
1430                 (outputRecord.seqNumIsHuge())) {
1431             /*
1432              * Ask for renegotiation when need to renew sequence number.


   1 /*
   2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 977         } catch (BadPaddingException e) {
 978             /*
 979              * The basic SSLv3 record protection involves (optional)
 980              * encryption for privacy, and an integrity check ensuring
 981              * data origin authentication.  We do them both here, and
 982              * throw a fatal alert if the integrity check fails.
 983              */
 984             byte alertType = (connectionState != cs_DATA) ?
 985                     Alerts.alert_handshake_failure :
 986                     Alerts.alert_bad_record_mac;
 987             fatal(alertType, e.getMessage(), e);
 988         } catch (SSLHandshakeException she) {
 989             // may be record sequence number overflow
 990             fatal(Alerts.alert_handshake_failure, she);
 991         } catch (IOException ioe) {
 992             fatal(Alerts.alert_unexpected_message, ioe);
 993         }
 994 
 995         // plainText should never be null for TLS protocols
 996         HandshakeStatus hsStatus = null;
 997         if (plainText == Plaintext.PLAINTEXT_NULL) {
 998             // Only happens for DTLS protocols.
 999             //
1000             // Received a retransmitted flight, and need to retransmit the
1001             // previous delivered handshake flight messages.
1002             if (enableRetransmissions) {
1003                 if (debug != null && Debug.isOn("verbose")) {
1004                     Debug.log(
1005                         "Retransmit the previous handshake flight messages.");
1006                 }
1007 
1008                 synchronized (this) {
1009                     outputRecord.launchRetransmission();
1010                 }
1011             }   // Otherwise, discard the retransmitted flight.
1012         } else if (!isDTLS || plainText != null) {
1013             hsStatus = processInputRecord(plainText, appData, offset, length);
1014         }
1015 
1016         if (hsStatus == null) {
1017             hsStatus = getHSStatus(null);
1018         }
1019 
1020         if (plainText == null) {
1021             plainText = Plaintext.PLAINTEXT_NULL;
1022         }
1023         plainText.handshakeStatus = hsStatus;
1024 
1025         return plainText;
1026     }
1027 
1028     /*
1029      * Process the record.
1030      */
1031     private synchronized HandshakeStatus processInputRecord(
1032             Plaintext plainText,
1033             ByteBuffer[] appData, int offset, int length) throws IOException {
1034 
1035         HandshakeStatus hsStatus = null;
1036         switch (plainText.contentType) {
1037             case Record.ct_handshake:
1038                 /*
1039                  * Handshake messages always go to a pending session
1040                  * handshaker ... if there isn't one, create one.  This
1041                  * must work asynchronously, for renegotiation.


1376         int deltaApp = appRemains;
1377         for (int i = offset; i < offset + length; i++) {
1378             deltaApp -= appData[i].remaining();
1379         }
1380 
1381         return new SSLEngineResult(
1382                 status, hsStatus, deltaApp, deltaNet, ciphertext.recordSN);
1383     }
1384 
1385     /*
1386      * Central point to write/get all of the outgoing data.
1387      */
1388     private Ciphertext writeRecord(ByteBuffer[] appData,
1389             int offset, int length, ByteBuffer netData) throws IOException {
1390 
1391         Ciphertext ciphertext = null;
1392         try {
1393             // Acquire the buffered to-be-delivered records or retransmissions.
1394             //
1395             // May have buffered records, or need retransmission if handshaking.
1396             if (!outputRecord.isEmpty() ||
1397                     (enableRetransmissions && handshaker != null)) {
1398                 ciphertext = outputRecord.acquireCiphertext(netData);
1399             }
1400 
1401             if ((ciphertext == null) && (appData != null)) {
1402                 ciphertext = outputRecord.encode(
1403                         appData, offset, length, netData);
1404             }
1405         } catch (SSLHandshakeException she) {
1406             // may be record sequence number overflow
1407             fatal(Alerts.alert_handshake_failure, she);
1408 
1409             return Ciphertext.CIPHERTEXT_NULL;   // make the complier happy
1410         } catch (IOException e) {
1411             fatal(Alerts.alert_unexpected_message, e);
1412 
1413             return Ciphertext.CIPHERTEXT_NULL;   // make the complier happy
1414         }
1415 
1416         if (ciphertext == null) {
1417             return Ciphertext.CIPHERTEXT_NULL;
1418         }
1419 
1420         HandshakeStatus hsStatus = null;
1421         Ciphertext.RecordType recordType = ciphertext.recordType;
1422         if ((recordType.contentType == Record.ct_handshake) &&

1423             (recordType.handshakeType == HandshakeMessage.ht_finished) &&
1424             outputRecord.isEmpty()) {
1425 
1426             if (handshaker == null) {
1427                 hsStatus = HandshakeStatus.FINISHED;
1428             } else if (handshaker.isDone()) {
1429                 hsStatus = finishHandshake();
1430                 connectionState = cs_DATA;
1431 
1432                 // Retransmit the last flight twice.
1433                 //
1434                 // The application data transactions may begin immediately
1435                 // after the last flight.  If the last flight get lost, the
1436                 // application data may be discarded accordingly.  As could
1437                 // be an issue for some applications.  This impact can be
1438                 // mitigated by sending the last fligth twice.
1439                 if (isDTLS && enableRetransmissions) {
1440                     if (debug != null && Debug.isOn("verbose")) {
1441                         Debug.log(
1442                             "Retransmit the last flight messages.");
1443                     }
1444 
1445                     synchronized (this) {
1446                         outputRecord.launchRetransmission();
1447                     }
1448 
1449                     hsStatus = HandshakeStatus.NEED_WRAP;
1450                 }
1451             }
1452         }   // Otherwise, the followed call to getHSStatus() will help.
1453 
1454         /*
1455          * We only need to check the sequence number state for
1456          * non-handshaking record.
1457          *
1458          * Note that in order to maintain the handshake status
1459          * properly, we check the sequence number after the last
1460          * record writing process. As we request renegotiation
1461          * or close the connection for wrapped sequence number
1462          * when there is enough sequence number space left to
1463          * handle a few more records, so the sequence number
1464          * of the last record cannot be wrapped.
1465          */
1466         hsStatus = getHSStatus(hsStatus);
1467         if (connectionState < cs_ERROR && !isOutboundDone() &&
1468                 (hsStatus == HandshakeStatus.NOT_HANDSHAKING) &&
1469                 (outputRecord.seqNumIsHuge())) {
1470             /*
1471              * Ask for renegotiation when need to renew sequence number.