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
218 changes: 218 additions & 0 deletions EvpTestRecipes/3.0/evppkey_ecx.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,221 @@ 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
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
Loading