Skip to content

Commit f1e0be6

Browse files
committed
test coverage for malformed PKCS files
1 parent 81d057d commit f1e0be6

File tree

1 file changed

+366
-0
lines changed

1 file changed

+366
-0
lines changed

tests/test_pkcs.py

Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55

66
try:
77
from ecdsa.der import unpem
8+
from ecdsa import der
89
from kyber_py.ml_kem.pkcs import (
910
ek_to_pem,
1011
ek_from_pem,
12+
ek_from_der,
1113
dk_to_pem,
1214
dk_from_pem,
15+
dk_from_der,
1316
)
1417

1518
ECDSA_PRESENT = True
@@ -615,3 +618,366 @@ def setUpClass(cls):
615618
uYOILhF1
616619
-----END PUBLIC KEY-----
617620
"""
621+
622+
623+
@unittest.skipUnless(ECDSA_PRESENT, "requires ecdsa package")
624+
class TestMalfomedKeys(unittest.TestCase):
625+
@classmethod
626+
def setUpClass(cls):
627+
cls.kem = ML_KEM_512
628+
cls.seed = bytes(64)
629+
cls.ek, cls.dk = cls.kem.key_derive(cls.seed)
630+
631+
def test_ek_sanity_check(self):
632+
enc = der.encode_sequence(
633+
der.encode_sequence(
634+
der.encode_oid(*self.kem.oid),
635+
),
636+
der.encode_bitstring(self.ek, 0),
637+
)
638+
639+
kem, key = ek_from_der(enc)
640+
641+
self.assertEqual(kem, self.kem)
642+
self.assertEqual(key, self.ek)
643+
644+
def test_ek_trailing_junk_after_pub_key(self):
645+
enc = der.encode_sequence(
646+
der.encode_sequence(
647+
der.encode_oid(*self.kem.oid),
648+
),
649+
der.encode_bitstring(self.ek, 0),
650+
) + b'\x00'
651+
652+
with self.assertRaises(der.UnexpectedDER) as e:
653+
ek_from_der(enc)
654+
655+
self.assertIn("Trailing junk after DER public key", str(e.exception))
656+
657+
def test_ek_wrong_oid(self):
658+
enc = der.encode_sequence(
659+
der.encode_sequence(
660+
der.encode_oid(1, 2, 3, 4),
661+
),
662+
der.encode_bitstring(self.ek, 0),
663+
)
664+
665+
with self.assertRaises(der.UnexpectedDER) as e:
666+
ek_from_der(enc)
667+
668+
self.assertIn("Not recognised algoritm OID: (1, 2, 3, 4)",
669+
str(e.exception))
670+
671+
def test_ek_parameters_in_alg_id(self):
672+
enc = der.encode_sequence(
673+
der.encode_sequence(
674+
der.encode_oid(*self.kem.oid),
675+
der.encode_sequence(),
676+
),
677+
der.encode_bitstring(self.ek, 0),
678+
)
679+
680+
with self.assertRaises(der.UnexpectedDER) as e:
681+
ek_from_der(enc)
682+
683+
self.assertIn("Parameters specified for ML-KEM OID",
684+
str(e.exception))
685+
686+
def test_ek_junk_after_public_key(self):
687+
enc = der.encode_sequence(
688+
der.encode_sequence(
689+
der.encode_oid(*self.kem.oid),
690+
),
691+
der.encode_bitstring(self.ek, 0),
692+
der.encode_integer(2),
693+
)
694+
695+
with self.assertRaises(der.UnexpectedDER) as e:
696+
ek_from_der(enc)
697+
698+
self.assertIn("Trailing junk after public key bitsting",
699+
str(e.exception))
700+
701+
def test_ek_unexpected_size_of_key(self):
702+
enc = der.encode_sequence(
703+
der.encode_sequence(
704+
der.encode_oid(*self.kem.oid),
705+
),
706+
der.encode_bitstring(self.ek + b'\x00', 0),
707+
)
708+
709+
with self.assertRaises(der.UnexpectedDER) as e:
710+
ek_from_der(enc)
711+
712+
self.assertIn("Wrong key size for the OID in structure",
713+
str(e.exception))
714+
715+
def test_dk_sanity_both(self):
716+
enc = der.encode_sequence(
717+
der.encode_integer(0),
718+
der.encode_sequence(
719+
der.encode_oid(*self.kem.oid),
720+
),
721+
der.encode_octet_string(
722+
der.encode_sequence(
723+
der.encode_octet_string(self.seed),
724+
der.encode_octet_string(self.dk),
725+
),
726+
),
727+
)
728+
729+
kem, expanded, seed, ek = dk_from_der(enc)
730+
731+
self.assertEqual(self.kem, kem)
732+
self.assertEqual(self.dk, expanded)
733+
self.assertEqual(self.seed, seed)
734+
self.assertEqual(self.ek, ek)
735+
736+
def test_dk_sanity_seed(self):
737+
enc = der.encode_sequence(
738+
der.encode_integer(0),
739+
der.encode_sequence(
740+
der.encode_oid(*self.kem.oid),
741+
),
742+
der.encode_octet_string(
743+
der.encode_implicit(0, self.seed),
744+
),
745+
)
746+
747+
kem, expanded, seed, ek = dk_from_der(enc)
748+
749+
self.assertEqual(self.kem, kem)
750+
self.assertEqual(self.dk, expanded)
751+
self.assertEqual(self.seed, seed)
752+
self.assertEqual(self.ek, ek)
753+
754+
def test_dk_sanity_expanded_only(self):
755+
enc = der.encode_sequence(
756+
der.encode_integer(0),
757+
der.encode_sequence(
758+
der.encode_oid(*self.kem.oid),
759+
),
760+
der.encode_octet_string(
761+
der.encode_octet_string(self.dk),
762+
),
763+
)
764+
765+
kem, expanded, seed, ek = dk_from_der(enc)
766+
767+
self.assertEqual(self.kem, kem)
768+
self.assertEqual(self.dk, expanded)
769+
self.assertEqual(None, seed)
770+
self.assertEqual(self.ek, ek)
771+
772+
def test_dk_trailing_junk(self):
773+
enc = der.encode_sequence(
774+
der.encode_integer(0),
775+
der.encode_sequence(
776+
der.encode_oid(*self.kem.oid),
777+
),
778+
der.encode_octet_string(
779+
der.encode_sequence(
780+
der.encode_octet_string(self.seed),
781+
der.encode_octet_string(self.dk),
782+
),
783+
),
784+
) + b'\x00'
785+
786+
with self.assertRaises(der.UnexpectedDER) as e:
787+
dk_from_der(enc)
788+
789+
self.assertIn("Trailing junk after private key structure",
790+
str(e.exception))
791+
792+
def test_dk_wrong_version(self):
793+
enc = der.encode_sequence(
794+
der.encode_integer(1),
795+
der.encode_sequence(
796+
der.encode_oid(*self.kem.oid),
797+
),
798+
der.encode_octet_string(
799+
der.encode_sequence(
800+
der.encode_octet_string(self.seed),
801+
der.encode_octet_string(self.dk),
802+
),
803+
),
804+
)
805+
806+
with self.assertRaises(der.UnexpectedDER) as e:
807+
dk_from_der(enc)
808+
809+
self.assertIn("Unsupported version: 1",
810+
str(e.exception))
811+
812+
def test_dk_wrong_oid(self):
813+
enc = der.encode_sequence(
814+
der.encode_integer(0),
815+
der.encode_sequence(
816+
der.encode_oid(1, 3, 2, 1),
817+
),
818+
der.encode_octet_string(
819+
der.encode_sequence(
820+
der.encode_octet_string(self.seed),
821+
der.encode_octet_string(self.dk),
822+
),
823+
),
824+
)
825+
826+
with self.assertRaises(der.UnexpectedDER) as e:
827+
dk_from_der(enc)
828+
829+
self.assertIn("Not recognised algorithm OID: (1, 3, 2, 1)",
830+
str(e.exception))
831+
832+
def test_dk_junk_after_oid(self):
833+
enc = der.encode_sequence(
834+
der.encode_integer(0),
835+
der.encode_sequence(
836+
der.encode_oid(*self.kem.oid),
837+
der.encode_integer(1),
838+
),
839+
der.encode_octet_string(
840+
der.encode_sequence(
841+
der.encode_octet_string(self.seed),
842+
der.encode_octet_string(self.dk),
843+
),
844+
),
845+
)
846+
847+
with self.assertRaises(der.UnexpectedDER) as e:
848+
dk_from_der(enc)
849+
850+
self.assertIn("Junk after algorithm OID",
851+
str(e.exception))
852+
853+
def test_dk_junk_after_both_encoding(self):
854+
enc = der.encode_sequence(
855+
der.encode_integer(0),
856+
der.encode_sequence(
857+
der.encode_oid(*self.kem.oid),
858+
),
859+
der.encode_octet_string(
860+
der.encode_sequence(
861+
der.encode_octet_string(self.seed),
862+
der.encode_octet_string(self.dk),
863+
) + b'\x00',
864+
),
865+
)
866+
867+
with self.assertRaises(der.UnexpectedDER) as e:
868+
dk_from_der(enc)
869+
870+
self.assertIn("Junk after both encoding",
871+
str(e.exception))
872+
873+
def test_dk_junk_in_both_encoding(self):
874+
enc = der.encode_sequence(
875+
der.encode_integer(0),
876+
der.encode_sequence(
877+
der.encode_oid(*self.kem.oid),
878+
),
879+
der.encode_octet_string(
880+
der.encode_sequence(
881+
der.encode_octet_string(self.seed),
882+
der.encode_octet_string(self.dk),
883+
der.encode_integer(1),
884+
),
885+
),
886+
)
887+
888+
with self.assertRaises(der.UnexpectedDER) as e:
889+
dk_from_der(enc)
890+
891+
self.assertIn("Junk after 'expandedKey' in 'both' value",
892+
str(e.exception))
893+
894+
def test_dk_wrong_expanded_key_size(self):
895+
enc = der.encode_sequence(
896+
der.encode_integer(0),
897+
der.encode_sequence(
898+
der.encode_oid(*self.kem.oid),
899+
),
900+
der.encode_octet_string(
901+
der.encode_sequence(
902+
der.encode_octet_string(self.seed),
903+
der.encode_octet_string(self.dk + b'\x00'),
904+
),
905+
),
906+
)
907+
908+
with self.assertRaises(der.UnexpectedDER) as e:
909+
dk_from_der(enc)
910+
911+
self.assertIn("Invalid expanded key size in encoding",
912+
str(e.exception))
913+
914+
def test_dk_wrong_seed_size(self):
915+
enc = der.encode_sequence(
916+
der.encode_integer(0),
917+
der.encode_sequence(
918+
der.encode_oid(*self.kem.oid),
919+
),
920+
der.encode_octet_string(
921+
der.encode_sequence(
922+
der.encode_octet_string(self.seed + b'\x00'),
923+
der.encode_octet_string(self.dk),
924+
),
925+
),
926+
)
927+
928+
with self.assertRaises(der.UnexpectedDER) as e:
929+
dk_from_der(enc)
930+
931+
self.assertIn("Invalid length of seed in encoding",
932+
str(e.exception))
933+
934+
def test_dk_wrong_tag_in_seed_encoding(self):
935+
enc = der.encode_sequence(
936+
der.encode_integer(0),
937+
der.encode_sequence(
938+
der.encode_oid(*self.kem.oid),
939+
),
940+
der.encode_octet_string(
941+
der.encode_implicit(1, self.seed),
942+
),
943+
)
944+
945+
with self.assertRaises(der.UnexpectedDER) as e:
946+
dk_from_der(enc)
947+
948+
self.assertIn("Unexpected tag in private key encoding",
949+
str(e.exception))
950+
951+
def test_dk_junk_after_seed_encoding(self):
952+
enc = der.encode_sequence(
953+
der.encode_integer(0),
954+
der.encode_sequence(
955+
der.encode_oid(*self.kem.oid),
956+
),
957+
der.encode_octet_string(
958+
der.encode_implicit(0, self.seed) + b'\x00',
959+
),
960+
)
961+
962+
with self.assertRaises(der.UnexpectedDER) as e:
963+
dk_from_der(enc)
964+
965+
self.assertIn("Junk after seed encoding",
966+
str(e.exception))
967+
968+
def test_dk_junk_after_expanded_key(self):
969+
enc = der.encode_sequence(
970+
der.encode_integer(0),
971+
der.encode_sequence(
972+
der.encode_oid(*self.kem.oid),
973+
),
974+
der.encode_octet_string(
975+
der.encode_octet_string(self.dk) + b'\x00',
976+
),
977+
)
978+
979+
with self.assertRaises(der.UnexpectedDER) as e:
980+
dk_from_der(enc)
981+
982+
self.assertIn("Junk after expandedKey",
983+
str(e.exception))

0 commit comments

Comments
 (0)