Skip to content

Commit 0236095

Browse files
committed
ECIES: support X25519 and X448 keys
Select the key type with wc_ecc_ctx_set_curve_id(), then use the new wc_ecc_encrypt_ex2()/wc_ecc_decrypt_ex2(); the ecc_key entry points keep their ABI. The ephemeral key is a raw little-endian u-coordinate (RFC 7748).
1 parent 4d1bd55 commit 0236095

8 files changed

Lines changed: 1745 additions & 135 deletions

File tree

doc/dox_comments/header_files/ecc.h

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,69 @@ int wc_ecc_ctx_reset(ecEncCtx* ctx, WC_RNG* rng); /* reset for use again w/o al
18881888
int wc_ecc_ctx_set_algo(ecEncCtx* ctx, byte encAlgo, byte kdfAlgo,
18891889
byte macAlgo);
18901890

1891+
/*!
1892+
\ingroup ECC
1893+
1894+
\brief This function selects the type of key an ecEncCtx object operates
1895+
on. It can optionally be called after wc_ecc_ctx_new.
1896+
1897+
ECC_CURVE_DEF, the default, means the key pointers handed to the ECIES
1898+
functions are ecc_key pointers. ECC_X25519 and ECC_X448 mean they are
1899+
curve25519_key and curve448_key pointers respectively, in which case they
1900+
must be passed to wc_ecc_encrypt_ex2 and wc_ecc_decrypt_ex2 - the
1901+
ecc_key-typed wc_ecc_encrypt, wc_ecc_encrypt_ex and wc_ecc_decrypt reject a
1902+
context configured for a Montgomery curve.
1903+
1904+
Individual ECC curves are not selectable here: for an ecc_key the curve is
1905+
carried by the key itself. This is a key type selector only.
1906+
1907+
\return 0 Returned upon successfully setting the key type.
1908+
\return NOT_COMPILED_IN Returned if the curve is compiled in but its ECIES
1909+
support is not. See WOLFSSL_ECIES_X25519 and WOLFSSL_ECIES_X448.
1910+
\return BAD_FUNC_ARG Returned if the given ecEncCtx object is NULL or
1911+
curveId is not one of the three values above.
1912+
1913+
\param ctx pointer to the ecEncCtx for which to set the key type
1914+
\param curveId ECC_CURVE_DEF, ECC_X25519 or ECC_X448
1915+
1916+
\note The setting survives wc_ecc_ctx_reset, so a context can be reused
1917+
across the REQ/RESP rounds without reconfiguring it.
1918+
1919+
_Example_
1920+
\code
1921+
ecEncCtx* ctx;
1922+
// initialize ctx
1923+
if (wc_ecc_ctx_set_curve_id(ctx, ECC_X25519) != 0) {
1924+
// error setting the key type
1925+
}
1926+
\endcode
1927+
1928+
\sa wc_ecc_ctx_new
1929+
\sa wc_ecc_ctx_get_curve_id
1930+
\sa wc_ecc_encrypt_ex2
1931+
\sa wc_ecc_decrypt_ex2
1932+
*/
1933+
1934+
int wc_ecc_ctx_set_curve_id(ecEncCtx* ctx, int curveId);
1935+
1936+
/*!
1937+
\ingroup ECC
1938+
1939+
\brief This function reads back the key type configured on an ecEncCtx
1940+
object with wc_ecc_ctx_set_curve_id.
1941+
1942+
\return 0 Returned upon successfully reading the key type.
1943+
\return BAD_FUNC_ARG Returned if either argument is NULL.
1944+
1945+
\param ctx pointer to the ecEncCtx to read
1946+
\param curveId pointer to an int that receives ECC_CURVE_DEF, ECC_X25519
1947+
or ECC_X448
1948+
1949+
\sa wc_ecc_ctx_set_curve_id
1950+
*/
1951+
1952+
int wc_ecc_ctx_get_curve_id(ecEncCtx* ctx, int* curveId);
1953+
18911954
/*!
18921955
\ingroup ECC
18931956
@@ -2243,6 +2306,113 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
22432306
int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
22442307
word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);
22452308

2309+
/*!
2310+
\ingroup ECC
2311+
2312+
\brief This function encrypts the given message using ECIES, as
2313+
wc_ecc_encrypt_ex does, but takes the keys as void pointers so that a
2314+
Montgomery-curve key can be used. The type the pointers actually have is
2315+
whatever wc_ecc_ctx_set_curve_id selected on ctx: ecc_key for
2316+
ECC_CURVE_DEF, curve25519_key for ECC_X25519, curve448_key for ECC_X448.
2317+
2318+
For the Montgomery curves the ephemeral public key is placed at the front
2319+
of the message as a raw little-endian u-coordinate - 32 bytes for X25519,
2320+
56 for X448 - with no format byte and no compression. This is the RFC 7748
2321+
encoding used by the TLS key_share extension and by HPKE.
2322+
2323+
\return 0 Returned upon successfully encrypting the message.
2324+
\return BAD_FUNC_ARG Returned if privKey, pubKey, msg, out or outSz is
2325+
NULL, or if compressed is set for a Montgomery curve.
2326+
\return BUFFER_E Returned if the supplied output buffer is too small.
2327+
\return NOT_COMPILED_IN Returned if the selected DEM or curve support is
2328+
not built in.
2329+
2330+
\param privKey pointer to the sender's private key, of the type ctx
2331+
selects. This is normally an ephemeral key, fresh for each message.
2332+
\param pubKey pointer to the peer's public key, of the type ctx selects
2333+
\param msg pointer to the buffer holding the message to encrypt
2334+
\param msgSz size of the buffer to encrypt
2335+
\param out pointer to the buffer in which to store the ciphertext
2336+
\param outSz pointer to a word32 holding the available size in out; on
2337+
success, holds the number of bytes written
2338+
\param ctx pointer to an ecEncCtx object. Mandatory for the Montgomery
2339+
curves: the key type cannot be recovered from a NULL context, and passing
2340+
NULL there would make this function read a curve25519_key or curve448_key
2341+
as though it were an ecc_key.
2342+
\param compressed whether to export the ephemeral public key as a
2343+
compressed point. ECC only; must be 0 for a Montgomery curve.
2344+
2345+
\note The crypto callback (WOLF_CRYPTO_CB) ECIES hooks take ecc_key
2346+
pointers and are therefore bypassed for the Montgomery curves.
2347+
2348+
_Example_
2349+
\code
2350+
byte msg[32]; // padded to the DEM block size
2351+
byte out[CURVE25519_PUB_KEY_SIZE + sizeof(msg) + WC_SHA256_DIGEST_SIZE];
2352+
word32 outSz = sizeof(out);
2353+
curve25519_key eph, peer;
2354+
ecEncCtx* ctx;
2355+
// initialize eph with a fresh key pair and peer with the peer public key
2356+
2357+
ctx = wc_ecc_ctx_new(0, &rng);
2358+
if (wc_ecc_ctx_set_curve_id(ctx, ECC_X25519) != 0) {
2359+
// error selecting the key type
2360+
}
2361+
if (wc_ecc_encrypt_ex2(&eph, &peer, msg, sizeof(msg), out, &outSz, ctx, 0)
2362+
!= 0) {
2363+
// error encrypting message
2364+
}
2365+
\endcode
2366+
2367+
\sa wc_ecc_decrypt_ex2
2368+
\sa wc_ecc_ctx_set_curve_id
2369+
\sa wc_ecc_encrypt_ex
2370+
*/
2371+
2372+
int wc_ecc_encrypt_ex2(void* privKey, void* pubKey, const byte* msg,
2373+
word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx, int compressed);
2374+
2375+
/*!
2376+
\ingroup ECC
2377+
2378+
\brief This function decrypts a message produced by wc_ecc_encrypt_ex2.
2379+
The keys are void pointers whose actual type is whatever
2380+
wc_ecc_ctx_set_curve_id selected on ctx.
2381+
2382+
For the Montgomery curves the peer's ephemeral public key is read from the
2383+
front of the message and validated - wc_curve25519_check_public or
2384+
wc_curve448_check_public - before the shared secret is derived. That check
2385+
requires a canonical encoding with the high bit clear, which is what
2386+
wc_ecc_encrypt_ex2 produces.
2387+
2388+
\return 0 Returned upon successfully decrypting the message.
2389+
\return BAD_FUNC_ARG Returned if privKey, msg, out or outSz is NULL, or
2390+
the input is too short to hold a message.
2391+
\return BUFFER_E Returned if the supplied output buffer is too small.
2392+
\return HASH_TYPE_E Returned if the message MAC does not verify.
2393+
\return AES_GCM_AUTH_E Returned if an AES-GCM DEM fails to authenticate.
2394+
2395+
\param privKey pointer to the recipient's private key, of the type ctx
2396+
selects
2397+
\param pubKey optional pointer to storage of the type ctx selects, which
2398+
receives the peer's ephemeral public key. May be NULL, in which case
2399+
temporary storage is used.
2400+
\param msg pointer to the ciphertext to decrypt
2401+
\param msgSz size of the ciphertext
2402+
\param out pointer to the buffer in which to store the plaintext
2403+
\param outSz pointer to a word32 holding the available size in out; on
2404+
success, holds the number of bytes written
2405+
\param ctx pointer to an ecEncCtx object. Mandatory for the Montgomery
2406+
curves, for the same reason as in wc_ecc_encrypt_ex2.
2407+
2408+
\sa wc_ecc_encrypt_ex2
2409+
\sa wc_ecc_ctx_set_curve_id
2410+
\sa wc_ecc_decrypt
2411+
*/
2412+
2413+
int wc_ecc_decrypt_ex2(void* privKey, void* pubKey, const byte* msg,
2414+
word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);
2415+
22462416

22472417
/*!
22482418
\ingroup ECC

0 commit comments

Comments
 (0)