diff --git a/doc/dox_comments/header_files/ecc.h b/doc/dox_comments/header_files/ecc.h index 0236d8c7e..97de1641b 100644 --- a/doc/dox_comments/header_files/ecc.h +++ b/doc/dox_comments/header_files/ecc.h @@ -1539,6 +1539,7 @@ int wc_ecc_sig_size(ecc_key* key); \endcode \sa wc_ecc_encrypt + \sa wc_ecc_encrypt_ex \sa wc_ecc_decrypt */ WOLFSSL_API @@ -1759,12 +1760,77 @@ int wc_ecc_ctx_set_info(ecEncCtx*, const byte* info, int sz); } \endcode + \sa wc_ecc_encrypt_ex \sa wc_ecc_decrypt */ WOLFSSL_API int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx); +/*! + \ingroup ECC + + \brief This function encrypts the given input message from msg + to out. This function takes an optional ctx object as parameter. + When supplied, encryption proceeds based on the ecEncCtx's + encAlgo, kdfAlgo, and macAlgo. If ctx is not supplied, processing + completes with the default algorithms, ecAES_128_CBC, + ecHKDF_SHA256 and ecHMAC_SHA256. This function requires that + the messages are padded according to the encryption type specified by ctx. + + \return 0 Returned upon successfully encrypting the input message + \return BAD_FUNC_ARG Returned if privKey, pubKey, msg, msgSz, out, + or outSz are NULL, or the ctx object specifies an unsupported + encryption type + \return BAD_ENC_STATE_E Returned if the ctx object given is in a + state that is not appropriate for encryption + \return BUFFER_E Returned if the supplied output buffer is too + small to store the encrypted ciphertext + \return MEMORY_E Returned if there is an error allocating memory + for the shared secret key + + \param privKey pointer to the ecc_key object containing the + private key to use for encryption + \param pubKey pointer to the ecc_key object containing the public + key of the peer with whom one wishes to communicate + \param msg pointer to the buffer holding the message to encrypt + \param msgSz size of the buffer to encrypt + \param out pointer to the buffer in which to store the encrypted + ciphertext + \param outSz pointer to a word32 object containing the available + size in the out buffer. Upon successfully encrypting the message, + holds the number of bytes written to the output buffer + \param ctx Optional: pointer to an ecEncCtx object specifying different + encryption algorithms to use + \param compressed Public key field is to be output in compressed format. + + _Example_ + \code + byte msg[] = { initialize with msg to encrypt. Ensure padded to block size }; + byte out[sizeof(msg)]; + word32 outSz = sizeof(out); + int ret; + ecc_key cli, serv; + // initialize cli with private key + // initialize serv with received public key + + ecEncCtx* cliCtx, servCtx; + // initialize cliCtx and servCtx + // exchange salts + ret = wc_ecc_encrypt_ex(&cli, &serv, msg, sizeof(msg), out, &outSz, cliCtx, + 1); + if(ret != 0) { + // error encrypting message + } + \endcode + + \sa wc_ecc_encrypt + \sa wc_ecc_decrypt +*/ +WOLFSSL_API +int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx, int compressed); + /*! \ingroup ECC @@ -1822,6 +1888,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, \endcode \sa wc_ecc_encrypt + \sa wc_ecc_encrypt_ex */ WOLFSSL_API int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 1487f1712..5d6293cc0 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -11928,8 +11928,8 @@ static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, ctx holds non default algos and inputs msgSz should be the right size for encAlgo, i.e., already padded return 0 on success */ -int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, - word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx) +int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx, int compressed) { int ret = 0; word32 blockSz = 0; @@ -11979,7 +11979,12 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, return ret; #ifndef WOLFSSL_ECIES_OLD - pubKeySz = 1 + wc_ecc_size(privKey) * 2; + if (!compressed) { + pubKeySz = 1 + wc_ecc_size(privKey) * 2; + } + else { + pubKeySz = 1 + wc_ecc_size(privKey); + } #endif if (ctx->protocol == REQ_RESP_SERVER) { @@ -12027,7 +12032,7 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) return ret; } - ret = wc_ecc_export_x963(privKey, out, &pubKeySz); + ret = wc_ecc_export_x963_ex(privKey, out, &pubKeySz, compressed); if (ret != 0) return ret; out += pubKeySz; @@ -12191,6 +12196,15 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, return ret; } +/* ecc encrypt with shared secret run through kdf + ctx holds non default algos and inputs + msgSz should be the right size for encAlgo, i.e., already padded + return 0 on success */ +int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx) +{ + return wc_ecc_encrypt_ex(privKey, pubKey, msg, msgSz, out, outSz, ctx, 0); +} /* ecc decrypt with shared secret run through kdf ctx holds non default algos and inputs @@ -12257,6 +12271,11 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, ret = ecc_public_key_size(privKey, &pubKeySz); if (ret != 0) return ret; +#ifdef HAVE_COMP_KEY + if ((msgSz > 1) && ((msg[0] == 0x02) || (msg[0] == 0x03))) { + pubKeySz = (pubKeySz / 2) + 1; + } +#endif #endif if (ctx->protocol == REQ_RESP_CLIENT) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 16080caa8..160fb26be 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -24642,6 +24642,66 @@ WOLFSSL_TEST_SUBROUTINE int ecc_encrypt_test(void) ret = -10412; goto done; } +#ifdef HAVE_COMP_KEY + /* Create new client and server contexts. */ + wc_ecc_ctx_free(srvCtx); + wc_ecc_ctx_free(cliCtx); + /* let's verify message exchange works, A is client, B is server */ + cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng); + srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng); + if (cliCtx == NULL || srvCtx == NULL) { + ret = -10416; goto done; + } + + /* get salt to send to peer */ + tmpSalt = wc_ecc_ctx_get_own_salt(cliCtx); + if (tmpSalt == NULL) { + ret = -10417; goto done; + } + XMEMCPY(cliSalt, tmpSalt, EXCHANGE_SALT_SZ); + + tmpSalt = wc_ecc_ctx_get_own_salt(srvCtx); + if (tmpSalt == NULL) { + ret = -10418; goto done; + } + XMEMCPY(srvSalt, tmpSalt, EXCHANGE_SALT_SZ); + + /* in actual use, we'd get the peer's salt over the transport */ + ret = wc_ecc_ctx_set_peer_salt(cliCtx, srvSalt); + if (ret != 0) + goto done; + ret = wc_ecc_ctx_set_peer_salt(srvCtx, cliSalt); + if (ret != 0) + goto done; + + ret = wc_ecc_ctx_set_info(cliCtx, (byte*)"wolfSSL MSGE", 11); + if (ret != 0) + goto done; + ret = wc_ecc_ctx_set_info(srvCtx, (byte*)"wolfSSL MSGE", 11); + if (ret != 0) + goto done; + + /* get encrypted msg (request) to send to B - compressed public key */ + outSz = sizeof(out); + ret = wc_ecc_encrypt_ex(userA, userB, msg, sizeof(msg), out, &outSz, cliCtx, + 1); + if (ret != 0) + goto done; + +#ifndef WOLFSSL_ECIES_OLD + wc_ecc_free(tmpKey); +#endif + /* B decrypts msg (request) from A - out has a compressed public key */ + plainSz = sizeof(plain); + ret = wc_ecc_decrypt(userB, tmpKey, out, outSz, plain, &plainSz, srvCtx); + if (ret != 0) + goto done; + + if (XMEMCMP(plain, msg, sizeof(msg)) != 0) { + ret = -10419; goto done; + } +#endif /* HAVE_COMP_KEY */ + #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 ret = ecc_encrypt_kat(&rng); #endif diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 694c12fb2..a5cc95d62 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -869,10 +869,13 @@ int wc_ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz); WOLFSSL_API int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, - word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx); + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx); +WOLFSSL_API +int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx, int compressed); WOLFSSL_API int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, - word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx); + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx); #endif /* HAVE_ECC_ENCRYPT */