Add OpenSSL.rand.bytes() function to wrap RAND_bytes().  Test cases and documentation included.
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..63af700
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,17 @@
+
+Only the .tex format documentation is original,
+because the others are derived from it, so don't
+edit them directly.  To build the other formats
+use a command of ...
+
+  make all
+
+
+To build the documentation you will need to have
+latex2html and lynx installed.  On fedora both can
+be obtained with...
+
+  sudo yum install latex2html lynx
+
+
+
diff --git a/doc/pyOpenSSL.tex b/doc/pyOpenSSL.tex
index cf69e0f..9f472b9 100644
--- a/doc/pyOpenSSL.tex
+++ b/doc/pyOpenSSL.tex
@@ -593,6 +593,10 @@
 \var{string}, measured in bytes. For more information, see e.g. \rfc{1750}.
 \end{funcdesc}
 
+\begin{funcdesc}{cleanup}{}
+Erase the memory used by the PRNG.  It's a wrapper of the C function \function{RAND_cleanup}.
+\end{funcdesc}
+
 \begin{funcdesc}{egd}{path\optional{, bytes}}
 Query the Entropy Gathering Daemon\footnote{See
 \url{http://www.lothar.com/tech/crypto/}} on socket \var{path} for \var{bytes}
@@ -605,6 +609,10 @@
 the file \var{path} to seed the PRNG. The default value of \var{bytes} is -1.
 \end{funcdesc}
 
+\begin{funcdesc}{bytes}{num_bytes}
+Get some random bytes as a string.  It's a wrapper of the C function \function{RAND_bytes}.
+\end{funcdesc}
+
 \begin{funcdesc}{screen}{}
 Add the current contents of the screen to the PRNG state.
 Availability: Windows.
diff --git a/setup.py b/setup.py
index 645e459..06d477b 100755
--- a/setup.py
+++ b/setup.py
@@ -88,6 +88,7 @@
                      'OpenSSL.version', 'OpenSSL.test.__init__',
                      'OpenSSL.test.util',
                      'OpenSSL.test.test_crypto',
+                     'OpenSSL.test.test_rand',
                      'OpenSSL.test.test_ssl'],
       data_files = data_files,
       description = 'Python wrapper module around the OpenSSL library',
diff --git a/src/rand/rand.c b/src/rand/rand.c
index f1c8440..cdb83bb 100644
--- a/src/rand/rand.c
+++ b/src/rand/rand.c
@@ -188,6 +188,36 @@
     return PyInt_FromLong((long)RAND_write_file(filename));
 }
 
+static char rand_bytes_doc[] = "\n\
+Get some randomm bytes as a string.\n\
+\n\
+@param num_bytes: The number of bytes to fetch\n\
+@return: A string of random bytes\n\
+";
+
+static PyObject *
+rand_bytes(PyObject *spam, PyObject *args, PyObject *keywds)
+{
+    int num_bytes;
+    static char *kwlist[] = {"num_bytes", NULL};
+    char *buf;
+    PyObject *obj;
+
+    if (!PyArg_ParseTupleAndKeywords(args, keywds, "i:bytes", kwlist, &num_bytes))
+        return NULL;
+    if(num_bytes < 0) {
+        PyErr_SetString(PyExc_ValueError, "num_bytes must not be negative");
+        return NULL;
+    }
+    buf = malloc(num_bytes);
+    if (buf == NULL)   /* out of memory  */
+        return NULL;
+    RAND_bytes(buf, num_bytes);
+    obj = PyString_FromStringAndSize(buf, num_bytes);
+    free(buf);
+    return obj;
+}
+
 
 /* Methods in the OpenSSL.rand module */
 static PyMethodDef rand_methods[] = {
@@ -201,6 +231,7 @@
     { "cleanup",   (PyCFunction)rand_cleanup,      METH_VARARGS, rand_cleanup_doc },
     { "load_file", (PyCFunction)rand_load_file,    METH_VARARGS, rand_load_file_doc },
     { "write_file",(PyCFunction)rand_write_file,   METH_VARARGS, rand_write_file_doc },
+    { "bytes",     (PyCFunction)rand_bytes,        METH_VARARGS|METH_KEYWORDS, rand_bytes_doc },
     { NULL, NULL }
 };
 
diff --git a/test/test_rand.py b/test/test_rand.py
new file mode 100644
index 0000000..fe10ab9
--- /dev/null
+++ b/test/test_rand.py
@@ -0,0 +1,63 @@
+# Copyright (C) Frederick Dean 2009, All rights reserved
+
+"""
+Unit tests for L{OpenSSL.rand}.
+"""
+
+from unittest import main
+import os 
+import stat
+
+from OpenSSL.test.util import TestCase
+from OpenSSL import rand
+
+class RandTests(TestCase):
+    def test_bytes(self):
+        """
+        Verify that we can obtain bytes from rand_bytes() and
+        that they are different each time.  Test the parameter
+        of rand_bytes() for bad values.
+        """
+        b1 = rand.bytes(50)
+        self.assertEqual(len(b1), 50)
+        b2 = rand.bytes(num_bytes=50)  # parameter by name
+        self.assertNotEqual(b1, b2)  #  Hip, Hip, Horay! FIPS complaince
+        b3 = rand.bytes(num_bytes=0) 
+        self.assertEqual(len(b3), 0)
+        try:
+            b4 = rand.bytes(-1) 
+            self.assertTrue(False)  # We shouldn't get here
+        except ValueError, v:
+            self.assertTrue(v.message == "num_bytes must not be negative")
+
+
+    def test_add(self):
+        """
+        Test adding of entropy to the PRNG.
+        """
+        rand.add('hamburger', 3)
+        rand.seed('milk shake')
+        self.assertTrue(rand.status())
+
+
+    def test_files(self):
+        """
+        Test reading and writing of files via rand functions.
+        """
+        # Write random bytes to a file 
+        tmpfile = self.mktemp()
+        rand.write_file(tmpfile)
+        # Verify length of written file
+        size = os.stat(tmpfile)[stat.ST_SIZE]
+        self.assertEquals(size, 1024)
+        # Read random bytes from file 
+        rand.load_file(tmpfile)
+        rand.load_file(tmpfile, 4)  # specify a length
+        # Cleanup
+        os.unlink(tmpfile)
+
+
+if __name__ == '__main__':
+    main()
+
+