Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 258 additions & 0 deletions EvpTestRecipes/3.0/evppkey_ecx.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,261 @@ Result = KEYPAIR_MISMATCH

PrivPubKeyPair = Bob-25519:Alice-25519-PUBLIC
Result = KEYPAIR_MISMATCH

Title = X25519 non-canonical public keys

# reduces to u = 2 mod p
PublicKeyRaw=NonCanonical-Pub-1:X25519:efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-1
SharedSecret=E80C0BE9D3A1C5D71EDD6316E8C9115CA35397CD47109BD38E32864F1ADECF4D

# reduces to u = 3 mod p
PublicKeyRaw=NonCanonical-Pub-2:X25519:f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-2
SharedSecret=2B6282A3A5AA1380B79D8ED2F73811F182E35E17E25A86D23C4D2F65713A6B7F

# high bit set AND value >= p after masking, reduces to u = 3 mod p
PublicKeyRaw=NonCanonical-Pub-3:X25519:f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-3
SharedSecret=2B6282A3A5AA1380B79D8ED2F73811F182E35E17E25A86D23C4D2F65713A6B7F

# reduces to u = 4 mod p
PublicKeyRaw=NonCanonical-Pub-4:X25519:f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-4
SharedSecret=3DC4B23E14B1E04DA492BAEBA54AE9CF9CD5298713903E6238E5128B31FA5E4E

# reduces to u = 5 mod p
PublicKeyRaw=NonCanonical-Pub-5:X25519:f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-5
SharedSecret=717EFC3F25E74904CCDF9896B6EB5836E85A45B5A7A26F9E3ACF91F0EB7D3F4A

# reduces to u = 6 mod p
PublicKeyRaw=NonCanonical-Pub-6:X25519:f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-6
SharedSecret=0FD3892BF714427086056B360E24A98CF0EE50BA6DC45744EBAA0BB8F9BC1F27

# reduces to u = 7 mod p
PublicKeyRaw=NonCanonical-Pub-7:X25519:f4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-7
SharedSecret=AF4F41D8794E87F83BEF3BF7B0929D43133911C25C5105AFB221A79FC9946C59

# reduces to u = 8 mod p
PublicKeyRaw=NonCanonical-Pub-8:X25519:f5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-8
SharedSecret=C8F33C10FCF2B405BB6097703DE0D4E706522736FAE188E1EBF7E4C1BCC2211B

# reduces to u = 9 (the base point) mod p
PublicKeyRaw=NonCanonical-Pub-9:X25519:f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-9
SharedSecret=8520F0098930A754748B7DDCB43EF75A0DBF3A0D26381AF4EBA4A98EAA9B4E6A

# reduces to u = 10 mod p
PublicKeyRaw=NonCanonical-Pub-10:X25519:f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-10
SharedSecret=01EE50445ED8B4AE530677B182359A0E41312B80EA4CC72185D18F352F485065

# reduces to u = 11 mod p
PublicKeyRaw=NonCanonical-Pub-11:X25519:f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-11
SharedSecret=E087CBDC36A1C45005481BC63B949590DCDC0F538A04C9BBC1C13E3DB0B82A52

# reduces to u = 12 mod p
PublicKeyRaw=NonCanonical-Pub-12:X25519:f9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-12
SharedSecret=98205C5722464A4FEFA3535D51BB4BFD25E7F1584A4DD7AFA74CE035D058892A

# reduces to u = 13 mod p
PublicKeyRaw=NonCanonical-Pub-13:X25519:faffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-13
SharedSecret=B8042BA97FC573CA543F1D05A56F3DC45BE0CB1B13CB9E01F07386E479980314

# reduces to u = 14 mod p
PublicKeyRaw=NonCanonical-Pub-14:X25519:fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-14
SharedSecret=53446A13586F563B6C32B9F40FA122A5F15AF45C5E750003A27C280CD39BC340

# reduces to u = 15 mod p
PublicKeyRaw=NonCanonical-Pub-15:X25519:fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-15
SharedSecret=FD5168B75730FD82D6392D05D53E2346CCD2F0895D4588F68977BE2BD719BA3B

# reduces to u = 16 mod p
PublicKeyRaw=NonCanonical-Pub-16:X25519:fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-16
SharedSecret=2FEF9732A4204D308743EC3DF457D9F6AF7AB3601097E4201FF04D773EC4C815

# reduces to u = 17 mod p
PublicKeyRaw=NonCanonical-Pub-17:X25519:feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-17
SharedSecret=81A02A45014594332261085128959869FC0540C6B12380F51DB4B41380DE2C2C

# reduces to u = 18 mod p
PublicKeyRaw=NonCanonical-Pub-18:X25519:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=NonCanonical-Pub-18
SharedSecret=359668D79A67267A57FFEF8F0F4A9882A7C0E3122CB1999C5626346383F9F811

