From 216ec7d6fc8ddcc7afddf7b4d57ad768783e80bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 30 Mar 2026 10:05:25 +0200 Subject: [PATCH] ECDH: add test cases with MSB 0 in shared secret MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The goal is to catch possible bugs where we would compute the output length based on the bitlength of the shared secret MPI. So, what matters is the most significant byte, even for Montgomery curves where the all values are written out little endian. The values were generated by the following sage script. The script could be a bit more compact by using E.random_point() instead of the conventional base point G as the peer's key, but I prefered making the script deterministic so its output can easily be checked. p256 = { "name": "p256", "p": 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1, "a": -3, "b": 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b, "gx": 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296, "gy": 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5, } p521 = { "name": "p521", "p": 2^521 - 1, "a": -3, "b": 0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00, "gx": 0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66, "gy": 0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650, } x255 = { "name": "x25519", "p": 2^255 - 19, "a": 486662, "gx": 9, "gy": 14781619447589544791020593568409986887264606134616475288964881837755586237401, } x448 = { "name": "x448", "p": 2^448 - 2^224 - 1, "a": 156326, "gx": 5, "gy": 355293926785568175264127502063783334808976399387714271831880898435169088786967410002932673765864550910142774147268105838985595290606362, } def byte_len(i): return (i.bit_length() + 7) // 8 def leading0(name, p, gx, gy, a, b=None): is_montgomery = b is None if is_montgomery: E = EllipticCurve(GF(p), [0, a, 0, 1, 0]) increment = 8 # x22519 scalars have the low 3 bits unset else: E = EllipticCurve(GF(p), [a, b]) increment = 1 G = E(gx, gy) s = 2^(p.bit_length() - 1) # x25519 scalars have bit 254 set Z = G * s while byte_len(Z.x().lift()) >= byte_len(p): s += increment Z += increment * G print(name) if is_montgomery: nbytes = byte_len(p) print(f"s: {s.to_bytes(nbytes, "little").hex()}") print(f"G: {G.x().lift().to_bytes(nbytes, "little").hex()}") print(f"Z: {Z.x().lift().to_bytes(nbytes, "little").hex()}") else: nibbles = byte_len(p) * 2 print(f"s: {s:0{nibbles}x}") print(f"G: 04{G.x().lift():0{nibbles}x}{G.y().lift():0{nibbles}x}") print(f"Z: {Z.x().lift():0{nibbles}x}") leading0(**p256) leading0(**p521) leading0(**x255) leading0(**x448) Signed-off-by: Manuel Pégourié-Gonnard --- tests/suites/test_suite_psa_crypto.data | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index b709f04003..a5fb4c712b 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -7256,6 +7256,11 @@ PSA (raw) key agreement: ECDH SECP256R1 (RFC 5903) depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256 key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":PSA_SUCCESS +# see generating script in commit message +PSA (raw) key agreement: ECDH SECP256R1 (shared secret with leading 0) +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256 +key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"800000000000000000000000000000000000000000000000000000000000000e":"046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5":"0054fe92ec56ef5ad8bf4d9c46d2ca773af76c2e8c8b00e20ab772cf8b34348f":PSA_SUCCESS + PSA (raw) key agreement: ECDH SECP384R1 (RFC 5903) depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_384 key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"04e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746":PSA_SUCCESS @@ -7264,6 +7269,11 @@ PSA (raw) key agreement: ECDH SECP521R1 (RFC 5903) depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_521 key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"0400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea":PSA_SUCCESS +# see generating script in commit message +PSA (raw) key agreement: ECDH SECP521R1 (shared secret with leading 0) +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_521 +key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"0400c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650":"002da7db02840f023a36e1fffeaee16d3c47bb435bec6a231d4aab1ec5412f56fb90fcc4eaab9fd8571084cb9da252466c052d21913ce0fda47e61829972ce8f9a17":PSA_SUCCESS + PSA (raw) key agreement: ECDH brainpoolP256r1 (RFC 7027) depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_BRAINPOOL_P_R1_256 key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b":PSA_SUCCESS @@ -7284,6 +7294,11 @@ PSA (raw) key agreement: X25519 (RFC 7748: Bob) depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_MONTGOMERY_255 key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb":"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742":PSA_SUCCESS +# see generating script in commit message +PSA (raw) key agreement: X25519 (shared secret with MSB 0) +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_MONTGOMERY_255 +key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"8813000000000000000000000000000000000000000000000000000000000040":"0900000000000000000000000000000000000000000000000000000000000000":"9ec15224edbe326c5b40fa30311421f1fb309fdd0fcaf472b5d0ad2067b7db00":PSA_SUCCESS + PSA (raw) key agreement: X448 (RFC 7748: Alice) depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_MONTGOMERY_448 key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b":"3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609":"07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d":PSA_SUCCESS @@ -7292,6 +7307,11 @@ PSA (raw) key agreement: X448 (RFC 7748: Bob) depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_MONTGOMERY_448 key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d":"9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0":"07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d":PSA_SUCCESS +# see generating script in commit message +PSA (raw) key agreement: X448 (shared secret with MSB 0) +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_MONTGOMERY_448 +key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"d805000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":"0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"517b6be2c2edd157319082d4ddc688add71297284b6da74b050170035d764c19b8a14da4600715b18d8a3320a8e18a1d80fc9e6f7ea85600":PSA_SUCCESS + PSA (raw) key agreement: FFDH 2048 bits depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT:PSA_WANT_DH_RFC7919_2048 key_agreement:PSA_ALG_FFDH:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):"4bd2bd426bda18aa94501942095ffe5a9affed1535b942f3449bce8e90f9e57f512c8fdda496c3ac051d951be206365fb5dd03a7d7db5236b98ddfa68237a45ef4513b381a82863cdb6521b44e10aa45de28d040326c5d95e9399ae25f6cad681f1cbf8c71934b91d5c8765f56d3978544784f297aa60afadd824e4b9525867fea33d873c379e3e7bd48528ec89aa01691b57df1c87c871b955331697e6a64db0837e1d24c80e2770179a98cae9da54d21cc5af4cc7b713b04554e2cdf417d78f12e8c749a2669e036a5b89eda7b087eb911c629f16128ab04f0ee7a3a9bec5772cfc68bbd0b492a781b36d26c2ec1f83953e192247e52714c3f32f0635f698c":"6d34e084b8d0e253a894237be9977e1a821b556ed4bc01cda691a927885979b59e55a30daa2a707769474b760e9f1c10544b2ce74b26efa4f069e05ce70471bf6b7e6c08a16fa880930790204e8b482478de0682ce3f58450a4e15abc14d05e13ef773a10a3e8bf2219f8ab556c88dc2a301b362c2d4e94bf2f0006bb36d15a5096ed1342f3f111ccf123ceae9bdc7bc0cde5edc9f0203f35f8a98aff6d75975357733a429364ed3aca32acaf9f857ef751e0e246140eebdfc2b403b644e42c48922f7f6cdaa6a2ef9ddfa54fb83657492f9f9a2c8aa4831601f9b11663e94d968d8be6e121aee2c79156e44aaa650bb26083983a76cc5883538d4794855ded1":"718ab2b5da3bc6e7767a98fb2c172bd74003fae2acffbc9a53d9b358401c1c748da36cab277e9397bc5eeec3010321d0f882d959eb097adddc99745526b213e30dc0df9fb1e4cd3fc27bfb1d6e89c715373439a66b9a13aa1334c84799827c17be1c36c1bc02fe60ea698da790fe4d2af710a435a1aae7fb11cd2a90a17ad87dde4f154b325dc47d8ea107a29d10a3bfa17149a1f9e8a1f7b680bfdca90fb0913c0b681670d904de49d7d000d24060330d4d2e4a2381d78c49e272d313174218561ceeb37e2ef824905d0fa42d13d49a73018411aeb749f7f4fc765bdc6db58bcebd995d4c949b0061f20759e1263d8f9ba3fd56afda07c178997256bb7d5230":PSA_SUCCESS