| 1625 | // Read up to "available" bytes from the network, decrypt it and pass plaintext to application. |
| 1626 | |
| 1627 | static ssize_t process_input_ssl(pn_transport_t *transport, unsigned int layer, const char *input_data, size_t available) |
| 1628 | { |
| 1629 | pni_ssl_t *ssl = transport->ssl; |
| 1630 | ssl_log( transport, PN_LEVEL_TRACE, "process_input_ssl( data size=%zu )",available ); |
| 1631 | ssize_t consumed = 0; |
| 1632 | ssize_t forwarded = 0; |
| 1633 | bool new_app_input; |
| 1634 | |
| 1635 | if (available == 0) { |
| 1636 | // No more inbound network data |
| 1637 | read_closed(transport, layer, 0); |
| 1638 | return 0; |
| 1639 | } |
| 1640 | |
| 1641 | do { |
| 1642 | if (ssl->sc_input_shutdown) { |
| 1643 | // TLS protocol shutdown detected on input, so we are done. |
| 1644 | read_closed(transport, layer, 0); |
| 1645 | return PN_EOS; |
| 1646 | } |
| 1647 | |
| 1648 | // sc_inbuf should be ready for new or additional network encrypted bytes. |
| 1649 | // i.e. no straggling decrypted bytes pending. |
| 1650 | assert(ssl->in_data_count == 0 && ssl->decrypting); |
| 1651 | new_app_input = false; |
| 1652 | size_t count; |
| 1653 | |
| 1654 | if (ssl->state != RUNNING) { |
| 1655 | count = _pni_min(ssl->sc_in_size - ssl->sc_in_count, available); |
| 1656 | } else { |
| 1657 | // look for TLS record boundaries |
| 1658 | if (ssl->sc_in_count < 5) { |
| 1659 | ssl->sc_in_incomplete = true; |
| 1660 | size_t hc = _pni_min(available, 5 - ssl->sc_in_count); |
| 1661 | memmove(ssl->sc_inbuf + ssl->sc_in_count, input_data, hc); |
| 1662 | ssl->sc_in_count += hc; |
| 1663 | input_data += hc; |
| 1664 | available -= hc; |
| 1665 | consumed += hc; |
| 1666 | if (ssl->sc_in_count < 5 || available == 0) |
| 1667 | break; |
| 1668 | } |
| 1669 | |
| 1670 | // Top up sc_inbuf from network input_data hoping for a complete TLS Record |
| 1671 | // We try to guess the length as an optimization, but let SChannel |
| 1672 | // ultimately decide if there is spoofing going on. |
| 1673 | unsigned char low = (unsigned char) ssl->sc_inbuf[4]; |
| 1674 | unsigned char high = (unsigned char) ssl->sc_inbuf[3]; |
| 1675 | size_t rec_len = high * 256 + low + 5; |
| 1676 | if (rec_len < 5 || rec_len == ssl->sc_in_count || rec_len > ssl->sc_in_size) |
| 1677 | rec_len = ssl->sc_in_size; |
| 1678 | |
| 1679 | count = _pni_min(rec_len - ssl->sc_in_count, available); |
| 1680 | } |
| 1681 | |
| 1682 | if (count > 0) { |
| 1683 | memmove(ssl->sc_inbuf + ssl->sc_in_count, input_data, count); |
| 1684 | ssl->sc_in_count += count; |
nothing calls this directly
no test coverage detected