0

I am working on using SChannel to build a client/server program. One of the things I would like to do is have file sharing. I found some example code of a client program using Schannel to communicate and I am wondering why the max size of a message is 32kb. Here is the example function that does the receiving

int tls_handshake(tls_ctx *c, tls_session *s) {
    DWORD         flags_in, flags_out;
    SecBuffer     ib[2], ob[1];
    SecBufferDesc in, out;
    int           len;

    // send initial hello
    if (!tls_hello(c, s)) {
      return 0;
    }

    flags_in = ISC_REQ_REPLAY_DETECT   |
               ISC_REQ_CONFIDENTIALITY |
               ISC_RET_EXTENDED_ERROR  |
               ISC_REQ_ALLOCATE_MEMORY |
               ISC_REQ_MANUAL_CRED_VALIDATION;

    c->ss     = SEC_I_CONTINUE_NEEDED;
    s->buflen = 0;

    while (c->ss == SEC_I_CONTINUE_NEEDED ||
           c->ss == SEC_E_INCOMPLETE_MESSAGE ||
           c->ss == SEC_I_INCOMPLETE_CREDENTIALS)
    {
      if (c->ss  == SEC_E_INCOMPLETE_MESSAGE)
      {
        // receive data from server
        len = recv(s->sck, &s->buf[s->buflen], s->maxlen - s->buflen, 0);

        // socket error?
        if (len  == SOCKET_ERROR) {
          c->ss  =  SEC_E_INTERNAL_ERROR;
          break;
        // server disconnected?
        } else if (len==0) {
          c->ss = SEC_E_INTERNAL_ERROR;
          break;
        }
        // increase buffer position
        s->buflen += len;
      }

      // inspect what we've received
      //tls_hex_dump(s->buf, s->buflen);

      // input data
      ib[0].pvBuffer   = s->buf;
      ib[0].cbBuffer   = s->buflen;
      ib[0].BufferType = SECBUFFER_TOKEN;

      // empty buffer
      ib[1].pvBuffer   = NULL;
      ib[1].cbBuffer   = 0;
      ib[1].BufferType = SECBUFFER_VERSION;

      in.cBuffers      = 2;
      in.pBuffers      = ib;
      in.ulVersion     = SECBUFFER_VERSION;

      // output from schannel
      ob[0].pvBuffer   = NULL;
      ob[0].cbBuffer   = 0;
      ob[0].BufferType = SECBUFFER_VERSION;

      out.cBuffers     = 1;
      out.pBuffers     = ob;
      out.ulVersion    = SECBUFFER_VERSION;

      c->ss = c->sspi->
        InitializeSecurityContextA(
        &s->cc, &s->ctx, NULL, flags_in, 0,
        SECURITY_NATIVE_DREP, &in, 0, NULL,
        &out, &flags_out, NULL);

      // what have we got so far?
      if (c->ss == SEC_E_OK ||
          c->ss == SEC_I_CONTINUE_NEEDED ||
          (FAILED(c->ss) && (flags_out & ISC_RET_EXTENDED_ERROR)))
      {
        // response for server?
        if (ob[0].cbBuffer != 0 && ob[0].pvBuffer) {
          // send response
          tls_send(s->sck, ob[0].pvBuffer, ob[0].cbBuffer);
          // free response
          c->sspi->FreeContextBuffer(ob[0].pvBuffer);
          ob[0].pvBuffer = NULL;
        }
      }
      // incomplete message? continue reading
      if (c->ss==SEC_E_INCOMPLETE_MESSAGE) continue;

      // completed handshake?
      if (c->ss==SEC_E_OK) {
        s->established = 1;

        // If the "extra" buffer contains data, this is encrypted application
        // protocol layer stuff and needs to be saved. The application layer
        // will decrypt it later with DecryptMessage.
        if (ib[1].BufferType == SECBUFFER_EXTRA) {
          DEBUG_PRINT("  [ we have extra data after handshake.\n");
          memmove(s->pExtra.pvBuffer,
              &s->buf[(s->buflen - ib[1].cbBuffer)], ib[1].cbBuffer);

          s->pExtra.cbBuffer   = ib[1].cbBuffer;
          s->pExtra.BufferType = SECBUFFER_TOKEN;
        } else {
          // no extra data encountered
          s->pExtra.pvBuffer   = NULL;
          s->pExtra.cbBuffer   = 0;
          s->pExtra.BufferType = SECBUFFER_EMPTY;
        }
        break;
      }
      // some other error
      if(FAILED(c->ss)) break;

      // Copy any leftover data from the "extra" buffer, and go around again.
      if(ib[1].BufferType == SECBUFFER_EXTRA) {
        memmove(s->buf, &s->buf[(s->buflen - ib[1].cbBuffer)], ib[1].cbBuffer);
        s->buflen = ib[1].cbBuffer;
        DEBUG_PRINT("  [ we have %i bytes of extra data.\n", s->buflen);

        tls_hex_dump(s->buf, s->buflen);

      } else {
        s->buflen = 0;
      }
    }
    return c->ss==SEC_E_OK ? 1 : 0;
}

The code comes from a Github I found here: https://github.com/odzhan/shells/blob/master/s6/tls.c

Inside one of his header files he defines

#define TLS_MAX_BUFSIZ      32768

I have also read in other places that this is a limit with TLS. Is it possible to increase that limit? What happens if I need to receive more then that? Like a large file?

Halloween
  • 388
  • 3
  • 15
  • All TCP based protocols (which includes TLS) are frame-based: whatever amount of data you have, it is split into a given number of packets, so that virtually you can send an infinite amount of data, and nothing changes based on the size of each individual packets (performance aside). TLS 1.3 says "The record layer fragments information blocks into TLSPlaintext records carrying data in chunks of 2^14 bytes or less." – Patrick Mevzek Feb 28 '20 at 15:16
  • How do I read the correct about of bytes of a packet that I send? Normally in my packet I would have a length in it. But since this is calling recv and the data is encrypted it wouldn't know how much to recv. – Halloween Feb 28 '20 at 22:21

0 Answers0