From 8e6ce97e2d8a7d142d03b5b877575e75fd2074ef Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 13 May 2009 12:32:49 -0400 Subject: Apply pyOpenSSL_rsa_check.diff --- OpenSSL/crypto/pkey.c | 34 ++++++++++++++++++++++++++++++++++ OpenSSL/test/test_crypto.py | 3 +++ 2 files changed, 37 insertions(+) diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c index 0a13aa3..cfedfda 100644 --- a/OpenSSL/crypto/pkey.c +++ b/OpenSSL/crypto/pkey.c @@ -107,6 +107,39 @@ crypto_PKey_type(crypto_PKeyObj *self, PyObject *args) return PyLong_FromLong(self->pkey->type); } +static char crypto_PKey_check_doc[] = "\n\ +Check the consistency of an RSA private key.\n\ +\n\ +Arguments: self - The PKey object\n\ + args - The Python argument tuple, should be empty\n\ +Returns: True if key is consistent. False if not.\n\ +"; + +static PyObject * +crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) +{ + int r; + EVP_PKEY *pkey; + + if (!PyArg_ParseTuple(args, ":check")) + return NULL; + pkey = self->pkey; + if(pkey == NULL) + return NULL; + + if(pkey->type == EVP_PKEY_RSA) { + RSA *rsa; + rsa = EVP_PKEY_get1_RSA(pkey); + r = RSA_check_key(rsa); + if (r == 1) + return PyInt_FromLong(1L); + else + return PyInt_FromLong(0L); + } else { + PyErr_SetString( PyExc_TypeError, "key type unsupported"); + return NULL; + } +} /* * ADD_METHOD(name) expands to a correct PyMethodDef declaration @@ -120,6 +153,7 @@ static PyMethodDef crypto_PKey_methods[] = ADD_METHOD(generate_key), ADD_METHOD(bits), ADD_METHOD(type), + ADD_METHOD(check), { NULL, NULL } }; #undef ADD_METHOD diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py index 71da5c3..6c0ee31 100644 --- a/OpenSSL/test/test_crypto.py +++ b/OpenSSL/test/test_crypto.py @@ -564,6 +564,7 @@ class PKeyTests(TestCase): key.generate_key(TYPE_RSA, bits) self.assertEqual(key.type(), TYPE_RSA) self.assertEqual(key.bits(), bits) + self.assertTrue(key.check()) def test_dsaGeneration(self): @@ -579,6 +580,7 @@ class PKeyTests(TestCase): key.generate_key(TYPE_DSA, bits) self.assertEqual(key.type(), TYPE_DSA) self.assertEqual(key.bits(), bits) + self.assertRaises(TypeError, key.check) def test_regeneration(self): @@ -2077,6 +2079,7 @@ class FunctionTests(TestCase): L{dump_privatekey} writes a PEM, DER, and text. """ key = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM) + self.assertTrue(key.check()) dumped_pem = dump_privatekey(FILETYPE_PEM, key) self.assertEqual(dumped_pem, cleartextPrivateKeyPEM) dumped_der = dump_privatekey(FILETYPE_ASN1, key) -- cgit v1.2.1 From 55ec1714c9e17f865d21416bca7522e44c16cd26 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 13 May 2009 14:14:30 -0400 Subject: test the negative path through PKeyType.check --- OpenSSL/test/test_crypto.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py index 6c0ee31..a22ad12 100644 --- a/OpenSSL/test/test_crypto.py +++ b/OpenSSL/test/test_crypto.py @@ -207,6 +207,7 @@ MbzjS007Oe4qqBnCWaFPSnJX6uLApeTbqAxAeyCql56ULW5x6vDMNC3dwjvS/CEh 11n8RkgFIQA0AhuKSIg3CbuartRsJnWOLwgLTzsrKYL4yRog1RJrtw== -----END RSA PRIVATE KEY----- """) + encryptedPrivateKeyPEMPassphrase = b("foobar") # Some PKCS#7 stuff. Generated with the openssl command line: @@ -250,6 +251,21 @@ vrzEeLDRiiPl92dyyWmu -----END X509 CRL----- """) + +# A broken RSA private key which can be used to test the error path through +# PKey.check. +inconsistentPrivateKeyPEM = b("""-----BEGIN RSA PRIVATE KEY----- +MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh +5kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEaAQJBAIqm/bz4NA1H++Vx5Ewx +OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT +zIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4 +nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2 +HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNeH+vRWsAYU/gbx+OQB+7VOcBAiEA +oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w= +-----END RSA PRIVATE KEY----- +""") + + class X509ExtTests(TestCase): """ Tests for L{OpenSSL.crypto.X509Extension}. @@ -512,11 +528,13 @@ class PKeyTests(TestCase): def test_pregeneration(self): """ L{PKeyType.bits} and L{PKeyType.type} return C{0} before the key is + generated. L{PKeyType.check} raises L{TypeError} before the key is generated. """ key = PKey() self.assertEqual(key.type(), 0) self.assertEqual(key.bits(), 0) + self.assertRaises(TypeError, key.check) def test_failedGeneration(self): @@ -595,6 +613,13 @@ class PKeyTests(TestCase): self.assertEqual(key.bits(), bits) + def test_inconsistentKey(self): + """ + L{PKeyType.check} returns C{False} if the key is not consistent. + """ + key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM) + self.assertFalse(key.check()) + class X509NameTests(TestCase): """ -- cgit v1.2.1 From de207e77797b77c4703d5c9dd886a76b1964bde8 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 13 May 2009 14:19:05 -0400 Subject: self->pkey is always something --- OpenSSL/crypto/pkey.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c index cfedfda..e229757 100644 --- a/OpenSSL/crypto/pkey.c +++ b/OpenSSL/crypto/pkey.c @@ -123,13 +123,10 @@ crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) if (!PyArg_ParseTuple(args, ":check")) return NULL; - pkey = self->pkey; - if(pkey == NULL) - return NULL; - if(pkey->type == EVP_PKEY_RSA) { + if(self->pkey->type == EVP_PKEY_RSA) { RSA *rsa; - rsa = EVP_PKEY_get1_RSA(pkey); + rsa = EVP_PKEY_get1_RSA(self->pkey); r = RSA_check_key(rsa); if (r == 1) return PyInt_FromLong(1L); -- cgit v1.2.1 From 49f93ab110d88df63b52f98f682150683dd21015 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 13 May 2009 14:20:00 -0400 Subject: Remove now unused local; use bools for return value --- OpenSSL/crypto/pkey.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c index e229757..7d5c6a8 100644 --- a/OpenSSL/crypto/pkey.c +++ b/OpenSSL/crypto/pkey.c @@ -119,7 +119,6 @@ static PyObject * crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) { int r; - EVP_PKEY *pkey; if (!PyArg_ParseTuple(args, ":check")) return NULL; @@ -129,9 +128,9 @@ crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) rsa = EVP_PKEY_get1_RSA(self->pkey); r = RSA_check_key(rsa); if (r == 1) - return PyInt_FromLong(1L); + return PyBool_FromLong(1L); else - return PyInt_FromLong(0L); + return PyBool_FromLong(0L); } else { PyErr_SetString( PyExc_TypeError, "key type unsupported"); return NULL; -- cgit v1.2.1 From d338e4e2b7fc4605a98b87da97471c3966cd5293 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 13 May 2009 15:45:07 -0400 Subject: Switch from returning False to raising an Error if the key doesn't check out - this provides more information --- OpenSSL/crypto/pkey.c | 12 ++++++++---- OpenSSL/test/test_crypto.py | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c index 7d5c6a8..f037fd4 100644 --- a/OpenSSL/crypto/pkey.c +++ b/OpenSSL/crypto/pkey.c @@ -112,7 +112,10 @@ Check the consistency of an RSA private key.\n\ \n\ Arguments: self - The PKey object\n\ args - The Python argument tuple, should be empty\n\ -Returns: True if key is consistent. False if not.\n\ +Returns: True if key is consistent.\n\ +Raises: Error if the key is inconsistent.\n\ + TypeError if the key is of a type which cannot be checked. Only RSA\n\ + keys can currently be checked.\n\ "; static PyObject * @@ -127,10 +130,11 @@ crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) RSA *rsa; rsa = EVP_PKEY_get1_RSA(self->pkey); r = RSA_check_key(rsa); - if (r == 1) + if (r == 1) { return PyBool_FromLong(1L); - else - return PyBool_FromLong(0L); + } else { + FAIL(); + } } else { PyErr_SetString( PyExc_TypeError, "key type unsupported"); return NULL; diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py index a22ad12..cda0137 100644 --- a/OpenSSL/test/test_crypto.py +++ b/OpenSSL/test/test_crypto.py @@ -618,7 +618,7 @@ class PKeyTests(TestCase): L{PKeyType.check} returns C{False} if the key is not consistent. """ key = load_privatekey(FILETYPE_PEM, inconsistentPrivateKeyPEM) - self.assertFalse(key.check()) + self.assertRaises(Error, key.check) class X509NameTests(TestCase): -- cgit v1.2.1 From fd0b8d666e5fa9974844783e3a3f0a036233f221 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 12 Jun 2011 18:05:50 -0400 Subject: Doc changes, braces everywhere --- OpenSSL/crypto/pkey.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c index f037fd4..f56a26d 100644 --- a/OpenSSL/crypto/pkey.c +++ b/OpenSSL/crypto/pkey.c @@ -110,21 +110,19 @@ crypto_PKey_type(crypto_PKeyObj *self, PyObject *args) static char crypto_PKey_check_doc[] = "\n\ Check the consistency of an RSA private key.\n\ \n\ -Arguments: self - The PKey object\n\ - args - The Python argument tuple, should be empty\n\ -Returns: True if key is consistent.\n\ -Raises: Error if the key is inconsistent.\n\ - TypeError if the key is of a type which cannot be checked. Only RSA\n\ - keys can currently be checked.\n\ +@return: True if key is consistent.\n\ +@raise Error: if the key is inconsistent.\n\ +@raise TypeError: if the key is of a type which cannot be checked.\n\ + Only RSA keys can currently be checked.\n\ "; static PyObject * -crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) -{ +crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) { int r; - if (!PyArg_ParseTuple(args, ":check")) + if (!PyArg_ParseTuple(args, ":check")) { return NULL; + } if(self->pkey->type == EVP_PKEY_RSA) { RSA *rsa; @@ -136,7 +134,7 @@ crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) FAIL(); } } else { - PyErr_SetString( PyExc_TypeError, "key type unsupported"); + PyErr_SetString(PyExc_TypeError, "key type unsupported"); return NULL; } } -- cgit v1.2.1 From 13788530b7ad18b1d648415f0296521042a8a66e Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 12 Jun 2011 18:06:51 -0400 Subject: tex docs --- doc/pyOpenSSL.tex | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/pyOpenSSL.tex b/doc/pyOpenSSL.tex index 4e00c14..6a49748 100644 --- a/doc/pyOpenSSL.tex +++ b/doc/pyOpenSSL.tex @@ -555,6 +555,12 @@ Generate a public/private key pair of the type \var{type} (one of Return the type of the key. \end{methoddesc} +\begin{methoddesc}[PKey]{check}{} +Check the consistency of this key, returning True if it is consistent and +raising an exception otherwise. This is only valid for RSA keys. See the +OpenSSL RSA_check_key man page for further limitations. +\end{methoddesc} + \subsubsection{PKCS7 objects \label{openssl-pkcs7}} PKCS7 objects have the following methods: -- cgit v1.2.1 From 7d74854a2765970ff35f1e462cb2b5044d4bd77b Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 12 Jun 2011 18:10:01 -0400 Subject: whitespace --- OpenSSL/crypto/pkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c index f56a26d..1f78682 100644 --- a/OpenSSL/crypto/pkey.c +++ b/OpenSSL/crypto/pkey.c @@ -124,7 +124,7 @@ crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) { return NULL; } - if(self->pkey->type == EVP_PKEY_RSA) { + if (self->pkey->type == EVP_PKEY_RSA) { RSA *rsa; rsa = EVP_PKEY_get1_RSA(self->pkey); r = RSA_check_key(rsa); -- cgit v1.2.1 From e81020e6e20988d97f1b7ad0f0d493b40a24dd09 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 12 Jun 2011 21:48:57 -0400 Subject: test bad args case of PKey.check --- OpenSSL/test/test_crypto.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py index cda0137..5cdcefb 100644 --- a/OpenSSL/test/test_crypto.py +++ b/OpenSSL/test/test_crypto.py @@ -621,6 +621,16 @@ class PKeyTests(TestCase): self.assertRaises(Error, key.check) + def test_check_wrong_args(self): + """ + L{PKeyType.check} raises L{TypeError} if called with any arguments. + """ + self.assertRaises(TypeError, PKey().check, None) + self.assertRaises(TypeError, PKey().check, object()) + self.assertRaises(TypeError, PKey().check, 1) + + + class X509NameTests(TestCase): """ Unit tests for L{OpenSSL.crypto.X509Name}. -- cgit v1.2.1