# Non-canonical p+0 (reduces to u = 0, identity) and p+1 (reduces to u = 1, low-order)
# are tested in the low-order section below as LowOrder-Pub-6-Identity-NonCanonical
# and LowOrder-Pub-5-NonCanonical respectively.

Title = X25519 high bit (bit 255) set

# Canonical non-low-order key with high bit set: must produce same shared secret
# Tests that bit 255 is masked before use
PublicKeyRaw=HighBit-Pub-1:X25519:de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882bcf

Derive=Alice-25519-Raw
PeerKey=HighBit-Pub-1
SharedSecret=4A5D9D5BA4CE2DE1728E3BF480350F25E07E21C947D19E3376F09B3C1E161742

# Canonical low-order key (u = 0) with high bit set
PublicKeyRaw=HighBit-LowOrder-Pub-1:X25519:0000000000000000000000000000000000000000000000000000000000000080

Derive=Alice-25519-Raw
PeerKey=HighBit-LowOrder-Pub-1
Result=DERIVE_ERROR

# Non-canonical (p+2, reduces to u = 2) with high bit set
# Tests that high bit is masked BEFORE non-canonical reduction
PublicKeyRaw=HighBit-NonCanonical-Pub-1:X25519:efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Derive=Alice-25519-Raw
PeerKey=HighBit-NonCanonical-Pub-1
SharedSecret=E80C0BE9D3A1C5D71EDD6316E8C9115CA35397CD47109BD38E32864F1ADECF4D

# Non-canonical (p+1, reduces to u = 1, low-order) with high bit set
# Tests high-bit masking + non-canonical reduction + low-order rejection
PublicKeyRaw=HighBit-NonCanonical-Pub-2:X25519:eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Derive=Alice-25519-Raw
PeerKey=HighBit-NonCanonical-Pub-2
Result=DERIVE_ERROR

Title = X25519 low-order public keys

# u = 0 (identity)
PublicKeyRaw=LowOrder-Pub-0:X25519:0000000000000000000000000000000000000000000000000000000000000000

Derive=Alice-25519-Raw
PeerKey=LowOrder-Pub-0
Result=DERIVE_ERROR

# u = 1 (low-order point)
PublicKeyRaw=LowOrder-Pub-1:X25519:0100000000000000000000000000000000000000000000000000000000000000

Derive=Alice-25519-Raw
PeerKey=LowOrder-Pub-1
Result=DERIVE_ERROR

# Wycheproof low-order point on the curve
PublicKeyRaw=LowOrder-Pub-2:X25519:e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800

Derive=Alice-25519-Raw
PeerKey=LowOrder-Pub-2
Result=DERIVE_ERROR

# Wycheproof low-order point on the twist
PublicKeyRaw=LowOrder-Pub-3:X25519:5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157

Derive=Alice-25519-Raw
PeerKey=LowOrder-Pub-3
Result=DERIVE_ERROR

# u = p - 1 (low-order)
PublicKeyRaw=LowOrder-Pub-4:X25519:ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=LowOrder-Pub-4
Result=DERIVE_ERROR

# Non-canonical encoding of u = 1 (value = 1 + p = eeff..ff7f)
# Tests both canonicalization AND low-order rejection
PublicKeyRaw=LowOrder-Pub-5-NonCanonical:X25519:eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=LowOrder-Pub-5-NonCanonical
Result=DERIVE_ERROR

# Non-canonical encoding of identity (value = p = edff...ff7f, reduces to 0)
# Acceptance criterion #3: identity must be rejected
PublicKeyRaw=LowOrder-Pub-6-Identity-NonCanonical:X25519:edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f

Derive=Alice-25519-Raw
PeerKey=LowOrder-Pub-6-Identity-NonCanonical
Result=DERIVE_ERROR

# Selected vectors from Wycheproof
# Source: https://github.com/C2SP/wycheproof/blob/main/testvectors_v1/x25519_test.json
Title = X25519 Wycheproof targeted vectors

# tcId = 2: public key on twist (Twist; result = acceptable, non-zero shared)
PrivateKeyRaw=WP-Priv-tcId-2:X25519:d85d8c061a50804ac488ad774ac716c3f5ba714b2712e048491379a500211958

PublicKeyRaw=WP-Pub-tcId-2:X25519:63aa40c6e38346c5caf23a6df0a5e6c80889a08647e551b3563449befcfc9733

Derive=WP-Priv-tcId-2
PeerKey=WP-Pub-tcId-2
SharedSecret=279DF67A7C4611DB4708A0E8282B195E5AC0ED6F4B2F292C6FBD0ACAC30D1332

# tcId = 3
PrivateKeyRaw=WP-Priv-tcId-3:X25519:c8b45bfd32e55325d9fd648cb302848039000b390e44d521e58aab3b29a6964b

