diff --git a/clients/go-tuf/go-tuf.xfails b/clients/go-tuf/go-tuf.xfails index 5bb8a0d..d863bcf 100644 --- a/clients/go-tuf/go-tuf.xfails +++ b/clients/go-tuf/go-tuf.xfails @@ -2,3 +2,5 @@ # Example: (commented out since the XFAIL is not needed with current go-tuf) # test_keytype_and_scheme[rsa/rsassa-pss-sha256] + +test_mldsa_keytype_and_scheme diff --git a/clients/python-tuf/python_tuf.py b/clients/python-tuf/python_tuf.py index 278ef33..d0e4f74 100755 --- a/clients/python-tuf/python_tuf.py +++ b/clients/python-tuf/python_tuf.py @@ -10,8 +10,18 @@ import shutil import sys +from securesystemslib.signer import KEY_FOR_TYPE_AND_SCHEME, SSlibKey from tuf.ngclient import Updater +# ML-DSA is not enable yet: enable to test the test suite +KEY_FOR_TYPE_AND_SCHEME.update( + { + ("ml-dsa", "ml-dsa-44/1"): SSlibKey, + ("ml-dsa", "ml-dsa-65/1"): SSlibKey, + ("ml-dsa", "ml-dsa-87/1"): SSlibKey, + } +) + def init(metadata_dir: str, trusted_root: str) -> None: """Initialize local trusted metadata""" diff --git a/pyproject.toml b/pyproject.toml index ac4d2c8..0ce9858 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,4 +39,5 @@ lint.select = ["ANN", "DTZ", "E", "F", "FA", "I", "N", "PIE", "PL", "PYI", "RET" lint.ignore = [ "S101", # assert is fine in pytest tests "PLR2004", # magic values are ok in a test suite + "PLR0913", # too many arguments ] diff --git a/tuf_conformance/_internal/repository_simulator.py b/tuf_conformance/_internal/repository_simulator.py index 096eada..1729972 100644 --- a/tuf_conformance/_internal/repository_simulator.py +++ b/tuf_conformance/_internal/repository_simulator.py @@ -74,6 +74,15 @@ ("ed25519", "ed25519"): [ CryptoSigner.generate_ed25519() for _ in range(NUM_SIGNERS) ], + ("ml-dsa", "ml-dsa-44/1"): [ + CryptoSigner.generate_mldsa(scheme="ml-dsa-44/1") for _ in range(NUM_SIGNERS) + ], + ("ml-dsa", "ml-dsa-65/1"): [ + CryptoSigner.generate_mldsa(scheme="ml-dsa-65/1") for _ in range(NUM_SIGNERS) + ], + ("ml-dsa", "ml-dsa-87/1"): [ + CryptoSigner.generate_mldsa(scheme="ml-dsa-87/1") for _ in range(NUM_SIGNERS) + ], } diff --git a/tuf_conformance/conftest.py b/tuf_conformance/conftest.py index 6bfe8ac..94cb0fc 100644 --- a/tuf_conformance/conftest.py +++ b/tuf_conformance/conftest.py @@ -98,9 +98,7 @@ def read_xfails(pytestconfig: pytest.Config) -> list[str]: @pytest.fixture(autouse=True) -def conformance_xfail( - pytestconfig: pytest.Config, request: pytest.FixtureRequest -) -> None: +def conformance_(pytestconfig: pytest.Config, request: pytest.FixtureRequest) -> None: xfails = read_xfails(pytestconfig) if request.node.originalname in xfails or request.node.name in xfails: diff --git a/tuf_conformance/test_keys.py b/tuf_conformance/test_keys.py index ceea2ea..a8adcc0 100644 --- a/tuf_conformance/test_keys.py +++ b/tuf_conformance/test_keys.py @@ -1,6 +1,9 @@ import json +from collections.abc import Generator +from unittest.mock import patch import pytest +from securesystemslib.signer import KEY_FOR_TYPE_AND_SCHEME, SSlibKey from tuf.api.metadata import Metadata, Root, Snapshot, Targets, Timestamp from tuf_conformance._internal.client_runner import ClientRunner @@ -141,6 +144,36 @@ def test_duplicate_sig_keyids(client: ClientRunner, server: SimulatorServer) -> assert client.version(Snapshot.type) is None +def _test_keytype_and_scheme_internal( + client: ClientRunner, + server: SimulatorServer, + keytype: str, + scheme: str, + bad_sig: str, +) -> None: + init_data, repo = server.new_test(client.test_name) + assert client.init_client(init_data) == 0 + # Add a new root signer with given keytype. + # Increase root threshold so the new key is required + signer = repo.new_signer(keytype, scheme) + repo.add_key(Root.type, signer=signer) + repo.root.roles[Root.type].threshold += 1 + repo.publish([Root.type]) + + assert client.refresh(init_data) == 0 + assert client.version(Root.type) == 2 + + # Create new root version. Replace the correct signature with one that looks + # reasonable for the keytype but is incorrect. Expect client to refuse the new root. + repo.publish([Root.type]) + root_md = Metadata.from_bytes(repo.signed_mds[Root.type].pop()) + root_md.signatures[signer.public_key.keyid].signature = bad_sig + repo.signed_mds[Root.type].append(root_md.to_bytes()) + + assert client.refresh(init_data) == 1 + assert client.version(Root.type) == 2 + + # keytype, scheme and an example signature from this type of key standard_keytypes = [ ( @@ -159,11 +192,10 @@ def test_duplicate_sig_keyids(client: ClientRunner, server: SimulatorServer) -> "b61589620c287e23a00abf0e653421010a0ad33869e5a096d604e08d7b4f8eb9c58ebb8a02124576be776f86ab5a3b05dbb6f27cc47f4b144f32ba4012d4b302", ), ] - -ids = [f"{keytype}/{scheme}" for keytype, scheme, _ in standard_keytypes] +standard_params = [pytest.param(*k, id=f"{k[0]}/{k[1]}") for k in standard_keytypes] -@pytest.mark.parametrize("keytype, scheme, bad_sig", standard_keytypes, ids=ids) +@pytest.mark.parametrize("keytype, scheme, bad_sig", standard_params) def test_keytype_and_scheme( client: ClientRunner, server: SimulatorServer, @@ -172,27 +204,54 @@ def test_keytype_and_scheme( bad_sig: str, ) -> None: """Test that client supports keytypes referenced in the TUF specification""" - init_data, repo = server.new_test(client.test_name) - assert client.init_client(init_data) == 0 - # Add a new root signer with given keytype. - # Increase root threshold so the new key is required - signer = repo.new_signer(keytype, scheme) - repo.add_key(Root.type, signer=signer) - repo.root.roles[Root.type].threshold += 1 - repo.publish([Root.type]) + _test_keytype_and_scheme_internal(client, server, keytype, scheme, bad_sig) - assert client.refresh(init_data) == 0 - assert client.version(Root.type) == 2 - # Create new root version. Replace the correct signature with one that looks - # reasonable for the keytype but is incorrect. Expect client to refuse the new root. - repo.publish([Root.type]) - root_md = Metadata.from_bytes(repo.signed_mds[Root.type].pop()) - root_md.signatures[signer.public_key.keyid].signature = bad_sig - repo.signed_mds[Root.type].append(root_md.to_bytes()) +@pytest.fixture +def enable_mldsa() -> Generator[None, None, None]: + # ML-DSA is not yet enabled by default in securesystemslib: enable for the test + with patch.dict( + KEY_FOR_TYPE_AND_SCHEME, + { + ("ml-dsa", "ml-dsa-44/1"): SSlibKey, + ("ml-dsa", "ml-dsa-65/1"): SSlibKey, + ("ml-dsa", "ml-dsa-87/1"): SSlibKey, + }, + ): + yield - assert client.refresh(init_data) == 1 - assert client.version(Root.type) == 2 + +mldsa_keytypes = [ + ( + "ml-dsa", + "ml-dsa-44/1", + "2589e6a4807acd47d240ada0a4dfb1a12832a9fb8c79ca38fe8911c50f491bdfd9f262635066e53d5ac09a923d636d0fb7815f0a5467aff2c1e0ca1cb25c276ac4aa56b20673d0855a98f0477941055a750ca13f71d51f0f5e85d532f1368544cf7cdb1515a2e686cb4f36adfdbab82b07f2b47541f99004cc21f104d2becc90f2a93333556963523cd271731a719276f30c0c96aa110bc8d6f7fd052cd954f62bd868ec351a8651c0520c3aa9e5b724b8eb7d0f06f640da3229f4ac8e732d2712ceeee6fb91ff56637ba82a840712453827306fffe13415f0d87f25756fe1738e7a2300b58f7dbd1706449049ed771f80a13c47c112530a6a9e938796b200e14adcc2dc5541197ff0ada4b2db62e18b5538674ea274fb7cc938341326bf8b456dc398ddd0516d5e4fd5d864318e015c02a9d460f19d998990fef8088f418af897d3fab16f598dbcde66d797de45b056c98d6b9e9e2b38bf7187d4ef4c59d4064cbbb7c58e2cca9721c048b2c4f9399788b98b2c50cb593e23fb51234ca88bbb644b7f9103c7d9da567902afa05420d5c0372104b3cfe176115dd84b9d47720ee39cfbf3817b9aabb470d3bc6379913c3f72d34dfa4977110c84eb67ca7589e0e7c9bcb145084f82e1b723fb596575d7b41f7728ca9614fd9ebdc737374131f0c3e6c843bbfd1007196c1a789815a3182b465a1da9ebad5afdc3310c0285e422c561894f0a56d62c58b526f5ac79f76b5b2a197053f0d4929ad3a33a57cf2db8d5080f1caf54ed3776942ad5f780f3a241dc32c1529e6306710db9f34fe80f0b61619b04547e68878a2bc7baf873789ec3c31aa34b8d901355e1b628f2e867abb3e5f52ee3386f7a385c8627b2f913ebbd804a396a5b26ef9e5ae87a16345fd39b435106d2f4d28f00b4551354b8c377cc4c2ac10305a4fbf5a2bb4437532f64e8877fdad8765497ca352bca3f3bc793d8df90b92dc4c183cc2f8cddb06347be895121006cc21ae9b995d574219ff29f8208052c2bf52ae224b434a1b372e26d9493bf3642d6bddfd4ad078add3f5385b19a16b411ab7cd09c1ce348e5f4997ae68219868e5ce1a62cdd0919de07796f8ccefc68b681f402cf16d0d14463fccbff387078c9165f21efde75d96492fc23300c555c9998d81a3540a4cceee9337314bf9083b5839c6a620b18ee0426466699c407c9585e99cc4c1e5c0168a655da6ebdf565e0f6a770cf945f6e02caac319fbc46b971d55689dccb50daf28b6d96c4f5cefab27073332257e567227d0ca643d48d8a8ea3f84e7397dc3c667d0f24c3ca895089ea6aaf0eaccec375f3d44091018c7ad7d41c47392eb92e071c5bc5e63da13c1205f556854bfe506cb40447b087022058a1dce71a7fa3502f13d02b46abf5e516576164be7a1b8b090eea324fe39b870c7aea9f5e5fb3d9c1dc08a3e46e73e14d25882f1a4d62cebe0521211dbb0e42a435a77d445954b286f43e72eb12f258ff786652a80f9202379069cd76d3dc05cd616f8f2acf85eb213ded8775e8fabf5d8d8dd46e06408cc6d4f26046eb5c9a6933a902324a937479e5865170e2bfadc76ea09244f645341c02ef02c9eb431ccf573af274f9ac95ca847594bface51f4160b1a65e9b9533bdc86ae9a162f5763064c46359835c2f31613e7fa1b1b39599f014a840de712cc00eb1844aea666fca9fd53675b3d1c7efbf56afa21f3fdecce9d81c2cd9a573e6fa1db83a024ca8086ff12392e1665aa34bcb491ddd114cf072dea870899881c636721ddc6a4b9b4ec8699f429ce96364655b59b70da4b419790329cdd6835e8fbcd562a25ad28e7362abb086ca6d5db3007bbf111ea25a718a84f25ca45b2b2d6c79e62f558f1412cd8810e2774506756977811d88a54f3494e901eab7cc4082a1dc503ed40434b009c713cf43bbe0c281af853587f6e82ac8cd0d946bf857f349803659589904e3f41d0127daf9d42ca58e6d67fab40779bc3ffc1e9f6e8f15ea382be80528e9a005830145ced767d41b91f8dc76b8020fe2ca9923cd16775ca51afd2f40a39cc624bd47b6f3f491f17289247e58ffb406c089cad3b812da1f5dafdcee48ed5429dd67582cd4b6f4e1f43e7bad01123ad58fe52e76c62c1116a08517616cbff8630d908e26ff9d973f91a0ec7e7c6d50082e9fdd40f2cd24674379f3d551c070671318832b9d9aa5c69e6c15f36b2fd93dabf3428bdd8d445afc6ed9853ecc8d2b850eb32a5b8650db89599434523af992648ccd51ee871f981b9b92da2810d5c9a33f3f3689752cea3ff574a3766d3c8092cabf3dff3363e4a4a8a94224715b2fe5cea5bb59469746be0ee04fbdc0cd83d22742cdf28720f7951f8637c5972a3d445e868c3d0256d7acf5c53fe27bae15ae3371c09f71c845b85571e5e137cf249a567b58aad4a6ffcf942e68818103d5301dccb37e337ab3c5fa51fbb2ad39aa32ced8142c491501e045628b4b66a1314c2ec1fda3d1edc7b3cfacd525802fde7da443fc712709fab614457b82e31da60a285b4052ab13d77f783ccde999691513467834ed69f976ecff98361d9a49a82222e1bcd5af4f5014d83567c4ae9ecde260fdd953c5cc85c46d7c91084c36eb05a672e2b8d857135b921be50b8aec3101990c105ae20d28158b9ebec0b51694b9740b1a96efae3d7ba67932e1402a9553a24ee3197f162774f6e8c30ff0702181057e8270028978aac97513e8f7959d223d7514ffa1ddad96eab25f12558ec8d19bb912f7201a6e1bafe869b33c34556b19d80e267a98134a2ba82ccc65c45d2d5d811fd8b0e49359193530b2099ff88b3abf6ae72158c725df1d1cf4f3c13a334e314bb055e937bf7738cb7023827b60ce72de9e86749f49de93fd26747eae63805c3196ad3ead35460feae6614a8dd27c706de6b175493e44db1102300a0d3b4191e545cb384d6c62eaeabed785e50465208831584d7f1cb4aabb8f19231d9ddbd3a9fe1d43dcb25c6de42d45ec974fc65c773cfe4ff30c0c246e25d785a3c37ab3c268d44482190fbeca657f868fffef5dbef01ea67ea76b74b48bc3ae7a95a481a1436996b75b897a1c46bac68b411f16fe9639515498f5f9aca26d404b81d293b2c21fc813e6c9a289fac72a9cad0feabc9182b82638641409e290d57e46de015030284d3444324612cf5a4a8c95a300cf5a0297cd1f03e01cf4dfc7fce5be30bd0a18ba7116d6ca9f0563a1087a1a9c9753ca9f8caf5b8644adc8b7abe338e30a788c1d92464cbd85b65b2373c48ce7ef3fef4f97fa431b0a32383e444c6879868ebef4f6001a1e4f52939ba1a6afb9bad0d2dde3fd1c4b5f6ca5a9b3cbcecfdedfe2f1191c26282d303b444652637584858cbabfe2ef00000000000000000000000000000000000d1e2c3f", + ), + ( + "ml-dsa", + "ml-dsa-65/1", + "d1a19edbdb8dea28d2a930e7f9c2425f7e4a025330a544565e1c9945735db5bf101cfa4ff67f7a3c160eb6bf2aaa74860c7c08158a86cd6ce537ec51013c57544f7a3a8a7b522e3a1a288dca90306a88622d62be3ec928bef85ec46e0370ea88c3477294802bc22931c4986444f5612eab8737aba1a8903a090c59d541f54c02a752dbb127f5d30876bf67a1ebb8b8cd6b990fe9c47784327b6659f96796315e8c34c97a2b1b5f3045e1bbe4dcc031f051116827d6c2dbe074156ca58fa1314e04b337f28d13c33ba3edb4040bbe0bdd9f17aa5c28f633683e0bbc240bde24bfe537e7157836ac6de34cfdbe8bc6ef9483271b9f2d10404d67e94fbaa58aebce0f2ddd76bbe18889eead3fa2b543fb6c30cc235cc56fb07cfb0ea29101fd074d726a24ef56eac26d81a0e7c955c612d432c20d240a3e01ac04832f2b50622d1b7062f7547ecf91b0cfef48ec42a610e528eca25aa0dbd6aaa3b3ebd84431b96af0660616c7f69ef43a7a4a8d4d19c241fefb9e5aa0c9ca0009fe01eb74993ef2e887d822ffec09cdedbde0f0b179ad969ed435f902243c4e32432a0ea5767975160d89a9c1940179e3d55bcb3c81ab38d53e8a935c9081d28b245cae8d280477acf1cfc70fffa5cae38b17709fc5d0fe27673436f596a71660077a2d86379e114803c6471430668b54096b15dead9cdb91b2c285a9ca7de6614ba661aa711cfb121f36ab187b3ff69a25fb77db7627f6983f70c2114c01a78cbb76649f94253a1ec39e17814d74b1af1ce28287ad86232de4594badf128cc070cffef72d13a730f795712359ca3233ef7ae6b2e43a609921fe3c750c45f732907b47d4f095f07ed2b1b097d0a2d8ed925ef61dadcd994bda7f6aec415092354c44c50b9028b326589d01fd2012fae15851b48dc32a4c2afbe05111db82398a798457facded8880b5b0092a3ccbb1bf414c1e83393fdefbe034c1ee5203337ad7451229238e6ab6486ff88738ab521b10a248bf7db800bbef7f7919d58a127548558e92af8586bf147b8c239887a94d448d646243010866505cd64118d6a2fb11b5c770368c36164a77cff04b6984b1e3c49e02e1550641ba3e518fbf552f9c0dde8b5f568e579d9c7fdde2658c5ea1f5d86ee34af9a750e76f486624338b3e2f3cab9fc35a87e3ea202d1053280967e069b0590a2250af0014d94fa6a8ae5b4d02ee2540f31576a1003c38bcae21d6b545fb99452f9358ad39604847af00dc66e025013dd08e68acca2b63188881fac7bd7ce9c6d65b74602825ea37c02d5ccaae1f586aedd806fc48930b66b17d6431b4111133c314e8d4c7ad65c7a38f4ef7c863ab3df85479f7609d86e23ca36775a5c53597230b3e4c654f7ad257ba6528917d6b327a8e8a071dc0e5e81049834f6a53e1622ce1037ae877ec380e7fe7f9951089b7cf42386483e7488e3d09c70beaf27810696643d4d8a4ba0dd9e86bd60bee2d40ded73caa106c62e5b2f116a1d74ef4203f32fd09a54a4230e41a80df5c7ea7f17ac0744ece524f040718b1f3a2f79863a905520dde8885597b02e6ea1b97b1637a0a52a936758951677036010ed3ccfb2802c7776bc196a8c820e57caa0aa8c83700865ccaac7363b947c4cf5a56e75494e59cbb1437b13c393fc661d52d0fcd0c5d0f5c74041037e4ab9d0ec11835ea95c6155a3dac44ac30d45fee4d0ad0ef776f4701f54a62ec427530d24b7d1799b48fd41048b5a4c3b4d1a9d34c8b6a993774ab6aad3b3313533cea1c767654ff996c870b80e8b74554fec839e13f1f6261ae2de1c8d69a0d80f9f343138c49a46202bd3727c04acc9efffb3343bdab46acf20ff3013f16a4b0ea7a2844edb8ac610ff12c8ea5092d06e75a244c66312c8b3734fca9b42c934adcfd160656f7851783ab7a49274d359201a5fcf219faaed34b1d589a86095ae2bfec989c0a813213f8270739c5a6c3d34d2973cc3eb2547daef1a0dbbc6fc43138e6cd20a8c2fcf0ff99981a1c0b26a12d092a071648603b0f47f257789e4907f2abb943e035821cdf81bc3debdb9502b808f3b9774b9aca311dd0bd66afa071c3375cb032493b382e4ab015e026f2c53547e39da9fd4793378a7bc80a63a4bbf32d5985487e42af9b33068bd81e3a0c1cbb05d72d021da730833d6d0c783359ca06a9f06b2220864c45b76ab16e09c382f2784d34b280bd86b77644e5b8e179e2495f9123e97a12c09435fd9f0967eb48dfdc22878874a59beb176c537876731c4e0c281d7c83de295542231e49db642001bf68088027b9f59a313f93f6cdcb6bdb585297b90eefaa84583563fe56d3330ea136c7abff760c9b267abca417ac22b71d84e1377b5e05b9e81b562f4c5dc438335e236d002433a22e77e6256b1aacf0ae76399adf802c25d5b58cb07b8dd911bebe6731b642e462c4f7d93bbddb167f1475d3000e8f593a4f16da7b07ca47ac6cd20b1c13f714cba4f8bbbd5699cb7d69997ca8249c42de07615f6a1b52478a83f586e24c5f77d403d5278736a8d4500e6bc5c4643382f8bc43fc8eaa81ed66a41b77acb0176cb99e49c8a4717006a0a0fbf081e4bc4fdb5b3cbfe79971ac8f70b36608ba16853ad59dbe13996beaf0fb02cd08f7e1fbd00e5506cb3399cad5cc6fa50a9647a70d897cfd94081a7c1e04e33bd56f96bcc1e88375c8121399cacaebc2b7986dea96fd7915b97bfe0428dbf7f1fb7f032fdffc4fb9489abefd6c9d42edc7ea89c3755c38e13a2fb1883edb16ee3c5a1c3674c1cead4db42f5182389142e52582c069e6546a4088d654e0d4d4a1b4d12e7731d251ac8458ba12b92b6ec80bf4bf146d4760765200026bf9ba7836e730774f27e5157532c24cb49ffcf24202c8d2c4bb77ce03a0894be62dab17aba0a0d8e6ea4c331f924d5f5cc67e15fda08ffa3fca7d99a5e3788e1fa2c37817207d8eef3c9e90b89a6da1abb1e97d3e0e27e4e6074731e3b66be0dee69cbafae85b4ccd7631f9af991fa64702a8f0fb889ce429f85d88f46d9e265e199c2193240e1ce6247e15abd3e1d9c8cf52aef83b4bddf1962ac25d5dd831a5be0184463d1eb2316cfdfe04c5aea173e86bcf0369893bc951bacb42cfde467a265bc507c27f806f803be30e05236675aaecaf782a13a74b8722df9aa6e13b0a359c7f053e7b2a14505a4b70246c4504b765a89be46537ab64737a5c2cdc3426bf9198ab4bdcea8d5817f2b6850a78fc43a2473b21fc0924e04e917287cf54a69a0810f4d215115fb1c2e57aa3efdb04e1c27356375bc1c3b819227fac17bd5d21d2531acca3ff1abe1d2130f72da4a7b4f1fd61c201603a60a3ad8be2e2fc05f473ae3e7f059a2d2d8b1ccbefaadc5beef0291ae9cedb7d6b7309b32ad8a6470c878b1a96d38c0a6b377db26edd4e5346db88c28e8fd5eccc25e137650f14a19b12f3aa81acb94277307ff495906c4d251e072575b64b2d8ce113af897f5f1b30eb2f913226b3b4f424ed3ee5b9f38c6c828a0594694e1a2c16e2c41e1c6ed01c808f2ac57492e08363df3d12c0fdf8e2f77da3be758d930c1bab2f70516ec0dba556166281caf7eca72115dc50376b78091de5cd616f3cfa9080eb6af33cf93979a2fdf66d045eb180039c1564e84326138d036cc6844463edafb1d09a96e8019d6753cb9d7fcb57f31c5fe272d2be99ae60b30b218797e0772c8b376cb83be3348733cfbc9580f87592777a127befe99aa0a0252ba92a710120066d8cb48414dc2d727650b3d19bac50c0b445545121a8556e0cc867543dcd087811f1cb152a3d680dd7f0141a92c8186500dcf092382f99050c48ae5284e23e69518e0d8a6f27aeda61007e307f06ec6a717cb5bb706b7f3e138c3f5a3682220eed645f89382526d8a4a2438c124fcec9a2ea07c0ead337ee5661b144d7e4411140813745692cdaeeeccf636d85d8626e36a94695cfaf45a025e73baaebd57253354bed3b3ef97a491c91ef76962ed7d0f25e722b067401ab93d08b95270a102f7315c027b4056a1fb07a92a3ba33184450c15b0e6a50ff5175596225012efe35d7efd69fddeccd07b3dfefa096c72288be7682a937888907ca86ead99b83f5562598809766607aa1eee7cdfeb8c70b1c2404b30a85e06db0cb453bb39bfb7f603383ca675e14c60b94d59c4d8af4bd3ca5588faa36c966fa8ba5c803df8eadb884efde697799b91a938e2b6c21c202f0e31d845a72c9f43ffe03472fda75b38ca49bfb8be142459ef5ada16c41587e71f6591bec9dacf769ec6ffb094ff996026ae2ee062c23d31cb76b78283515600e52d97bb67736898405cb9781d861f3449895e2a399f3ae81d794fdc23097de795ddae9f91ce9f49f3b1b51ee1e170bc7055c7474f7ab449639fe626e5758570f11e917eeafbe998d0cb6a31e62ac7cf8ac7c2c23bcf4496b53b52313287de06c5e5608114168d43b54084a1926548828311a609f605bbce34a53fecccac3ddb79090dbb6a53d06efc5363ea2e78d32e7e1b8e8b0f6837f82f131b0a08f256a6457159425474da396cb1c8f662700231011f8b15113724d463c25ef62a696f969dd6f32c65787fb3de4a505288a20f3c63737ea2bde43f5f6fa8f3fa7d8592a6cbf9000000000000000000000000000000000000060c11191f25", + ), + ( + "ml-dsa", + "ml-dsa-87/1", + "965711dfc5f8a5e89e2843dfc775634306ea556fdc670c65d7b7f5caaf083f32bc3cf7a8b6435fc6acf05255855f7a5df5a21120d1e990ec12383f71ce00394291b2212cf86d5e0fb18c05e59263285e4fb990051b46cabb146366a32d4b82ccf7a58e9d3ebdd136fb584c21bdd6ff0dcaddb1bf6c21fa110d87e4e7832420abb67f010791fbb7886fd0c465cf83e150fc42f16f5d780d4880f84d0dc4d26e83a90743d17f8f0d8b48018be7aec1767eed833f64445e660740f7b3bb52d0d27d1bf077aaa5c4e0dd2ed1a0813569b8d28f75c249c8f7c250dbcf7de191b964b9522aaae177bc271f551d4ca0f68a511a2cc27248687c7deb9c4c30861cc76b1cd224cd34570b25d1103f3228238a46c6517579a69c682fb267f90dbfe4344df8aa38a981c7d41cde0425ad72d15b9f9882bfe001d7fe69507f8172c7d0cd0c689c66662c710185c0f7f858ed122266c6116418269c2e12e43541a960154e75c93c9171cb60cf171540b2d638c77489efd4a7b4207349138d1d61aac7089e20ae475a5b75fa45d7abdc0e550622d70f304b8b31205a543516ab60c37f0f94c4b6b0fad0e2ca84b87adc5134c38ff25a1ac54494126372c7971c13ea1ebb2a2a92b84dab68931e7ce0602104e074d1dd341c81024b6b4d5450c6acaaac66b4c97ceb20615380c4e586d32226cbd0a7bcb8451b324332e06d4180d39112fedcb71fba85714d429dc37407d1c58cbff474a6185f629e69e10983d3076dc9582da494eeb432a456d4d7c705187f413a35549d2b0372313ac43c830229654f7777a2193b4b389f7a8e4c7fcf38aec6375a42d48f04f010e1dae7a3c1ceb9f4343d81f6b3af753f38d24931a72d4f2ffd02f75d286f7d814d03ae9a346b1e2bc935a0567f7ffb89bee638099421621238c0996506c51449bc6ea4804cd611c338dfc549aa19c2f786c9640906a59eece8ac94ef9014ed937cd149b6ed9b8479cc7c8d5ad90152a4081c19a80196ca81917ed26970ed67009ae982169f8dfa9c6256cb19c46ce519e65e7b5fc12b4c9531a9b830e551bf5c6206c74a631b810475117a7ea48610f2cf486f3f43f474b5ad411d805df0b576c6694c49f3511f5e1edd4f19cff785d1f127482e3413c69be0625db2aecf22209911753c7d52b362177682c777eb76a25b1313fcc1621b9814513b9447c4f453b27d889c4a8c9b4b25dd2fbcbd13bb1040fe0667f5a6c817ec3324f660d756939d70fa0ad18294e45c772e53061632a3d988c30c2f2d9555cc7864cfc06466dc4025e91c7cc744a5c30675187f3e0fc438308e0721101708c8e4aa7109fc57166db6d54677d91b5e69a6c2698474822299bf36abfa173dd5ad0bdde098f3f694632e7ba49e2a0738c52da5a56a17deae1af17723eabe0cad7177fa3a003f80562f60210262dd7df27988429817701c6ae711f8dbea0f71f2f575ea2c2d42c6bdd90a4637f2e55e7514fc73c3237ba4d5b7453eb9767d20dda6260570fcb39b9888365c00acdc2b1e90ce43550f081dbfe333a1e93107a3fdb1762387b4ef2d1c25e89bbef0734e6416eaaef4ca68c151a1c0edfa9260ad1dc10cae7bae56496402cf1093f47a48224e8d2cdd4f8be1fadd5004ee16c00b874be76f0a72312fc60c49ed675798e8f94bef692ff86813662eed9b65b1352848daa868552f4341332000b95dc5767f8ff12397a0d80ab12761c41ef6b79719a80ca1d7b12ced1fd6d0a4d0ed6de41b8449edd101555dd5f157df17784fa5e3d60555fc6f5afff42801452e03b0d9554700c714062a247fa7a57f5a51385bacb00b8b27b32922819568557121c971c1f3ce4a527623d96e702f5a375bed89c6600523f21634b8c8c330558666fc19158380fada7a4eda33cd98c2cf191f2dd161880a657313f7bc026fe6b5f93ff3c945885d16f4eb2a6b7eb15177c99fcfeec8cc7711f3d752edc7c018e771eff27f16aee51f0358736c864de6a1c152df4458c84d777a1f38a4d5fc07e445fb33947cd45d2a6ff9397cf6b2bf428bc4ac9dca1ecce69be069004516652e96d5f86650a9e7b4d660c0d255ecb5f872dc78c32f3722beeef68f6a4b029b26f0f82b6b6908fab48c1563c85a13b630702570ef14198b2002f9384d8cbd04f2e769bd2e9d43b507e75d8a3f40947faff60dfa47d5ff0880cd093b9d5583f8f722f5987718e4f280703b3d1a388c4e5ca4292e7053d0a54526dbf06df03822c35e5b203e87bd0b5c4e550e54826a8a5bd57f9ca1445bbf4617ec89f181be770a921438496f5a920b49e346652f86a91255cb984005755e3641964d4e6c175fd265eb8d29a07f36f05c0100bbe184fa49968ad079bb7cf3a418373b40ce5e6e4c039a6baef0815c3803878acef9d5d56204093db85e304287e7106d49796a1d8e7513d3f09da721deaf98b22f8a67550b8510847d8f53791966230120d15bd0b956f6e01698e3e739c295d640f6a857d28eed826d9217f156773aa8ae9a4adfa16d14517aeeccbeaac346afa2bcc1f88827fd7b30005f7b3c036c8cc34372d1964d8e522407bd4df59e31b949524bca71a5269cbd05814b262ff00edabd00d9a1b60c50d83a6904a4482ba335aa1fb09a3f030e1a391665e8a3846fa2eb90a1aef8d2a563152a46b448c7eaea9af52e1efd4cbd7e478cd337d32f2f769f906c8724b516716187d57b6220df4b4c5d8d3b60df972e3744858d22cc7dd734d41408e3892f79f3fb2f773adbe20fc2572d3b2f734e6132aed792a024effb6b8d7a7b8fef1fcfb4a2c35ef5143bc10c3b8e4270f8b2280bd18fb776ad5f4c1d246f323144b8c756b1000e83e7117b8afb6ab323d32924e38edc6c3de7494447d8baab6759b64ea651f2031d73d2d6e43e0cd8b17da0a99074a62fdcdf7dc2832965155fd98cd145b67d2fb3c5d66d56224736c16efa71aa32661be3ca6d81f275bb2c4a7e08fe72b18d668d317e4d5fc9425e17739591926d8dbaf340ade9e5251bab7d70689071662447cc18d24d47babae6cdc64bae5755bf278af986b8f5fe730d8bdd5bb979d478ff2050aca7d18b6b3a848d233874953dd2a10a5eb186b0f4a7ab6d427bf38fe0667e85a2433cf65a10c0f544e2b8d1e51ba461a4b84e083d48e7c9a78fdc4eeef51e40955947ba7afd23e1fb1da9c9b949ece297237c46b937006a1362f62a39430e7211efc2e74ae636c2ed33e01742468c6e4b4925421cf0824fdf64b71f5bab8606ce3b1ee4c33b31836217105bd79709bcdcf0fedefa4601c5ef9fbc6e0828ae41fb892629c9fe6449c9b0bbe25a207465e3dd59ccfe0328ad430878cfa130f060703b6316d380f42dcc2f2d58c5554fb85cc45ae419f5bca1de433f2f1f23f3a3202f926ac797624256bef899d1fc6794bd941ccb76ffcd5e3051ec1fecfcc99a987080ea12f77c889a44abf2b5b82b338490072d4083d5b4d4a252ceaed92aaaaab1d797a4b8ad99f9dc686109c69675a6be06cd7632e0b7bc90e01f67055c5661b2fa3ab120b0f900ad1f46b518c77fd75814a9a69b1e98c3f44c18d0d7bba93d4152974110013da69b0a38a1050e8590a58756f74d0c1eba543aac9bd51b4e3af3c2bbd76d98a87d2ebf6b544c2e452f002c8a4b6374d6c53e71422f79a42ae1b8b006ba1722f2e4de3a9dae0fa9baa6e1e1b24b90c5534359300e38a547dd2b73fc4e816f9ae2613143192df95ae69a31cf61dfe5bbc57c42cfc082d5683be973a712375dce9e1dc0337dbb14fe88ceb2019846c601586d97737411d50dfd3d737fe2fe0d31992d3eefe85252ce24fa8e5bb650b450341f311c1df77d6146e70d352f8b0be9bd14096525b64c41c0a7b57f90a4fb72ca29cd5a79467a50a93fb405944ab2d37c822f5573d8f126c202d822d902dd868a7ad647fd9ff39f1823e3afb7c40e3f6ea79605d34293a8d2b3efb97123be728fbd43da3ed107beb672aa263af1abe2b6f36b2ba55cf647e9cac87ce56e1596b296c57451f62c95e5a3bc81211b059572cde1482f43e95b17bbc8946adb9f503090fd6c025e943cab839e51f8609c9e844d47dfb63afed3d9a5654d032d6a0a25c82be488608b9e69ca4c0487f383a17a4b67ae3d76e124bfa373201a9e3e3806c2b1f774535f30361f24093b77a733166b7cea316b7e062682a6db3bb895f0e4112aacee63c34080a8eecb1571395623755b986ae53625aa153c6946c96f779a015103f32092a8a70a272b5f929bb566b5fe26d7cf8038b61acf9b4e334d3d322ae5d6580c2f78f568831369938ce86efcccffd12bf3fa1d02680e5bf678706a76af23ae184f26477eb9789d0cd9bf259d5e7877a969b6a9dd1e60f742a90321d34feaef9a73addca681ea6cb0c1647fcf587e99b3b6f5884848ed96fe44dd040861069dbf051fc29d9bbca6736c80f96564cadd93d2731ab3a33629d968b122fd2f38e2ed2cc945e3cbed77d3ccdd2fe336aed48539f00437efe19e02a079331f9030187fbf0b8fbd119e442ecf58ab8fd6ceed82b7ae86b630647239851ebd569a8e66e7c8095d072478848f4cad5364341adec6f86df05583a1ccba313ac0b24d19b806e7a0385f8a9e850b3eb8b085d7c8dfcc051cd6be4d4a2b5c6626e3ad37b763231ce20e180853f6a9c6d496add04041ff1f8fd49a822cb8435e14929c8bfcb561c294588c9ebb8d4dcc11eca6ab7bc7d50a98b719ac8c44272b9df518a53b0abe44581caa7cb10edb77e92f08a6e9561a16e63fd7da2c998180bf05140ad55f47612fcc41d9691354e39b11f636b80eac1cfff252003ea335dbc4967627540519645e30e8fad215f7376035288aa77685ce36f7534187d943c2095ef79f5646a29719f4b2768da4239cec4c4d32167bedca132b64f5905ea83fce2ffe1fffe72962a6e97803bbea97ecd7f5a3ae8694b6118a7236a64c993bdb8418c02ac1d8f2f88f886e7549d06df2fe7c15256de84bbfe1586099ef97eab25dfe77526c4bbe6014540d299ad16b92e7558cecf9da1c0962aee51aaba1a52e13a6a28b3592d84c9dfade814748c3b8c07827fc97e8276e817a57ce217c80a34a3cc351daa2c59effe946b4e95f8c360b362ebe511f0d9fb605c69a66fa5b8ec154b2f4e810fed0259fc9753937a15f94ee5ee8efcc1194eccdd8529badb5140eeac7b4ba8470677593eee76f043609e7b0b901ac3314f912e5abdf9b7a221a517e83bd343537cccea9c6a301646288ede200e642ec2d3bd54caced8bd6252b806711616f5431c99bbfe571c5f37913d04e9bcb19c0243b7e998320ae078e6b4b275e5fc25c79ec7f45e21713b9d6a331ed8731ad57d88b78966aadca63ff85facf6579dd3bd392139a14c9f713cbdeaca096e2efe9967a87cc7e65f981b064bb7fc1f814893fb1f802ba7ac2ea0714187d99714f8313cbd31d2ab5654e9807dc6907582109f5935a65a67e79040083a80a8ed50230903a0a7286e1e6bf05c83be9c624007184ae35ed81249f608b90d3e7987fb3230a596eff529caf358ec81df37d89122040a2e27bf2a60a8456906dc6ec79b7c7abbe088f5236b433524283cc27075741d916caa629d2cdb2ada2d4c4e08a25eac0c60db8aa745e440edf2d9e3e1c51f060f2e8d2dfd039a56a56591d922a0d14df70832d538d407d5dbb565ccbb47a2a0251d07c1dcae9ad2c61ff8371bb74aec08bb5c98bb0a96a4c8d6b36806f52f376b4a56e922731611c65093d9c76d897b43bca4bf5d704480c7a5b4ab7ee1e391c742b9b19115a0cc329ba9e9b0d79b17c4a82d28471181185fd8cdcf25658ef061d44b5e455cce00f9f4eacd5309039661cef5615d464ce3d647e5aab91de2a8271adc3cbac1a8c5dd6cc3b72fb9b6d3194ae27d4a149c776ed191a7f9bd814bfb149e0f363bf6e8ad097aafe9d847f1d05ffcbc543e5651e86b11a23cefec193fdd83ea2590dbcd787e8beadb4834f8a15025a43d45ca3ab11679901d2c4815107f39b3ff86141fa12f7b1fce77b343e2bf3c99bbc4586cd10cec1a334f0d4f244e8c5b9e9786192817d68272c57c21f268ea3f8ebb8654febd3350eaff13ee1be007f6ef6d73f0fab1793b0e8035de450f112596baafcbf42c30ad92bdc652a2b7202bfa5fd4d8f58c987b61c6dd958ba8d8d14ddd3545d95ddaa2dc7197aee89f9691cc8141b81310b86f97e2c6ef93102bccc1a7b9c8143274f276c7dbe1025e9984c20b894b77bc8f3372ba2b42a803411793f40a8ede48ed4e9b122f54436ee5cbbdfef23bcfa061c778a3654e70786be1445057b9a0ae5c109356a98f55a5fbbc32449adb2b5f6af052bdb6f67f9f29e852119e81df7e05288a825fc9ebc027b62fb4a13620b7d5895d5a9229399aeea5bee7dacd7563abc55a56e4ddb086e1c383b3e5a6e8e96b3bee7202372b2ccfb057198a2b7bfd7e8eb0004134b575f748dbed4dff100153f40506377bdcadc527789a4b7c6e80a263e496aa5aee3f704092136728d8ebcbfe9000b111a263037404a", + ), +] +mldsa_params = [pytest.param(*k, id=f"{k[0]}/{k[1]}") for k in mldsa_keytypes] + + +@pytest.mark.parametrize("keytype, scheme, bad_sig", mldsa_params) +def test_mldsa_keytype_and_scheme( + client: ClientRunner, + server: SimulatorServer, + keytype: str, + scheme: str, + bad_sig: str, + enable_mldsa: None, +) -> None: + """Test that client supports ML-DSA keytypes""" + _test_keytype_and_scheme_internal(client, server, keytype, scheme, bad_sig) def test_invalid_sig_in_valid_metadata(