Secure Oldies V: Windows 3.x and Winsock 1.1

Secure Oldies V: Windows 3.x and Winsock 1.1

How the oldest Microsoft 32-bit platform fare running modern TLS.

Despite the version numbering, Windows NT 3.1 is the first Windows NT released at 1993. Windows NT was the first 32-bit platform that Microsoft has free of legacy things like MS-DOS. It was complete rewrite rather than a refactor of the Windows they had before, Windows 3.1.

Porting to Windows NT 3.x

I hesitated to target this OS due to two things:

  1. I'm unsure about the compatibility of early Winsock version before Winsock 2.0.
  2. Windows NT 3.x has no CryptoAPI support which makes it lacks of cryptographically secure pseudo number generator. CryptoAPI support only available for Windows NT 4 and up.

However, I managed to compile it with some caveats

  1. It will use Winsock 1.x which is only available for TCP/IP.
  2. It won't be secure, as I'll use garbage memory from calling malloc, which I think is not random enough. But I'll use it as entropy source.
  3. Only support Windows 3.51 and up.

Warning: this port is not secure, and I advised strongly not to use this other than for entertainment and educational purposes

Step 1: Turn off platform entropy source

Because mbedTLS is so portable, it also allows us to supply any custom entropy source. To avoid linking to CryptoAPI we'd need to turn off platform entropy source by opening mbedtls_config.h. Find a definition of MBEDTLS_NO_PLATFORM_ENTROPY and uncomment that line this will turn off platform entropy based on CryptoAPI.

/**
 * \def MBEDTLS_NO_PLATFORM_ENTROPY
 *
 * Do not use built-in platform entropy functions.
 * This is useful if your platform does not support
 * standards like the /dev/urandom or Windows CryptoAPI.
 *
 * Uncomment this macro to disable the built-in platform entropy functions.
 */
#define MBEDTLS_NO_PLATFORM_ENTROPY

If we recompile this binary, the result will be error -0x34 which weans that entropy doesn't work.

We'd need to somehow supply an entropy based on the fact that if we do malloc, it'll allocate a memory region filled with garbage and then we tell mbedTLS that this is a strong entropy source (which is not), otherwise mbedTLS will refuse to work.

static int weak_entropy_source_cb(void *data, unsigned char *output, size_t len, size_t *olen) {
  unsigned char *garbage = (unsigned char *) malloc(len);
  *olen = len; 

  memcpy(output, garbage, len);

  free(garbage);
  return 0;
}

and then add it before call to setup DRBG

mbedtls_entropy_add_source(&entropy, 
      weak_entropy_source_cb, 
      NULL, 
      16, 
      MBEDTLS_ENTROPY_SOURCE_STRONG); // we're clearly lying

Try to compile if that's succeeded then we move to the next step by downgrading Winsock to Winsock 1.x.

Step 2: Downgrade Winsock to Winsock 1.x

This is a easy, we just change the code for WSAStartup() to:

WSADATA wsa;
return WSAStartup(MAKEWORD(1, 1), &wsa);

And then alter the line from CMakeLists.txt to link to wsock32 rather than ws2_32.

if (WIN32)
  target_link_libraries(binfetch PUBLIC wsock32)
endif (WIN32)

And then change the include by removing winsock2.h and replace it with plain old' winsock.h.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock.h>

Testing

Recompile and rejoice!

Running TLS 1.2 HTTP client on Windows NT 3.51 on top of Intel 486