diff --git a/src/sbbs3/ssl.c b/src/sbbs3/ssl.c
new file mode 100644
index 0000000000000000000000000000000000000000..40987e5575897ff31a5fb39c360ab121ec6ff712
--- /dev/null
+++ b/src/sbbs3/ssl.c
@@ -0,0 +1,87 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include "ssl.h"
+#include "js_socket.h"	// TODO... move this stuff in here?
+
+static scfg_t	scfg;
+
+static bool get_error_string(int status, CRYPT_SESSION sess, char *estr, char *file, int line)
+{
+	int		ret;
+	int		len = 0;
+	char	tmpstr[CRYPT_MAX_TEXTSIZE+1];
+
+	if (cryptStatusOK(status))
+		return true;
+
+	ret = cryptGetAttributeString(sess, CRYPT_ATTRIBUTE_ERRORMESSAGE, tmpstr, &len);
+	estr[len]=0;
+	if (cryptStatusOK(ret) && len)
+		sprintf(estr, "cryptlib error %d at %s:%d (%s)", status, file, line, tmpstr);
+	else
+		sprintf(estr, "cryptlib error %d at %s:%d", status, file, line);
+	return false;
+}
+
+#define DO(x)	get_error_string(x, ssl_context, estr, __FILE__, __LINE__)
+
+CRYPT_CONTEXT get_ssl_cert(scfg_t *cfg, char *estr)
+{
+	CRYPT_KEYSET		ssl_keyset;
+	CRYPT_CONTEXT		ssl_context;
+	CRYPT_CERTIFICATE	ssl_cert;
+	int					i;
+	char				sysop_email[sizeof(cfg->sys_inetaddr)+6];
+    char				str[MAX_PATH+1];
+
+	if(!do_cryptInit())
+		return -1;
+	/* Get the certificate... first try loading it from a file... */
+	SAFEPRINTF2(str,"%s%s",cfg->ctrl_dir,"ssl.cert");
+	if(cryptStatusOK(cryptKeysetOpen(&ssl_keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, str, CRYPT_KEYOPT_NONE))) {
+		if(!DO(cryptGetPrivateKey(ssl_keyset, &ssl_context, CRYPT_KEYID_NAME, "ssl_cert", cfg->sys_pass)))
+			return -1;
+	}
+	else {
+		/* Couldn't do that... create a new context and use the cert from there... */
+		if(!cryptStatusOK(i=cryptCreateContext(&ssl_context, CRYPT_UNUSED, CRYPT_ALGO_RSA))) {
+			sprintf(estr, "cryptlib error %d creating SSL context",i);
+			return -1;
+		}
+		if(!DO(cryptSetAttributeString(ssl_context, CRYPT_CTXINFO_LABEL, "ssl_cert", 8)))
+			goto failure_return_1;
+		if(!DO(cryptGenerateKey(ssl_context)))
+			goto failure_return_1;
+		if(!DO(cryptKeysetOpen(&ssl_keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, str, CRYPT_KEYOPT_CREATE)))
+			goto failure_return_1;
+		if(!DO(cryptAddPrivateKey(ssl_keyset, ssl_context, cfg->sys_pass)))
+			goto failure_return_2;
+		if(!DO(cryptCreateCert(&ssl_cert, CRYPT_UNUSED, CRYPT_CERTTYPE_CERTIFICATE)))
+			goto failure_return_2;
+		if(!DO(cryptSetAttribute(ssl_cert, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, ssl_context)))
+			goto failure_return_3;
+		if(!DO(cryptSetAttribute(ssl_cert, CRYPT_CERTINFO_XYZZY, 1 )))
+			goto failure_return_3;
+		if(!DO(cryptSetAttributeString(ssl_cert, CRYPT_CERTINFO_COMMONNAME, cfg->sys_inetaddr, strlen(cfg->sys_inetaddr))))
+			goto failure_return_3;
+		sprintf(sysop_email, "sysop@%s", scfg.sys_inetaddr);
+		if(!DO(cryptSetAttributeString(ssl_cert, CRYPT_CERTINFO_RFC822NAME, cfg->sys_inetaddr, strlen(cfg->sys_inetaddr))))
+			goto failure_return_3;
+		if(!DO(cryptSignCert(ssl_cert, ssl_context)))
+			goto failure_return_3;
+		if(!DO(cryptAddPublicKey(ssl_keyset, ssl_cert)))
+			goto failure_return_3;
+		cryptDestroyCert(ssl_cert);
+	}
+
+	cryptKeysetClose(ssl_keyset);
+	return ssl_context;
+
+failure_return_3:
+	cryptDestroyCert(ssl_cert);
+failure_return_2:
+	cryptKeysetClose(ssl_keyset);
+failure_return_1:
+	cryptDestroyContext(ssl_context);
+	return -1;
+}
diff --git a/src/sbbs3/ssl.h b/src/sbbs3/ssl.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b4a9bfd81be1f5ee4f9b2f8a677b3d2d5bc6c84
--- /dev/null
+++ b/src/sbbs3/ssl.h
@@ -0,0 +1,11 @@
+#ifndef SBBS_SSL_H
+#define SBBS_SSL_H
+
+#include <cryptlib.h>
+#include "scfgdefs.h"
+
+#define SSL_ESTR_LEN	CRYPT_MAX_TEXTSIZE + 1024 /* File name, line number, status code, and some static text */
+
+CRYPT_CONTEXT get_ssl_cert(scfg_t *cfg, char *estr);
+
+#endif