title: SSLEngine: Invalid TLS padding data when unwrapping after a successful handshake
body: <p>I am using non-blocking socketChannel and SSLEngine an ssl server. So after a successfull handshake, i read the socket ( 184 bytes /384 bytes are being read in the first time), and then i pass this buffer to unwrap method. The unwrap method throw the following exception :</p>
  
  <pre><code>javax.net.ssl.SSLHandshakeException: Invalid TLS padding data
      at sun.security.ssl.Alerts.getSSLException(Unknown Source)
      at sun.security.ssl.SSLEngineImpl.fatal(Unknown Source)
      at sun.security.ssl.SSLEngineImpl.readRecord(Unknown Source)
      at sun.security.ssl.SSLEngineImpl.readNetRecord(Unknown Source)
      at sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source)
      at javax.net.ssl.SSLEngine.unwrap(Unknown Source)
  </code></pre>
  
  <p>But in case I read all the bytes (384/384) in the first time, then I don't get this exception.</p>
  
  <p>I thought that if the sslengine doesn't have enough byte to unwrap it will return a bufferUnderflow status.</p>
  
  <p>Do I really need all bytes to call unwrap method? If yes how can I be sure I read all bytes for the non blocking socket?</p>
  
  <hr>
  
  <p>EDIT: the code:</p>
  
  <pre><code>public boolean doHandShake(SocketChannel socket) throws Exception{
  
          if(!socket.isConnected()){
              return false;
          }
  
          outAppData.clear();
          inAppData.clear();
          inNetData.clear();
          outNetData.clear();
  
          if(engine==null || socket==null)
           return false;
  
  
            engine.beginHandshake();
            SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
  
            while (hs != SSLEngineResult.HandshakeStatus.FINISHED &amp;&amp;
                      hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
  
                switch (hs) {
  
                case NEED_UNWRAP:
                     int read=1;
                    while (read &gt; 0) {
                              read=socket.read(inNetData);
                              if(read==-1){
                                  throw new IOException ("channel closed");
                              }
                          }
  
                    inNetData.flip();
                    engineRes=engine.unwrap(inNetData, outAppData);
                    inNetData.compact();
  
                    switch(engineRes.getStatus()){
                              case BUFFER_OVERFLOW:
                                  System.out.println("overFlow");
                                  break;
                              case CLOSED:
                                  return false;
                              case OK:
                                  //outAppData.clear();
                              //  inNetData.clear();
                                  break;
                              default:
                                  break;
                    }
  
                break;
  
                case NEED_WRAP :
                   outNetData.clear();
                    engineRes=engine.wrap(inAppData, outNetData);
                    outNetData.flip();
                    switch (engineRes.getStatus()){
                              case BUFFER_OVERFLOW:
                                  System.out.println("overFlow");
                                  break;
                              case BUFFER_UNDERFLOW:
                                  System.out.println("underFlowa");
                                  break;
                              case CLOSED:
                                  return false;
                              case OK:
                                  //outNetData.flip();
                                  while(outNetData.hasRemaining()){
                                      if(socket.write(outNetData)&lt;0){
                                          throw new Exception("Channel Has been Closed");
                                      }
                                  }
  
                                  break;
                              default:
                                  break;
  
  
                    }
  
                break;
  
                case NEED_TASK :
                    Runnable r=engine.getDelegatedTask();
                    r.run();
                    break;
  
                case FINISHED:
                    System.out.println("finished");
                      break;
  
                case NOT_HANDSHAKING:
                      break;
  
                    default: 
                        throw new IllegalArgumentException("Inexpected/Unhadled SSLEngineResult :"+hs);
  
                }
  
                hs = engine.getHandshakeStatus();
  
            }
            return true;
  
      }
  </code></pre>
  
  <p>then I read 184/384 bytes using non blocking channel.</p>
  
  <p>read = _socketChannel.read(buffer);</p>
  
  <p>and then pass the to <code>buffer</code> to be decrypted:</p>
  
  <pre><code>public ByteBuffer decrypt(ByteBuffer inNetData) throws SSLException{
  
          if(!isValidSession()){
              return null;
          }
              outAppData.clear();
  
              try{
                engineRes=engine.unwrap(inNetData, outAppData);
              }catch(Exception e){
                  e.printStackTrace();
              }
                inNetData.compact();
  
                switch(engineRes.getStatus()){
                      case BUFFER_OVERFLOW:
                          outAppData=ByteBuffer.allocate(outNetData.capacity()*2);
                          inNetData.position(0);
                          return encrypt(inNetData);
                      case BUFFER_UNDERFLOW:
                          return null;
                      case CLOSED:
                          return null;
                      case OK:
                          outAppData.flip();
                          System.out.println(new String(outAppData.array(),0,400));
  
                          return outAppData;
                      default:
                          break;
                }
  
  
          return null;
      }
  </code></pre>
  
  <p>the exception is being thrown in engine.unwrap
  engineRes=engine.unwrap(inNetData, outAppData);</p>