diff options
author | Rob Austein <sra@hactrn.net> | 2016-08-10 12:38:36 -0400 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2016-08-10 12:38:36 -0400 |
commit | 133bb3907f478e3ccc1dc8f8fb15e924f37a0d97 (patch) | |
tree | f9437453bd8b7ba33c20982e227a4ba59eaa5d8d | |
parent | 9cfb3fbc22f3e79ec16a037e2c3140cd9c7c634c (diff) |
Add regression test for borked or missing PKCS #1.5 DigestInfo.
Oleg found a cute bug where C_SignUpdate() and C_SignFinal() would
generate an incorrect signature which C_VerifyUpdate() and
C_VerifyFinal() would think was fine because the verification code had
essentially the same bug as the signature code. None of this applied
to the (much) more commonly used C_Sign() and C_Verify() functions,
which is why nobody noticed until now.
Bug fixed in sw/libhal commit 36dfaf0adbddbb9f1f7852911228b3ab24ba01aa
but we need a regression test to make sure we don't reintroduce the
bug. So we add a test which computes the signature both ways, then
verifies it with PyCrypto as well as both ways with our own code.
We should probably be doing more comparisons of RSA results with
PyCrypto. For ECDSA with non-deterministic signatures it's a bit
harder, but more checking against the Python ecdsa library would still
be a good idea.
-rw-r--r-- | unit_tests.py | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/unit_tests.py b/unit_tests.py index fb8446f..c9d3886 100644 --- a/unit_tests.py +++ b/unit_tests.py @@ -13,8 +13,10 @@ from py11 import * from py11.mutex import MutexDB try: - from Crypto.Util.number import inverse - from Crypto.PublicKey import RSA + from Crypto.Util.number import inverse + from Crypto.PublicKey import RSA + from Crypto.Signature import PKCS1_v1_5 + from Crypto.Hash import SHA256 pycrypto_loaded = True except ImportError: pycrypto_loaded = False @@ -560,6 +562,34 @@ class TestKeys(TestCase): p11.C_VerifyInit(self.session, CKM_SHA512_RSA_PKCS, public_key) p11.C_Verify(self.session, hamster, sig) + @unittest.skipUnless(pycrypto_loaded, "requires PyCrypto") + def test_load_sign_verify_rsa_1024_with_rpki_data(self): + "Load/sign/verify with RSA-1024-SHA-256, externally-supplied key" + public_key, private_key = self._load_rsa_keypair(rsa_1024_pem, "RSA-1024") + tbs = ''' + 31 6B 30 1A 06 09 2A 86 48 86 F7 0D 01 09 03 31 + 0D 06 0B 2A 86 48 86 F7 0D 01 09 10 01 1A 30 1C + 06 09 2A 86 48 86 F7 0D 01 09 05 31 0F 17 0D 31 + 36 30 37 31 36 30 39 35 32 35 37 5A 30 2F 06 09 + 2A 86 48 86 F7 0D 01 09 04 31 22 04 20 11 A2 E6 + 0F 1F 86 AF 45 25 4D 8F E1 1F C9 EA B3 83 4A 41 + 17 C1 42 B7 43 AD 51 5E F5 A2 F8 E3 25 + ''' + tbs = "".join(chr(int(i, 16)) for i in tbs.split()) + p11.C_SignInit(self.session, CKM_SHA256_RSA_PKCS, private_key) + p11.C_SignUpdate(self.session, tbs) + sig = p11.C_SignFinal(self.session) + self.assertIsInstance(sig, str) + p11.C_VerifyInit(self.session, CKM_SHA256_RSA_PKCS, public_key) + p11.C_Verify(self.session, tbs, sig) + verifier = PKCS1_v1_5.new(RSA.importKey(rsa_1024_pem)) + digest = SHA256.new(tbs) + self.assertTrue(verifier.verify(digest, sig)) + p11.C_SignInit(self.session, CKM_SHA256_RSA_PKCS, private_key) + self.assertEqual(sig, p11.C_Sign(self.session, tbs)) + p11.C_VerifyInit(self.session, CKM_SHA256_RSA_PKCS, public_key) + p11.C_VerifyUpdate(self.session, tbs) + p11.C_VerifyFinal(self.session, sig) # Keys for preload tests, here rather than inline because they're # bulky. These are in PKCS #8 format, see PyCrypto or the "pkey" and |