PublicKeyRaw=WP-Pub-tcId-3:X25519:0f83c36fded9d32fadf4efa3ae93a90bb5cfa66893bc412c43fa7287dbb99779

Derive=WP-Priv-tcId-3
PeerKey=WP-Pub-tcId-3
SharedSecret=4BC7E01E7D83D6CF67632BF90033487A5FC29EBA5328890EA7B1026D23B9A45F

# tcId = 63
PrivateKeyRaw=WP-Priv-tcId-63:X25519:e0f978dfcd3a8f1a5093418de54136a584c20b7b349afdf6c0520886f95b1272

PublicKeyRaw=WP-Pub-tcId-63:X25519:e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800

Derive=WP-Priv-tcId-63
PeerKey=WP-Pub-tcId-63
Result=DERIVE_ERROR

# tcId = 103
PrivateKeyRaw=WP-Priv-tcId-103:X25519:60a3a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a9767f

PublicKeyRaw=WP-Pub-tcId-103:X25519:b7b6d39c765cb60c0c8542f4f3952ffb51d3002d4aeb9f8ff988b192043e6d0a

Derive=WP-Priv-tcId-103
PeerKey=WP-Pub-tcId-103
SharedSecret=0200000000000000000000000000000000000000000000000000000000000000
30 changes: 27 additions & 3 deletions SymCryptProvider/src/keymgmt/p_scossl_ecc_keymgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
extern "C" {
#endif

#define SCOSSL_X25519_MAX_SIZE (32)
#define SCOSSL_ECC_DEFAULT_DIGEST SN_sha256
#define SCOSSL_ECC_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_PUBLIC_KEY | OSSL_KEYMGMT_SELECT_PRIVATE_KEY | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)

Expand Down Expand Up @@ -527,6 +526,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(_Inout_ SCOSSL_ECC_KEY_CTX
SCOSSL_STATUS ret = SCOSSL_FAILURE;
SYMCRYPT_NUMBER_FORMAT numFormat = keyCtx->isX25519 ? SYMCRYPT_NUMBER_FORMAT_LSB_FIRST : SYMCRYPT_NUMBER_FORMAT_MSB_FIRST;
SYMCRYPT_ECPOINT_FORMAT pointFormat = keyCtx->isX25519 ? SYMCRYPT_ECPOINT_FORMAT_X : SYMCRYPT_ECPOINT_FORMAT_XY;
UINT32 flags = SYMCRYPT_FLAG_ECKEY_ECDH;
const OSSL_PARAM *p;

if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL)
Expand All @@ -553,6 +553,16 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(_Inout_ SCOSSL_ECC_KEY_CTX
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
goto cleanup;
}

if (cbPublicKey != SCOSSL_X25519_KEY_SIZE)
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
goto cleanup;
}

p_scossl_x25519_canonicalize_public_key(pbPublicKey);

flags |= SYMCRYPT_FLAG_KEY_NO_FIPS;
}
else
{
Expand Down Expand Up @@ -585,7 +595,7 @@ static SCOSSL_STATUS p_scossl_ecc_keymgmt_set_params(_Inout_ SCOSSL_ECC_KEY_CTX
pbPublicKey, cbPublicKey,
numFormat,
pointFormat,
SYMCRYPT_FLAG_ECKEY_ECDH,
flags,
keyCtx->key);
if (scError != SYMCRYPT_NO_ERROR)
{
Expand Down Expand Up @@ -1102,6 +1112,14 @@ static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
goto cleanup;
}

if (cbPublicKey != SCOSSL_X25519_KEY_SIZE)
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
goto cleanup;
}

p_scossl_x25519_canonicalize_public_key(pbPublicKey);
}

if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY)) != NULL)
Expand All @@ -1112,6 +1130,12 @@ static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *
goto cleanup;
}

if (cbPrivateKey != SCOSSL_X25519_KEY_SIZE)
{
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
goto cleanup;
}

// Preserve original bits for export
keyCtx->modifiedPrivateBits = pbPrivateKey[0] & 0x07;
keyCtx->modifiedPrivateBits |= pbPrivateKey[cbPrivateKey-1] & 0xc0;
Expand All @@ -1126,7 +1150,7 @@ static SCOSSL_STATUS p_scossl_x25519_keymgmt_import(_Inout_ SCOSSL_ECC_KEY_CTX *
pbPublicKey, cbPublicKey,
SYMCRYPT_NUMBER_FORMAT_LSB_FIRST,
SYMCRYPT_ECPOINT_FORMAT_X,
SYMCRYPT_FLAG_ECKEY_ECDH,
SYMCRYPT_FLAG_ECKEY_ECDH | SYMCRYPT_FLAG_KEY_NO_FIPS,
keyCtx->key);
if (scError != SYMCRYPT_NO_ERROR)
{
Expand Down
Loading