Start porting the C to the Python 3 APIs
diff --git a/OpenSSL/crypto/crypto.c b/OpenSSL/crypto/crypto.c
index d9f1a4e..d71e3ec 100644
--- a/OpenSSL/crypto/crypto.c
+++ b/OpenSSL/crypto/crypto.c
@@ -36,15 +36,15 @@
     Py_DECREF(argv);
     if (ret == NULL)
         return 0;
-    if (!PyString_Check(ret))
+    if (!PyBytes_Check(ret))
     {
         PyErr_SetString(PyExc_ValueError, "String expected");
         return 0;
     }
-    nchars = PyString_Size(ret);
+    nchars = PyBytes_Size(ret);
     if (nchars > len)
         nchars = len;
-    strncpy(buf, PyString_AsString(ret), nchars);
+    strncpy(buf, PyBytes_AsString(ret), nchars);
     return nchars;
 }
 
@@ -77,10 +77,10 @@
 
     if (pw != NULL)
     {
-        if (PyString_Check(pw))
+        if (PyBytes_Check(pw))
         {
             cb = NULL;
-            cb_arg = PyString_AsString(pw);
+            cb_arg = PyBytes_AsString(pw);
         }
         else if (PyCallable_Check(pw))
         {
@@ -167,10 +167,10 @@
             PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
             return NULL;
         }
-        if (PyString_Check(pw))
+        if (PyBytes_Check(pw))
         {
             cb = NULL;
-            cb_arg = PyString_AsString(pw);
+            cb_arg = PyBytes_AsString(pw);
         }
         else if (PyCallable_Check(pw))
         {
@@ -220,7 +220,7 @@
     }
 
     buf_len = BIO_get_mem_data(bio, &temp);
-    buffer = PyString_FromStringAndSize(temp, buf_len);
+    buffer = PyBytes_FromStringAndSize(temp, buf_len);
     BIO_free(bio);
 
     return buffer;
@@ -323,7 +323,7 @@
     }
 
     buf_len = BIO_get_mem_data(bio, &temp);
-    buffer = PyString_FromStringAndSize(temp, buf_len);
+    buffer = PyBytes_FromStringAndSize(temp, buf_len);
     BIO_free(bio);
 
     return buffer;
@@ -426,7 +426,7 @@
     }
 
     buf_len = BIO_get_mem_data(bio, &temp);
-    buffer = PyString_FromStringAndSize(temp, buf_len);
+    buffer = PyBytes_FromStringAndSize(temp, buf_len);
     BIO_free(bio);
 
     return buffer;
@@ -578,7 +578,7 @@
         return NULL;
 
     str = X509_verify_cert_error_string(errnum);
-    return PyString_FromString(str);
+    return PyText_FromString(str);
 }
 
 static char crypto_exception_from_error_queue_doc[] = "\n\
@@ -632,7 +632,7 @@
         return NULL;
     }
 
-    buffer = PyString_FromStringAndSize((char*)sig_buf, sig_len);
+    buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
     return buffer;
 }
 
@@ -772,6 +772,15 @@
 
 #endif
 
+#ifdef PY3
+static struct PyModuleDef cryptomodule = {
+    PyModuleDef_HEAD_INIT,
+    "crypto",
+    crypto_doc,
+    -1,
+    crypto_methods
+};
+#endif
 
 /*
  * Initialize crypto sub module
@@ -779,19 +788,27 @@
  * Arguments: None
  * Returns:   None
  */
