Tests for the error handling in the global passphrase callback
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index f613e7e..b4b33d2 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -99,19 +99,23 @@
         self.assertRaises(TypeError, ctx.use_privatekey, "")
 
 
+    def _write_encrypted_pem(self, passphrase):
+        key = PKey()
+        key.generate_key(TYPE_RSA, 128)
+        pemFile = self.mktemp()
+        fObj = file(pemFile, 'w')
+        fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
+        fObj.close()
+        return pemFile
+
+
     def test_set_passwd_cb(self):
         """
         L{Context.set_passwd_cb} accepts a callable which will be invoked when
         a private key is loaded from an encrypted PEM.
         """
-        key = PKey()
-        key.generate_key(TYPE_RSA, 128)
-        pemFile = self.mktemp()
-        fObj = file(pemFile, 'w')
         passphrase = "foobar"
-        fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
-        fObj.close()
-
+        pemFile = self._write_encrypted_pem(passphrase)
         calledWith = []
         def passphraseCallback(maxlen, verify, extra):
             calledWith.append((maxlen, verify, extra))
@@ -125,6 +129,67 @@
         self.assertEqual(calledWith[0][2], None)
 
 
+    def test_passwd_callback_exception(self):
+        """
+        L{Context.use_privatekey_file} propagates any exception raised by the
+        passphrase callback.
+        """
+        pemFile = self._write_encrypted_pem("monkeys are nice")
+        def passphraseCallback(maxlen, verify, extra):
+            raise RuntimeError("Sorry, I am a fail.")
+
+        context = Context(TLSv1_METHOD)
+        context.set_passwd_cb(passphraseCallback)
+        self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
+
+
+    def test_passwd_callback_false(self):
+        """
+        L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
+        passphrase callback returns a false value.
+        """
+        pemFile = self._write_encrypted_pem("monkeys are nice")
+        def passphraseCallback(maxlen, verify, extra):
+            return None
+
+        context = Context(TLSv1_METHOD)
+        context.set_passwd_cb(passphraseCallback)
+        self.assertRaises(Error, context.use_privatekey_file, pemFile)
+
+
+    def test_passwd_callback_non_string(self):
+        """
+        L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
+        passphrase callback returns a true non-string value.
+        """
+        pemFile = self._write_encrypted_pem("monkeys are nice")
+        def passphraseCallback(maxlen, verify, extra):
+            return 10
+
+        context = Context(TLSv1_METHOD)
+        context.set_passwd_cb(passphraseCallback)
+        self.assertRaises(Error, context.use_privatekey_file, pemFile)
+
+
+    def test_passwd_callback_too_long(self):
+        """
+        If the passphrase returned by the passphrase callback returns a string
+        longer than the indicated maximum length, it is truncated.
+        """
+        # A priori knowledge!
+        passphrase = "x" * 1024
+        pemFile = self._write_encrypted_pem(passphrase)
+        def passphraseCallback(maxlen, verify, extra):
+            assert maxlen == 1024
+            return passphrase + "y"
+
+        context = Context(TLSv1_METHOD)
+        context.set_passwd_cb(passphraseCallback)
+        # This shall succeed because the truncated result is the correct
+        # passphrase.
+        context.use_privatekey_file(pemFile)
+
+
     def test_set_info_callback(self):
         """
         L{Context.set_info_callback} accepts a callable which will be invoked