-void
-initcrypto(void)
-{
+PyOpenSSL_MODINIT(crypto) {
+#ifndef PY3
     static void *crypto_API[crypto_API_pointers];
     PyObject *c_api_object;
+#endif
     PyObject *module;
 
     ERR_load_crypto_strings();
     OpenSSL_add_all_algorithms();
 
-    if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
-        return;
+#ifdef PY3
+    module = PyModule_Create(&cryptomodule);
+#else
+    module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
+#endif
 
+    if (module == NULL) {
+        return NULL;
+    }
+
+#ifndef PY3
     /* Initialize the C API pointer array */
     crypto_API[crypto_X509_New_NUM]      = (void *)crypto_X509_New;
     crypto_API[crypto_X509Name_New_NUM]  = (void *)crypto_X509Name_New;
@@ -804,6 +821,7 @@
     c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
     if (c_api_object != NULL)
         PyModule_AddObject(module, "_C_API", c_api_object);
+#endif
 
     crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
     if (crypto_Error == NULL)
@@ -844,6 +862,15 @@
         goto error;
     if (!init_crypto_revoked(module))
         goto error;
+
+#ifdef PY3
+    return module;
+#endif
+
 error:
+#ifdef PY3
+    return NULL;
+#else
     ;
+#endif
 }
diff --git a/OpenSSL/py3k.h b/OpenSSL/py3k.h
new file mode 100644
index 0000000..a9e8e5c
--- /dev/null
+++ b/OpenSSL/py3k.h
@@ -0,0 +1,34 @@
+#ifndef PyOpenSSL_PY3K_H_
+#define PyOpenSSL_PY3K_H_
+
+#if (PY_VERSION_HEX >= 0x03000000)
+
+#define PY3
+
+#define PyOpenSSL_MODINIT(name)                 \
+PyMODINIT_FUNC \
+PyInit_##name(void)
+
+#define PyText_FromString PyUnicode_FromString
+
+#else /* (PY_VERSION_HEX >= 0x03000000) */
+
+#define PyBytes_FromStringAndSize PyString_FromStringAndSize
+
+#define PyLong_FromLong PyInt_FromLong
+
+#define PyBytes_Size PyString_Size
+#define PyBytes_Check PyString_Check
+#define PyBytes_AsString PyString_AsString
+#define PyBytes_FromStringAndSize PyString_FromStringAndSize
+
+#define PyText_FromString PyString_FromString
+
+#define PyOpenSSL_MODINIT(name)
+void \
+init##name(void)
+
+#endif /* (PY_VERSION_HEX >= 0x03000000) */
+
+#endif /* PyOpenSSL_PY3K_H_ */
+
diff --git a/OpenSSL/rand/rand.c b/OpenSSL/rand/rand.c
index 1bf71b1..2f10e3b 100644
--- a/OpenSSL/rand/rand.c
+++ b/OpenSSL/rand/rand.c
@@ -230,7 +230,7 @@
         exception_from_error_queue(rand_Error);
         goto done;
     }
-    obj = PyString_FromStringAndSize(buf, (unsigned) num_bytes);
+    obj = PyBytes_FromStringAndSize(buf, (unsigned) num_bytes);
  done:
     free(buf);
     return obj;
@@ -254,28 +254,55 @@
 };
 
 
+#ifdef PY3
+static struct PyModuleDef randmodule = {
+    PyModuleDef_HEAD_INIT,
+    "rand",
+    rand_doc,
+    -1,
+    rand_methods
+};
+#endif
+
 /*
  * Initialize the rand sub module
  *
  * Arguments: None
  * Returns:   None
  */
-void
-initrand(void)
-{
+PyOpenSSL_MODINIT(rand) {
     PyObject *module;
 
+#ifdef PY3
+    module = PyModule_Create(&randmodule);
+#else
+    module = Py_InitModule3("rand", rand_methods, rand_doc);
+#endif
+    if (module == NULL) {
+        return NULL;
+    }
+
+    rand_Error = PyErr_NewException("OpenSSL.rand.Error", NULL, NULL);
+
+    if (rand_Error == NULL) {
+        goto error;
+    }
+
+    if (PyModule_AddObject(module, "Error", rand_Error) != 0) {
+        goto error;
+    }
+
     ERR_load_RAND_strings();
 
-    if ((module = Py_InitModule3("rand", rand_methods, rand_doc)) == NULL)
-        return;
+#ifdef PY3
+    return module;
+#endif
 
-    rand_Error = PyErr_NewException("OpenSSL.rand.Error", NULL, NULL);
-    if (rand_Error == NULL)
-        goto error;
-    if (PyModule_AddObject(module, "Error", rand_Error) != 0)
-        goto error;
- error:
+error:
+#ifdef PY3
+    return NULL;
+#else
     ;
+#endif
 }
 
diff --git a/OpenSSL/util.h b/OpenSSL/util.h
index d1157a7..73accbf 100644
--- a/OpenSSL/util.h
+++ b/OpenSSL/util.h
@@ -22,6 +22,12 @@
  */
 #include "pymemcompat.h"
 
+/*
+ * py3k defines macros that help with Python 2.x/3.x compatibility.
+ */
+#include "py3k.h"
+
+
 extern  PyObject *error_queue_to_list(void);
 extern void exception_from_error_queue(PyObject *the_Error);
 extern  void      flush_error_queue(void);