Fixes and improvements for crypto callbacks with TLS (mutual auth) (#4437)

* This PR resolves issues with using TLS client authentication (mutual auth) with crypto callbacks. The TLS client auth will not be sent without a private key being set. The solution is to allow setting a public key only if crypto callbacks is enabled and a devId is set.

* Fix to allow using crypto callbacks with TLS mutual authentication where a private key is not available.
* Fix for ED25519 sign when only a private key is loaded.
* Fix to enable crypto callbacks for ED25519 and Curve25519 in TLS by using the _ex init functions.
* Fix for wc_PemToDer return code where a PKCS8 header does not exist.
* Remove duplicate logs in DoCertificateVerify.
* Doxygen API updates: Added crypto callback help and updated use_PrivateKey with info about public key use.

* * Added crypto callback tests for TLS client and server with mutual auth for RSA, ECC and ED25519.
* Enhanced the API unit test TLS code to allow setting CA, cert and key.

* Revert ED25519 changes. Opt to calculate public key directly when required for signing in the TLS crypto callback test. Build configuration fixes.

* Fix to use proper devId in `ProcessBufferTryDecode`.

* Various build fixes due to changes in PR. G++ issue with `missing-field-initializers`. Unused api.c func with DTLS and session export. Duplicate `eccKeyPubFile` def.

* Added crypto callback TLS tests at WOLFSSL object level. Fix for ED25519/ED448 with client mutual auth where the private key is not set till WOLFSSL object. Fix issues with  `wolfSSL_CTX_GetDevId` where devId is set on WOLFSSL object. Enable the `_id` API's for crypto callbacks.

* Proper fix for `eccKeyPubFile` name conflict. Was causing RSA test to fail (expected DER, not PEM).
pull/4456/head
David Garske 2021-10-06 18:12:06 -07:00 committed by GitHub
parent 928f4ad430
commit 9d2082f7e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 798 additions and 124 deletions

View File

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwwPRK/45pDJFO1PIhCsq
fHSavaoqUgdH1qY2sgcyjtC6aXvGw0Se1IFI/S1oootnu6F1yDYsStIb94u6zw35
7+zxgR57mwNHmr9lzH9lJGmm6BSJW+Q098WwFJP1Z3s6enjhAVZWkaYTQo3SPECc
TO/Rht83URsMoTv18aNKNeThzpbfG36/TpfQEOioCDCBryALQxTFdGe0MoJvjYbC
iECZNoO6HkByIhfXUmUkc7DO7xnNrv94bHvAEgPUTnINUG07ozujmV6dyNkMhbPZ
itlUJttt+qy7/yVMxNF59HHThkAYE7BjtXJOMMSXhIYtVi/XFfd/wK71/Fvl+6G6
0wIDAQAB
-----END PUBLIC KEY-----

View File

@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U
6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ihf/DPGNqREQI0huggWDMLgDSJ2A==
-----END PUBLIC KEY-----

View File

@ -14,6 +14,7 @@ EXTRA_DIST += \
certs/client-crl-dist.pem \
certs/client-crl-dist.der \
certs/ecc-key.pem \
certs/ecc-keyPub.pem \
certs/ecc-privkey.pem \
certs/ecc-privkeyPkcs8.der \
certs/ecc-privkeyPkcs8.pem \
@ -34,13 +35,13 @@ EXTRA_DIST += \
certs/server-ecc-rsa.pem \
certs/server-keyEnc.pem \
certs/server-key.pem \
certs/server-keyPub.pem \
certs/server-keyPkcs8.der \
certs/server-keyPkcs8Enc12.pem \
certs/server-keyPkcs8Enc2.pem \
certs/server-keyPkcs8Enc.pem \
certs/server-keyPkcs8Enc.der \
certs/server-keyPkcs8.pem \
certs/server-pub-key.pem \
certs/server-revoked-cert.pem \
certs/server-revoked-key.pem \
certs/wolfssl-website-ca.pem \
@ -71,6 +72,7 @@ EXTRA_DIST += \
certs/client-key.der \
certs/client-ecc-cert.der \
certs/client-keyPub.der \
certs/client-keyPub.pem \
certs/dh2048.der \
certs/dh3072.der \
certs/dh4096.der \

View File

@ -86,6 +86,25 @@ run_renewcerts(){
mv tmp.pem client-uri-cert.pem
echo "End of section"
echo "---------------------------------------------------------------------"
############################################################
# Public Versions of client-key.pem
############################################################
openssl rsa -inform pem -in certs/client-key.pem -outform der -out certs/client-keyPub.der -pubout
openssl rsa -inform pem -in certs/client-key.pem -outform pem -out certs/client-keyPub.pem -pubout
############################################################
# Public Versions of server-key.pem
############################################################
#openssl rsa -inform pem -in certs/server-key.pem -outform der -out certs/server-keyPub.der -pubout
openssl rsa -inform pem -in certs/server-key.pem -outform pem -out certs/server-keyPub.pem -pubout
############################################################
# Public Versions of ecc-key.pem
############################################################
#openssl ec -inform pem -in certs/ecc-key.pem -outform der -out certs/ecc-keyPub.der -pubout
openssl ec -inform pem -in certs/ecc-key.pem -outform pem -out certs/ecc-keyPub.pem -pubout
############################################################
#### update the self-signed (2048-bit) client-relative-uri.pem
############################################################

View File

@ -0,0 +1,111 @@
/*!
\ingroup CryptoCb
\brief This function registers a unique device identifier (devID) and
callback function for offloading crypto operations to external
hardware such as Key Store, Secure Element, HSM, PKCS11 or TPM.
For STSAFE with Crypto Callbacks example see
wolfcrypt/src/port/st/stsafe.c and the wolfSSL_STSAFE_CryptoDevCb function.
For TPM based crypto callbacks example see the wolfTPM2_CryptoDevCb
function in wolfTPM src/tpm2_wrap.c
\return CRYPTOCB_UNAVAILABLE to fallback to using software crypto
\return 0 for success
\return negative value for failure
\param devId any unique value, not -2 (INVALID_DEVID)
\param cb a callback function with prototype:
typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx);
_Example_
\code
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/cryptocb.h>
static int myCryptoCb_Func(int devId, wc_CryptoInfo* info, void* ctx)
{
int ret = CRYPTOCB_UNAVAILABLE;
if (info->algo_type == WC_ALGO_TYPE_PK) {
#ifndef NO_RSA
if (info->pk.type == WC_PK_TYPE_RSA) {
switch (info->pk.rsa.type) {
case RSA_PUBLIC_ENCRYPT:
case RSA_PUBLIC_DECRYPT:
// RSA public op
ret = wc_RsaFunction(
info->pk.rsa.in, info->pk.rsa.inLen,
info->pk.rsa.out, info->pk.rsa.outLen,
info->pk.rsa.type, info->pk.rsa.key,
info->pk.rsa.rng);
break;
case RSA_PRIVATE_ENCRYPT:
case RSA_PRIVATE_DECRYPT:
// RSA private op
ret = wc_RsaFunction(
info->pk.rsa.in, info->pk.rsa.inLen,
info->pk.rsa.out, info->pk.rsa.outLen,
info->pk.rsa.type, info->pk.rsa.key,
info->pk.rsa.rng);
break;
}
}
#endif
#ifdef HAVE_ECC
if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
// ECDSA
ret = wc_ecc_sign_hash(
info->pk.eccsign.in, info->pk.eccsign.inlen,
info->pk.eccsign.out, info->pk.eccsign.outlen,
info->pk.eccsign.rng, info->pk.eccsign.key);
}
#endif
#ifdef HAVE_ED25519
if (info->pk.type == WC_PK_TYPE_ED25519_SIGN) {
// ED25519 sign
ret = wc_ed25519_sign_msg_ex(
info->pk.ed25519sign.in, info->pk.ed25519sign.inLen,
info->pk.ed25519sign.out, info->pk.ed25519sign.outLen,
info->pk.ed25519sign.key, info->pk.ed25519sign.type,
info->pk.ed25519sign.context,
info->pk.ed25519sign.contextLen);
}
#endif
}
return ret;
}
int devId = 1;
wc_CryptoCb_RegisterDevice(devId, myCryptoCb_Func, &myCtx);
wolfSSL_CTX_SetDevId(ctx, devId);
\endcode
\sa wc_CryptoCb_UnRegisterDevice
\sa wolfSSL_SetDevId
\sa wolfSSL_CTX_SetDevId
*/
WOLFSSL_API int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx);
/*!
\ingroup CryptoCb
\brief This function un-registers a unique device identifier (devID)
callback function.
\return none No returns.
\param devId any unique value, not -2 (INVALID_DEVID)
_Example_
\code
wc_CryptoCb_UnRegisterDevice(devId);
devId = INVALID_DEVID;
wolfSSL_CTX_SetDevId(ctx, devId);
\endcode
\sa wc_CryptoCb_RegisterDevice
\sa wolfSSL_SetDevId
\sa wolfSSL_CTX_SetDevId
*/
WOLFSSL_API void wc_CryptoCb_UnRegisterDevice(int devId);

View File

@ -6,6 +6,7 @@
\defgroup Camellia Algorithms - Camellia
\defgroup ChaCha Algorithms - ChaCha
\defgroup ChaCha20Poly1305 Algorithms - ChaCha20_Poly1305
\defgroup Crypto Callbacks - CryptoCb
\defgroup Curve25519 Algorithms - Curve25519
\defgroup Curve448 Algorithms - Curve448
\defgroup DSA Algorithms - DSA

View File

@ -33,6 +33,7 @@
<li>\ref Camellia</li>
<li>\ref ChaCha</li>
<li>\ref ChaCha20Poly1305</li>
<li>\ref Crypto Callbacks</li>
<li>\ref Curve25519</li>
<li>\ref Curve448</li>
<li>\ref DSA</li>

View File

@ -906,6 +906,13 @@ WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int)
argument specifies the format type of the file - SSL_FILETYPE_ASN1or
SSL_FILETYPE_PEM. Please see the examples for proper usage.
If using an external key store and do not have the private key you can
instead provide the public key and register the crypro callback to handle
the signing. For this you can build with --enable-cryptocb or
WOLF_CRYPTO_CB and register a crypto callback using
wc_CryptoCb_RegisterDevice and set the associated devId using
wolfSSL_CTX_SetDevId.
\return SSL_SUCCESS upon success.
\return SSL_FAILURE The file is in the wrong format, or the wrong format
has been given using the format argument. The file doesnt exist, cant
@ -931,6 +938,8 @@ WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int)
\sa wolfSSL_CTX_use_PrivateKey_buffer
\sa wolfSSL_use_PrivateKey_file
\sa wolfSSL_use_PrivateKey_buffer
\sa wc_CryptoCb_RegisterDevice
\sa wolfSSL_CTX_SetDevId
*/
WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int);
@ -1311,6 +1320,13 @@ WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int);
The format argument specifies the format type of the file -
SSL_FILETYPE_ASN1 or SSL_FILETYPE_PEM.
If using an external key store and do not have the private key you can
instead provide the public key and register the crypro callback to handle
the signing. For this you can build with --enable-cryptocb or
WOLF_CRYPTO_CB and register a crypto callback using
wc_CryptoCb_RegisterDevice and set the associated devId using
wolfSSL_SetDevId.
\return SSL_SUCCESS upon success.
\return SSL_FAILURE If the function call fails, possible causes might
include: The file is in the wrong format, or the wrong format has been
@ -1340,6 +1356,8 @@ WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int);
\sa wolfSSL_CTX_use_PrivateKey_buffer
\sa wolfSSL_CTX_use_PrivateKey_file
\sa wolfSSL_use_PrivateKey_buffer
\sa wc_CryptoCb_RegisterDevice
\sa wolfSSL_SetDevId
*/
WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, int);

View File

@ -6705,19 +6705,19 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
case DYNAMIC_TYPE_ED25519:
wc_ed25519_init((ed25519_key*)*pKey);
wc_ed25519_init_ex((ed25519_key*)*pKey, ssl->heap, ssl->devId);
ret = 0;
break;
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_CURVE25519
case DYNAMIC_TYPE_CURVE25519:
wc_curve25519_init((curve25519_key*)*pKey);
wc_curve25519_init_ex((curve25519_key*)*pKey, ssl->heap, ssl->devId);
ret = 0;
break;
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED448
case DYNAMIC_TYPE_ED448:
wc_ed448_init((ed448_key*)*pKey);
wc_ed448_init_ex((ed448_key*)*pKey, ssl->heap, ssl->devId);
ret = 0;
break;
#endif /* HAVE_CURVE448 */
@ -6768,19 +6768,21 @@ static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
#ifdef HAVE_ED25519
case DYNAMIC_TYPE_ED25519:
wc_ed25519_free((ed25519_key*)pKey);
ret = wc_ed25519_init((ed25519_key*)pKey);
ret = wc_ed25519_init_ex((ed25519_key*)pKey, ssl->heap,
ssl->devId);
break;
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_CURVE25519
case DYNAMIC_TYPE_CURVE25519:
wc_curve25519_free((curve25519_key*)pKey);
ret = wc_curve25519_init((curve25519_key*)pKey);
ret = wc_curve25519_init_ex((curve25519_key*)pKey, ssl->heap,
ssl->devId);
break;
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED448
case DYNAMIC_TYPE_ED448:
wc_ed448_free((ed448_key*)pKey);
ret = wc_ed448_init((ed448_key*)pKey);
ret = wc_ed448_init_ex((ed448_key*)pKey, ssl->heap, ssl->devId);
break;
#endif /* HAVE_CURVE448 */
#ifdef HAVE_CURVE448
@ -22073,6 +22075,15 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
/* Decode the key assuming it is an RSA private key. */
ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
(RsaKey*)ssl->hsKey, ssl->buffers.key->length);
#ifdef WOLF_CRYPTO_CB
/* if using crypto callbacks allow using a public key */
if (ret != 0 && ssl->devId != INVALID_DEVID) {
WOLFSSL_MSG("Trying RSA public key with crypto callbacks");
idx = 0;
ret = wc_RsaPublicKeyDecode(ssl->buffers.key->buffer, &idx,
(RsaKey*)ssl->hsKey, ssl->buffers.key->length);
}
#endif
if (ret == 0) {
WOLFSSL_MSG("Using RSA private key");
@ -22119,6 +22130,16 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx,
(ecc_key*)ssl->hsKey,
ssl->buffers.key->length);
#ifdef WOLF_CRYPTO_CB
/* if using crypto callbacks allow using a public key */
if (ret != 0 && ssl->devId != INVALID_DEVID) {
WOLFSSL_MSG("Trying ECC public key with crypto callbacks");
idx = 0;
ret = wc_EccPublicKeyDecode(ssl->buffers.key->buffer, &idx,
(ecc_key*)ssl->hsKey,
ssl->buffers.key->length);
}
#endif
if (ret == 0) {
WOLFSSL_MSG("Using ECC private key");
@ -22162,6 +22183,16 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx,
(ed25519_key*)ssl->hsKey,
ssl->buffers.key->length);
#ifdef WOLF_CRYPTO_CB
/* if using crypto callbacks allow using a public key */
if (ret != 0 && ssl->devId != INVALID_DEVID) {
WOLFSSL_MSG("Trying ED25519 public key with crypto callbacks");
idx = 0;
ret = wc_Ed25519PublicKeyDecode(ssl->buffers.key->buffer, &idx,
(ed25519_key*)ssl->hsKey,
ssl->buffers.key->length);
}
#endif
if (ret == 0) {
WOLFSSL_MSG("Using ED25519 private key");
@ -22197,7 +22228,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
#elif !defined(NO_RSA)
WOLFSSL_MSG("Trying ED448 private key, RSA didn't work");
#else
WOLFSSL_MSG("Trying ED447 private key");
WOLFSSL_MSG("Trying ED448 private key");
#endif
/* Set start of data to beginning of buffer. */

View File

@ -2325,10 +2325,10 @@ WOLFSSL_ABI
int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
{
int devId = INVALID_DEVID;
if (ctx != NULL)
devId = ctx->devId;
else if (ssl != NULL)
if (ssl != NULL)
devId = ssl->devId;
if (ctx != NULL && devId == INVALID_DEVID)
devId = ctx->devId;
return devId;
}
void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
@ -5354,13 +5354,22 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
ret = wc_InitRsaKey_ex(key, heap, devId);
if (ret == 0) {
*idx = 0;
if (wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length)
!= 0) {
ret = wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length);
#ifdef WOLF_CRYPTO_CB
if (ret != 0 && devId != INVALID_DEVID) {
/* if using crypto callbacks, try public key decode */
*idx = 0;
ret = wc_RsaPublicKeyDecode(der->buffer, idx, key, der->length);
}
#endif
if (ret != 0) {
#if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
!defined(HAVE_ED448)
WOLFSSL_MSG("RSA decode failed and ECC/ED25519/ED448 not "
"enabled to try");
ret = WOLFSSL_BAD_FILE;
#else
ret = 0; /* continue trying other algorithms */
#endif
}
else {
@ -5415,8 +5424,15 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
if (wc_ecc_init_ex(key, heap, devId) == 0) {
*idx = 0;
if (wc_EccPrivateKeyDecode(der->buffer, idx, key,
der->length) == 0) {
ret = wc_EccPrivateKeyDecode(der->buffer, idx, key, der->length);
#ifdef WOLF_CRYPTO_CB
if (ret != 0 && devId != INVALID_DEVID) {
/* if using crypto callbacks, try public key decode */
*idx = 0;
ret = wc_EccPublicKeyDecode(der->buffer, idx, key, der->length);
}
#endif
if (ret == 0) {
/* check for minimum ECC key size and then free */
int minKeySz = ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz;
@ -5442,6 +5458,9 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
*resetSuites = 1;
}
}
else {
ret = 0; /* continue trying other algorithms */
}
wc_ecc_free(key);
}
@ -5467,11 +5486,18 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
return MEMORY_E;
#endif
ret = wc_ed25519_init(key);
ret = wc_ed25519_init_ex(key, heap, devId);
if (ret == 0) {
*idx = 0;
if (wc_Ed25519PrivateKeyDecode(der->buffer, idx, key,
der->length) == 0) {
ret = wc_Ed25519PrivateKeyDecode(der->buffer, idx, key, der->length);
#ifdef WOLF_CRYPTO_CB
if (ret != 0 && devId != INVALID_DEVID) {
/* if using crypto callbacks, try public key decode */
*idx = 0;
ret = wc_Ed25519PublicKeyDecode(der->buffer, idx, key, der->length);
}
#endif
if (ret == 0) {
/* check for minimum key size and then free */
int minKeySz = ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz;
@ -5491,11 +5517,19 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
}
*keyFormat = ED25519k;
if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
*resetSuites = 1;
if (ssl != NULL) {
/* ED25519 requires caching enabled for tracking message
* hash used in EdDSA_Update for signing */
ssl->options.cacheMessages = 1;
if (ssl->options.side == WOLFSSL_SERVER_END) {
*resetSuites = 1;
}
}
}
}
else {
ret = 0; /* continue trying other algorithms */
}
wc_ed25519_free(key);
}
@ -5549,8 +5583,13 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der
}
*keyFormat = ED448k;
if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
*resetSuites = 1;
if (ssl != NULL) {
/* ED448 requires caching enabled for tracking message
* hash used in EdDSA_Update for signing */
ssl->options.cacheMessages = 1;
if (ssl->options.side == WOLFSSL_SERVER_END) {
*resetSuites = 1;
}
}
}
@ -16070,7 +16109,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
return ret;
}
#ifdef HAVE_PKCS11
#if defined(HAVE_PKCS11) || defined(WOLF_CRYPTO_CB)
int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
long sz, int devId, long keySz)
{
@ -16124,7 +16163,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
return ret;
}
#endif
#endif /* HAVE_PKCS11 || WOLF_CRYPTO_CB */
int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz, int format)

View File

@ -6656,8 +6656,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
{
#ifndef NO_RSA
if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) {
WOLFSSL_MSG("Doing RSA peer cert verify");
ret = RsaVerify(ssl, sig->buffer, (word32)sig->length, &args->output,
args->sigAlgo, args->hashAlgo, ssl->peerRsaKey,
#ifdef HAVE_PK_CALLBACKS
@ -6674,8 +6672,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
#endif /* !NO_RSA */
#ifdef HAVE_ECC
if (ssl->peerEccDsaKeyPresent) {
WOLFSSL_MSG("Doing ECC peer cert verify");
ret = EccVerify(ssl, input + args->idx, args->sz,
args->sigData, args->sigDataSz,
ssl->peerEccDsaKey,
@ -6694,8 +6690,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
if (ssl->peerEd25519KeyPresent) {
WOLFSSL_MSG("Doing ED25519 peer cert verify");
ret = Ed25519Verify(ssl, input + args->idx, args->sz,
args->sigData, args->sigDataSz,
ssl->peerEd25519Key,
@ -6715,8 +6709,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
#endif
#ifdef HAVE_ED448
if (ssl->peerEd448KeyPresent) {
WOLFSSL_MSG("Doing ED448 peer cert verify");
ret = Ed448Verify(ssl, input + args->idx, args->sz,
args->sigData, args->sigDataSz,
ssl->peerEd448Key,

View File

@ -4820,20 +4820,33 @@ done:
#endif /* defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TIRTOS) && !defined(NO_WOLFSSL_CLIENT) */
}
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) && \
defined(HAVE_ALPN) && defined(HAVE_SNI) && \
defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_BIO)
#define HAVE_ALPN_PROTOS_SUPPORT
#endif
/* SNI / ALPN / session export helper functions */
#if defined(HAVE_SNI) || defined(HAVE_ALPN) ||\
(defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS))
/* Generic TLS client / server with callbacks for API unit tests
* Used by SNI / ALPN / crypto callback helper functions */
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && \
(defined(HAVE_SNI) || defined(HAVE_ALPN) || defined(WOLF_CRYPTO_CB) || \
defined(HAVE_ALPN_PROTOS_SUPPORT))
#define ENABLE_TLS_CALLBACK_TEST
#endif
#if defined(ENABLE_TLS_CALLBACK_TEST) || \
(defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT))
/* TLS server for API unit testing - generic */
static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
{
callback_functions* callbacks = ((func_args*)args)->callbacks;
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(callbacks->method());
WOLFSSL_CTX* ctx;
WOLFSSL* ssl = NULL;
SOCKET_T sfd = 0;
SOCKET_T cfd = 0;
word16 port;
SOCKET_T sfd = 0;
SOCKET_T cfd = 0;
word16 port;
char msg[] = "I hear you fa shizzle!";
int len = (int) XSTRLEN(msg);
@ -4841,10 +4854,27 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
int idx;
int ret, err = 0;
((func_args*)args)->return_code = TEST_FAIL;
ctx = wolfSSL_CTX_new(callbacks->method());
if (ctx == NULL) {
printf("CTX new failed\n");
return 0;
}
/* set defaults */
if (callbacks->caPemFile == NULL)
callbacks->caPemFile = cliCertFile;
if (callbacks->certPemFile == NULL)
callbacks->certPemFile = svrCertFile;
if (callbacks->keyPemFile == NULL)
callbacks->keyPemFile = svrKeyFile;
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
((func_args*)args)->return_code = TEST_FAIL;
wolfSSL_CTX_SetDevId(ctx, callbacks->devId);
#if defined(USE_WINDOWS_API)
port = ((func_args*)args)->signal->port;
@ -4869,19 +4899,25 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0));
wolfSSL_CTX_load_verify_locations(ctx, callbacks->caPemFile, 0));
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
wolfSSL_CTX_use_certificate_file(ctx, callbacks->certPemFile,
WOLFSSL_FILETYPE_PEM));
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM));
wolfSSL_CTX_use_PrivateKey_file(ctx, callbacks->keyPemFile,
WOLFSSL_FILETYPE_PEM));
if (callbacks->ctx_ready)
callbacks->ctx_ready(ctx);
ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
printf("SSL new failed\n");
wolfSSL_CTX_free(ctx);
return 0;
}
if (wolfSSL_dtls(ssl)) {
SOCKADDR_IN_T cliAddr;
socklen_t cliLen;
@ -4900,6 +4936,18 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, cfd));
if (callbacks->loadToSSL) {
wolfSSL_SetDevId(ssl, callbacks->devId);
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_use_certificate_file(ssl, callbacks->certPemFile,
WOLFSSL_FILETYPE_PEM));
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_use_PrivateKey_file(ssl, callbacks->keyPemFile,
WOLFSSL_FILETYPE_PEM));
}
#ifdef NO_PSK
#if !defined(NO_FILESYSTEM) && !defined(NO_DH)
wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM);
@ -4982,11 +5030,12 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
#endif
}
/* TLS Client for API unit testing - generic */
static void run_wolfssl_client(void* args)
{
callback_functions* callbacks = ((func_args*)args)->callbacks;
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(callbacks->method());
WOLFSSL_CTX* ctx;
WOLFSSL* ssl = NULL;
SOCKET_T sfd = 0;
@ -4996,23 +5045,46 @@ static void run_wolfssl_client(void* args)
int idx;
int ret, err = 0;
((func_args*)args)->return_code = TEST_FAIL;
/* set defaults */
if (callbacks->caPemFile == NULL)
callbacks->caPemFile = caCertFile;
if (callbacks->certPemFile == NULL)
callbacks->certPemFile = cliCertFile;
if (callbacks->keyPemFile == NULL)
callbacks->keyPemFile = cliKeyFile;
ctx = wolfSSL_CTX_new(callbacks->method());
if (ctx == NULL) {
printf("CTX new failed\n");
return;
}
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
((func_args*)args)->return_code = TEST_FAIL;
if (!callbacks->loadToSSL) {
wolfSSL_CTX_SetDevId(ctx, callbacks->devId);
}
#ifdef WOLFSSL_ENCRYPTED_KEYS
wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif
AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0));
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_load_verify_locations(ctx, callbacks->caPemFile, 0));
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM));
if (!callbacks->loadToSSL) {
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_certificate_file(ctx, callbacks->certPemFile,
WOLFSSL_FILETYPE_PEM));
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, WOLFSSL_FILETYPE_PEM));
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_CTX_use_PrivateKey_file(ctx, callbacks->keyPemFile,
WOLFSSL_FILETYPE_PEM));
}
if (callbacks->ctx_ready)
callbacks->ctx_ready(ctx);
@ -5028,6 +5100,18 @@ static void run_wolfssl_client(void* args)
}
AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, sfd));
if (callbacks->loadToSSL) {
wolfSSL_SetDevId(ssl, callbacks->devId);
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_use_certificate_file(ssl, callbacks->certPemFile,
WOLFSSL_FILETYPE_PEM));
AssertIntEQ(WOLFSSL_SUCCESS,
wolfSSL_use_PrivateKey_file(ssl, callbacks->keyPemFile,
WOLFSSL_FILETYPE_PEM));
}
if (callbacks->ssl_ready)
callbacks->ssl_ready(ssl);
@ -5073,8 +5157,8 @@ static void run_wolfssl_client(void* args)
#endif
}
#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) ||
defined(WOLFSSL_SESSION_EXPORT) */
#endif /* ENABLE_TLS_CALLBACK_TEST */
static void test_wolfSSL_read_write(void)
{
@ -6092,8 +6176,8 @@ static void test_wolfSSL_tls_export(void)
| TLS extensions tests
*----------------------------------------------------------------------------*/
#if defined(HAVE_SNI) || defined(HAVE_ALPN)
/* connection test runner */
#ifdef ENABLE_TLS_CALLBACK_TEST
/* Connection test runner - generic */
static void test_wolfSSL_client_server(callback_functions* client_callbacks,
callback_functions* server_callbacks)
{
@ -6135,8 +6219,12 @@ static void test_wolfSSL_client_server(callback_functions* client_callbacks,
#ifdef WOLFSSL_TIRTOS
fdCloseSession(Task_self());
#endif
client_callbacks->return_code = client_args.return_code;
server_callbacks->return_code = server_args.return_code;
}
#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) */
#endif /* ENABLE_TLS_CALLBACK_TEST */
#ifdef HAVE_SNI
static void test_wolfSSL_UseSNI_params(void)
@ -6267,58 +6355,69 @@ static void verify_FATAL_ERROR_on_client(WOLFSSL* ssl)
}
/* END of connection tests callbacks */
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
static void test_wolfSSL_UseSNI_connection(void)
{
unsigned long i;
callback_functions callbacks[] = {
/* success case at ctx */
{0, use_SNI_at_ctx, 0, 0, 0, 0},
{0, use_SNI_at_ctx, 0, verify_SNI_real_matching, 0, 0},
{.ctx_ready = use_SNI_at_ctx},
{.ctx_ready = use_SNI_at_ctx, .on_result = verify_SNI_real_matching},
/* success case at ssl */
{0, 0, use_SNI_at_ssl, verify_SNI_real_matching, 0, 0},
{0, 0, use_SNI_at_ssl, verify_SNI_real_matching, 0, 0},
{.ssl_ready = use_SNI_at_ssl, .on_result = verify_SNI_real_matching},
{.ssl_ready = use_SNI_at_ssl, .on_result = verify_SNI_real_matching},
/* default mismatch behavior */
{0, 0, different_SNI_at_ssl, verify_FATAL_ERROR_on_client, 0, 0},
{0, 0, use_SNI_at_ssl, verify_UNKNOWN_SNI_on_server, 0, 0},
{.ssl_ready = different_SNI_at_ssl, .on_result = verify_FATAL_ERROR_on_client},
{.ssl_ready = use_SNI_at_ssl, .on_result = verify_UNKNOWN_SNI_on_server},
/* continue on mismatch */
{0, 0, different_SNI_at_ssl, 0, 0, 0},
{0, 0, use_SNI_WITH_CONTINUE_at_ssl, verify_SNI_no_matching, 0, 0},
{.ssl_ready = different_SNI_at_ssl},
{.ssl_ready = use_SNI_WITH_CONTINUE_at_ssl, .on_result = verify_SNI_no_matching},
/* fake answer on mismatch */
{0, 0, different_SNI_at_ssl, 0, 0, 0},
{0, 0, use_SNI_WITH_FAKE_ANSWER_at_ssl, verify_SNI_fake_matching, 0, 0},
{.ssl_ready = different_SNI_at_ssl},
{.ssl_ready = use_SNI_WITH_FAKE_ANSWER_at_ssl, .on_result = verify_SNI_fake_matching},
/* sni abort - success */
{0, use_SNI_at_ctx, 0, 0, 0, 0},
{0, use_MANDATORY_SNI_at_ctx, 0, verify_SNI_real_matching, 0, 0},
{.ctx_ready = use_SNI_at_ctx},
{.ctx_ready = use_MANDATORY_SNI_at_ctx, .on_result = verify_SNI_real_matching},
/* sni abort - abort when absent (ctx) */
{0, 0, 0, verify_FATAL_ERROR_on_client, 0, 0},
{0, use_MANDATORY_SNI_at_ctx, 0, verify_SNI_ABSENT_on_server, 0, 0},
{ .on_result = verify_FATAL_ERROR_on_client},
{.ctx_ready = use_MANDATORY_SNI_at_ctx, .on_result = verify_SNI_ABSENT_on_server},
/* sni abort - abort when absent (ssl) */
{0, 0, 0, verify_FATAL_ERROR_on_client, 0, 0},
{0, 0, use_MANDATORY_SNI_at_ssl, verify_SNI_ABSENT_on_server, 0, 0},
{ .on_result = verify_FATAL_ERROR_on_client},
{.ssl_ready = use_MANDATORY_SNI_at_ssl, .on_result = verify_SNI_ABSENT_on_server},
/* sni abort - success when overwritten */
{0, 0, 0, 0, 0, 0},
{0, use_MANDATORY_SNI_at_ctx, use_SNI_at_ssl, verify_SNI_no_matching, 0, 0},
{.ctx_ready = NULL},
{.ctx_ready = use_MANDATORY_SNI_at_ctx, .ssl_ready = use_SNI_at_ssl, .on_result = verify_SNI_no_matching},
/* sni abort - success when allowing mismatches */
{0, 0, different_SNI_at_ssl, 0, 0, 0},
{0, use_PSEUDO_MANDATORY_SNI_at_ctx, 0, verify_SNI_fake_matching, 0, 0},
{.ssl_ready = different_SNI_at_ssl},
{.ctx_ready = use_PSEUDO_MANDATORY_SNI_at_ctx, .on_result = verify_SNI_fake_matching},
};
for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) {
callbacks[i ].method = wolfSSLv23_client_method;
callbacks[i + 1].method = wolfSSLv23_server_method;
callbacks[i ].devId = devId;
callbacks[i + 1].devId = devId;
test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]);
}
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
static void test_wolfSSL_SNI_GetFromBuffer(void)
{
byte buff[] = { /* www.paypal.com */
@ -6641,8 +6740,7 @@ static void test_wolfSSL_UseSupportedCurve(void)
#endif
}
#if defined(HAVE_ALPN) && !defined(NO_WOLFSSL_SERVER) && \
defined(HAVE_IO_TESTS_DEPENDENCIES)
#if defined(HAVE_ALPN) && defined(HAVE_IO_TESTS_DEPENDENCIES)
static void verify_ALPN_FATAL_ERROR_on_client(WOLFSSL* ssl)
{
@ -6776,51 +6874,62 @@ static void verify_ALPN_client_list(WOLFSSL* ssl)
AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_FreePeerProtocol(ssl, &clist));
}
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
static void test_wolfSSL_UseALPN_connection(void)
{
unsigned long i;
callback_functions callbacks[] = {
/* success case same list */
{0, 0, use_ALPN_all, 0, 0, 0},
{0, 0, use_ALPN_all, verify_ALPN_matching_http1, 0, 0},
{.ssl_ready = use_ALPN_all},
{.ssl_ready = use_ALPN_all, .on_result = verify_ALPN_matching_http1},
/* success case only one for server */
{0, 0, use_ALPN_all, 0, 0, 0},
{0, 0, use_ALPN_one, verify_ALPN_matching_spdy2, 0, 0},
{.ssl_ready = use_ALPN_all},
{.ssl_ready = use_ALPN_one, .on_result = verify_ALPN_matching_spdy2},
/* success case only one for client */
{0, 0, use_ALPN_one, 0, 0, 0},
{0, 0, use_ALPN_all, verify_ALPN_matching_spdy2, 0, 0},
{.ssl_ready = use_ALPN_one},
{.ssl_ready = use_ALPN_all, .on_result = verify_ALPN_matching_spdy2},
/* success case none for client */
{0, 0, 0, 0, 0, 0},
{0, 0, use_ALPN_all, 0, 0, 0},
{.ssl_ready = NULL},
{.ssl_ready = use_ALPN_all},
/* success case mismatch behavior but option 'continue' set */
{0, 0, use_ALPN_all_continue, verify_ALPN_not_matching_continue, 0, 0},
{0, 0, use_ALPN_unknown_continue, 0, 0, 0},
{.ssl_ready = use_ALPN_all_continue, .on_result = verify_ALPN_not_matching_continue},
{.ssl_ready = use_ALPN_unknown_continue},
/* success case read protocol send by client */
{0, 0, use_ALPN_all, 0, 0, 0},
{0, 0, use_ALPN_one, verify_ALPN_client_list, 0, 0},
{.ssl_ready = use_ALPN_all},
{.ssl_ready = use_ALPN_one, .on_result = verify_ALPN_client_list},
/* mismatch behavior with same list
* the first and only this one must be taken */
{0, 0, use_ALPN_all, 0, 0, 0},
{0, 0, use_ALPN_all, verify_ALPN_not_matching_spdy3, 0, 0},
{.ssl_ready = use_ALPN_all},
{.ssl_ready = use_ALPN_all, .on_result = verify_ALPN_not_matching_spdy3},
/* default mismatch behavior */
{0, 0, use_ALPN_all, 0, 0, 0},
{0, 0, use_ALPN_unknown, verify_ALPN_FATAL_ERROR_on_client, 0, 0},
{.ssl_ready = use_ALPN_all},
{.ssl_ready = use_ALPN_unknown, .on_result = verify_ALPN_FATAL_ERROR_on_client},
};
for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) {
callbacks[i ].method = wolfSSLv23_client_method;
callbacks[i + 1].method = wolfSSLv23_server_method;
callbacks[i ].devId = devId;
callbacks[i + 1].devId = devId;
test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]);
}
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
static void test_wolfSSL_UseALPN_params(void)
{
#ifndef NO_WOLFSSL_CLIENT
@ -6896,11 +7005,7 @@ static void test_wolfSSL_UseALPN_params(void)
}
#endif /* HAVE_ALPN */
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) && \
(defined(HAVE_ALPN) && defined(HAVE_SNI)) &&\
defined(HAVE_IO_TESTS_DEPENDENCIES)
#ifdef HAVE_ALPN_PROTOS_SUPPORT
static void CTX_set_alpn_protos(SSL_CTX *ctx)
{
unsigned char p[] = {
@ -6919,7 +7024,6 @@ static void CTX_set_alpn_protos(SSL_CTX *ctx)
#else
AssertIntEQ(ret, SSL_SUCCESS);
#endif
}
static void set_alpn_protos(SSL* ssl)
@ -6972,26 +7076,38 @@ static void verify_alpn_matching_http1(WOLFSSL* ssl)
AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz));
}
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
static void test_wolfSSL_set_alpn_protos(void)
{
unsigned long i;
callback_functions callbacks[] = {
/* use CTX_alpn_protos */
{0, CTX_set_alpn_protos, 0, 0, 0, 0},
{0, CTX_set_alpn_protos, 0, verify_alpn_matching_http1, 0, 0},
{.ctx_ready = CTX_set_alpn_protos},
{.ctx_ready = CTX_set_alpn_protos, .on_result = verify_alpn_matching_http1},
/* use set_alpn_protos */
{0, 0, set_alpn_protos, 0, 0, 0},
{0, 0, set_alpn_protos, verify_alpn_matching_spdy3, 0, 0},
{.ssl_ready = set_alpn_protos},
{.ssl_ready = set_alpn_protos, .on_result = verify_alpn_matching_spdy3},
};
for (i = 0; i < sizeof(callbacks) / sizeof(callback_functions); i += 2) {
callbacks[i ].method = wolfSSLv23_client_method;
callbacks[i + 1].method = wolfSSLv23_server_method;
callbacks[i ].devId = devId;
callbacks[i + 1].devId = devId;
test_wolfSSL_client_server(&callbacks[i], &callbacks[i + 1]);
}
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif /* HAVE_ALPN_PROTOS_SUPPORT */
static void test_wolfSSL_UseALPN(void)
{
#if defined(HAVE_ALPN) && !defined(NO_WOLFSSL_SERVER) &&\
@ -7000,17 +7116,9 @@ static void test_wolfSSL_UseALPN(void)
test_wolfSSL_UseALPN_params();
#endif
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_BIO)
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) && \
(defined(HAVE_ALPN) && defined(HAVE_SNI)) && \
defined(HAVE_IO_TESTS_DEPENDENCIES)
#ifdef HAVE_ALPN_PROTOS_SUPPORT
test_wolfSSL_set_alpn_protos();
#endif
#endif
}
static void test_wolfSSL_DisableExtendedMasterSecret(void)
@ -30294,7 +30402,7 @@ static void test_wolfSSL_PEM_bio_RSAKey(void)
RSA_free(rsa);
/* Ensure that keys beginning with BEGIN RSA PUBLIC KEY can be read, too. */
AssertNotNull(bio = BIO_new_file("./certs/server-pub-key.pem", "rb"));
AssertNotNull(bio = BIO_new_file("./certs/server-keyPub.pem", "rb"));
AssertNotNull((rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL)));
BIO_free(bio);
RSA_free(rsa);
@ -49768,6 +49876,308 @@ static void test_SSL_CIPHER_get_xxx(void)
#endif
}
#if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES)
static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer,
int* keyFormat)
{
int ret;
byte* key_buf = NULL;
size_t key_sz = 0;
EncryptedInfo encInfo;
XMEMSET(&encInfo, 0, sizeof(encInfo));
ret = load_file(privKeyFile, &key_buf, &key_sz);
if (ret == 0) {
ret = wc_PemToDer(key_buf, key_sz, PRIVATEKEY_TYPE, pDer,
NULL, &encInfo, keyFormat);
}
if (key_buf != NULL) {
free(key_buf); key_buf = NULL;
}
(void)encInfo; /* not used in this test */
#ifdef DEBUG_WOLFSSL
printf("%s (%d): Loading PEM %s (len %d) to DER (len %d)\n",
(ret == 0) ? "Success" : "Failure", ret, privKeyFile, (int)key_sz,
(*pDer)->length);
#endif
return ret;
}
static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx)
{
int ret = CRYPTOCB_UNAVAILABLE;
const char* privKeyFile = (const char*)ctx;
DerBuffer* pDer = NULL;
int keyFormat = 0;
if (info->algo_type == WC_ALGO_TYPE_PK) {
#ifdef DEBUG_WOLFSSL
printf("test_CryptoCb_Func: Pk Type %d\n", info->pk.type);
#endif
#ifndef NO_RSA
if (info->pk.type == WC_PK_TYPE_RSA) {
switch (info->pk.rsa.type) {
case RSA_PUBLIC_ENCRYPT:
case RSA_PUBLIC_DECRYPT:
/* perform software based RSA public op */
ret = CRYPTOCB_UNAVAILABLE; /* fallback to software */
break;
case RSA_PRIVATE_ENCRYPT:
case RSA_PRIVATE_DECRYPT:
{
RsaKey key;
/* perform software based RSA private op */
#ifdef DEBUG_WOLFSSL
printf("test_CryptoCb_Func: RSA Priv\n");
#endif
ret = load_pem_key_file_as_der(privKeyFile, &pDer,
&keyFormat);
if (ret != 0) {
return ret;
}
ret = wc_InitRsaKey(&key, NULL);
if (ret == 0) {
word32 keyIdx = 0;
/* load RSA private key and perform private transform */
ret = wc_RsaPrivateKeyDecode(pDer->buffer, &keyIdx,
&key, pDer->length);
if (ret == 0) {
ret = wc_RsaFunction(
info->pk.rsa.in, info->pk.rsa.inLen,
info->pk.rsa.out, info->pk.rsa.outLen,
info->pk.rsa.type, &key, info->pk.rsa.rng);
}
else {
/* if decode fails, then fall-back to software based crypto */
printf("test_CryptoCb_Func: RSA private key decode "
"failed %d, falling back to software\n", ret);
ret = CRYPTOCB_UNAVAILABLE;
}
wc_FreeRsaKey(&key);
}
wc_FreeDer(&pDer); pDer = NULL;
break;
}
}
#ifdef DEBUG_WOLFSSL
printf("test_CryptoCb_Func: RSA Type %d, Ret %d, Out %d\n",
info->pk.rsa.type, ret, *info->pk.rsa.outLen);
#endif
}
#endif /* !NO_RSA */
#ifdef HAVE_ECC
if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
ecc_key key;
/* perform software based ECC sign */
#ifdef DEBUG_WOLFSSL
printf("test_CryptoCb_Func: ECC Sign\n");
#endif
ret = load_pem_key_file_as_der(privKeyFile, &pDer, &keyFormat);
if (ret != 0) {
return ret;
}
ret = wc_ecc_init(&key);
if (ret == 0) {
word32 keyIdx = 0;
/* load ECC private key and perform private transform */
ret = wc_EccPrivateKeyDecode(pDer->buffer, &keyIdx,
&key, pDer->length);
if (ret == 0) {
ret = wc_ecc_sign_hash(
info->pk.eccsign.in, info->pk.eccsign.inlen,
info->pk.eccsign.out, info->pk.eccsign.outlen,
info->pk.eccsign.rng, &key);
}
else {
/* if decode fails, then fall-back to software based crypto */
printf("test_CryptoCb_Func: ECC private key decode "
"failed %d, falling back to software\n", ret);
ret = CRYPTOCB_UNAVAILABLE;
}
wc_ecc_free(&key);
}
wc_FreeDer(&pDer); pDer = NULL;
#ifdef DEBUG_WOLFSSL
printf("test_CryptoCb_Func: ECC Ret %d, Out %d\n",
ret, *info->pk.eccsign.outlen);
#endif
}
#endif /* HAVE_ECC */
#ifdef HAVE_ED25519
if (info->pk.type == WC_PK_TYPE_ED25519_SIGN) {
ed25519_key key;
/* perform software based ED25519 sign */
#ifdef DEBUG_WOLFSSL
printf("test_CryptoCb_Func: ED25519 Sign\n");
#endif
ret = load_pem_key_file_as_der(privKeyFile, &pDer, &keyFormat);
if (ret != 0) {
return ret;
}
ret = wc_ed25519_init(&key);
if (ret == 0) {
word32 keyIdx = 0;
/* load ED25519 private key and perform private transform */
ret = wc_Ed25519PrivateKeyDecode(pDer->buffer, &keyIdx,
&key, pDer->length);
if (ret == 0) {
/* calculate public key */
ret = wc_ed25519_make_public(&key, key.p, ED25519_PUB_KEY_SIZE);
if (ret == 0) {
key.pubKeySet = 1;
ret = wc_ed25519_sign_msg_ex(
info->pk.ed25519sign.in, info->pk.ed25519sign.inLen,
info->pk.ed25519sign.out, info->pk.ed25519sign.outLen,
&key, info->pk.ed25519sign.type,
info->pk.ed25519sign.context,
info->pk.ed25519sign.contextLen);
}
}
else {
/* if decode fails, then fall-back to software based crypto */
printf("test_CryptoCb_Func: ED25519 private key decode "
"failed %d, falling back to software\n", ret);
ret = CRYPTOCB_UNAVAILABLE;
}
wc_ed25519_free(&key);
}
wc_FreeDer(&pDer); pDer = NULL;
#ifdef DEBUG_WOLFSSL
printf("test_CryptoCb_Func: ED25519 Ret %d, Out %d\n",
ret, *info->pk.ed25519sign.outLen);
#endif
}
#endif /* HAVE_ED25519 */
}
(void)thisDevId;
(void)keyFormat;
return ret;
}
/* tlsVer: WOLFSSL_TLSV1_2 or WOLFSSL_TLSV1_3 */
static void test_wc_CryptoCb_TLS(int tlsVer,
const char* cliCaPemFile, const char* cliCertPemFile,
const char* cliPrivKeyPemFile, const char* cliPubKeyPemFile,
const char* svrCaPemFile, const char* svrCertPemFile,
const char* svrPrivKeyPemFile, const char* svrPubKeyPemFile)
{
callback_functions client_cbf;
callback_functions server_cbf;
XMEMSET(&client_cbf, 0, sizeof(client_cbf));
XMEMSET(&server_cbf, 0, sizeof(server_cbf));
if (tlsVer == WOLFSSL_TLSV1_3) {
#ifdef WOLFSSL_TLS13
server_cbf.method = wolfTLSv1_3_server_method;
client_cbf.method = wolfTLSv1_3_client_method;
#endif
}
else if (tlsVer == WOLFSSL_TLSV1_2) {
#ifndef WOLFSSL_NO_TLS12
server_cbf.method = wolfTLSv1_2_server_method;
client_cbf.method = wolfTLSv1_2_client_method;
#endif
}
if (server_cbf.method == NULL) {
/* not enabled */
return;
}
/* Setup the keys for the TLS test */
client_cbf.certPemFile = cliCertPemFile;
client_cbf.keyPemFile = cliPubKeyPemFile;
client_cbf.caPemFile = cliCaPemFile;
server_cbf.certPemFile = svrCertPemFile;
server_cbf.keyPemFile = svrPubKeyPemFile;
server_cbf.caPemFile = svrCaPemFile;
/* Setup a crypto callback with pointer to private key file for testing */
client_cbf.devId = 1;
wc_CryptoCb_RegisterDevice(client_cbf.devId, test_CryptoCb_Func,
(void*)cliPrivKeyPemFile);
server_cbf.devId = 2;
wc_CryptoCb_RegisterDevice(server_cbf.devId, test_CryptoCb_Func,
(void*)svrPrivKeyPemFile);
/* Perform TLS server and client test */
/* First test is at WOLFSSL_CTX level */
test_wolfSSL_client_server(&client_cbf, &server_cbf);
/* Check for success */
AssertIntEQ(server_cbf.return_code, TEST_SUCCESS);
AssertIntEQ(client_cbf.return_code, TEST_SUCCESS);
/* Second test is a WOLFSSL object level */
client_cbf.loadToSSL = 1; server_cbf.loadToSSL = 1;
test_wolfSSL_client_server(&client_cbf, &server_cbf);
/* Check for success */
AssertIntEQ(server_cbf.return_code, TEST_SUCCESS);
AssertIntEQ(client_cbf.return_code, TEST_SUCCESS);
/* Un register the devId's */
wc_CryptoCb_UnRegisterDevice(client_cbf.devId);
client_cbf.devId = INVALID_DEVID;
wc_CryptoCb_UnRegisterDevice(server_cbf.devId);
server_cbf.devId = INVALID_DEVID;
}
#endif /* WOLF_CRYPTO_CB && HAVE_IO_TESTS_DEPENDENCIES */
static void test_wc_CryptoCb(void)
{
#ifdef WOLF_CRYPTO_CB
/* TODO: Add crypto callback API tests */
#ifdef HAVE_IO_TESTS_DEPENDENCIES
#ifndef NO_RSA
/* RSA */
test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_3,
svrCertFile, cliCertFile, cliKeyFile, cliKeyPubFile,
cliCertFile, svrCertFile, svrKeyFile, svrKeyPubFile);
test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_2,
svrCertFile, cliCertFile, cliKeyFile, cliKeyPubFile,
cliCertFile, svrCertFile, svrKeyFile, svrKeyPubFile);
#endif
#ifdef HAVE_ECC
/* ECC */
test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_3,
caEccCertFile, cliEccCertFile, cliEccKeyFile, cliEccKeyPubFile,
cliEccCertFile, eccCertFile, eccKeyFile, eccKeyPubFile);
test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_2,
caEccCertFile, cliEccCertFile, cliEccKeyFile, cliEccKeyPubFile,
cliEccCertFile, eccCertFile, eccKeyFile, eccKeyPubFile);
#endif
#ifdef HAVE_ED25519
/* ED25519 */
test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_3,
caEdCertFile, cliEdCertFile, cliEdKeyFile, cliEdKeyPubFile,
cliEdCertFile, edCertFile, edKeyFile, edKeyPubFile);
test_wc_CryptoCb_TLS(WOLFSSL_TLSV1_2,
caEdCertFile, cliEdCertFile, cliEdKeyFile, cliEdKeyPubFile,
cliEdCertFile, edCertFile, edKeyFile, edKeyPubFile);
#endif
#endif /* HAVE_IO_TESTS_DEPENDENCIES */
#endif /* WOLF_CRYPTO_CB */
}
/*----------------------------------------------------------------------------*
| Main
*----------------------------------------------------------------------------*/
@ -50616,6 +51026,8 @@ void ApiTest(void)
test_wolfSSL_CTX_LoadCRL();
test_wc_CryptoCb();
AssertIntEQ(test_ForceZero(), 0);
AssertIntEQ(test_wolfSSL_Cleanup(), WOLFSSL_SUCCESS);

View File

@ -6382,7 +6382,7 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
return MEMORY_E;
tmpIdx = 0;
if (wc_ed25519_init(ed25519) == 0) {
if (wc_ed25519_init_ex(ed25519, heap, INVALID_DEVID) == 0) {
if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, ed25519, keySz) == 0) {
*algoID = ED25519k;
}
@ -13034,7 +13034,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
if (sigCtx->key.ed25519 == NULL) {
ERROR_OUT(MEMORY_E, exit_cs);
}
if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) {
if ((ret = wc_ed25519_init_ex(sigCtx->key.ed25519,
sigCtx->heap, sigCtx->devId)) < 0) {
goto exit_cs;
}
if ((ret = wc_ed25519_import_public(key, keySz,
@ -18771,7 +18772,6 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
/* map header if not found for type */
for (;;) {
headerEnd = XSTRNSTR((char*)buff, header, sz);
if (headerEnd) {
break;
}
@ -18806,7 +18806,14 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
}
#endif
else {
#ifdef WOLF_CRYPTO_CB
/* allow loading a public key for use with crypto callbacks */
type = PUBLICKEY_TYPE;
header = BEGIN_PUB_KEY;
footer = END_PUB_KEY;
#else
break;
#endif
}
}
else if (type == PUBLICKEY_TYPE) {
@ -18907,18 +18914,30 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
/* eat end of line characters */
headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd);
if (type == PRIVATEKEY_TYPE) {
if (keyFormat) {
/* keyFormat is Key_Sum enum */
if (keyFormat) {
if (type == PRIVATEKEY_TYPE) {
#ifndef NO_RSA
if (header == BEGIN_RSA_PRIV)
*keyFormat = RSAk;
#endif
#ifdef HAVE_ECC
if (header == BEGIN_EC_PRIV)
*keyFormat = ECDSAk;
#endif
#if !defined(NO_DSA)
#ifndef NO_DSA
if (header == BEGIN_DSA_PRIV)
*keyFormat = DSAk;
#endif
}
#ifdef WOLF_CRYPTO_CB
else if (type == PUBLICKEY_TYPE) {
#ifndef NO_RSA
if (header == BEGIN_RSA_PUB)
*keyFormat = RSAk;
#endif
}
#endif
}
#ifdef WOLFSSL_ENCRYPTED_KEYS
@ -18993,7 +19012,6 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
return 0;
}
#ifdef WOLFSSL_ENCRYPTED_KEYS
if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) {
int passwordSz = NAME_SZ;
@ -19112,8 +19130,8 @@ int wc_PemToDer(const unsigned char* buff, long longSz, int type,
ret = ToTraditional(der->buffer, der->length);
if (ret > 0) {
der->length = ret;
ret = 0;
}
ret = 0; /* ignore error removing PKCS8 header */
}
#endif
return ret;

View File

@ -12021,8 +12021,7 @@ WOLFSSL_TEST_SUBROUTINE int memory_test(void)
#if !defined(USE_CERT_BUFFERS_256) && !defined(NO_ASN)
#if defined(HAVE_ECC) && defined(WOLFSSL_CERT_GEN)
#ifndef NO_RSA
/* eccKeyPubFile is used in a test that requires RSA. */
static const char* eccKeyPubFile = CERT_ROOT "ecc-keyPub.der";
static const char* eccKeyPubFileDer = CERT_ROOT "ecc-keyPub.der";
#endif
static const char* eccCaKeyFile = CERT_ROOT "ca-ecc-key.der";
static const char* eccCaCertFile = CERT_ROOT "ca-ecc-cert.pem";
@ -14542,7 +14541,7 @@ static int rsa_ecc_certgen_test(WC_RNG* rng, byte* tmp)
XMEMCPY(tmp, ecc_key_pub_der_256, sizeof_ecc_key_pub_der_256);
bytes3 = sizeof_ecc_key_pub_der_256;
#else
file3 = XFOPEN(eccKeyPubFile, "rb");
file3 = XFOPEN(eccKeyPubFileDer, "rb");
if (!file3) {
ERROR_OUT(-7855, exit_rsa);
}

View File

@ -335,23 +335,29 @@
#define caCertFile "certs/ca-cert.pem"
#define eccCertFile "certs/server-ecc.pem"
#define eccKeyFile "certs/ecc-key.pem"
#define eccKeyPubFile "certs/ecc-keyPub.pem"
#define eccRsaCertFile "certs/server-ecc-rsa.pem"
#define svrCertFile "certs/server-cert.pem"
#define svrKeyFile "certs/server-key.pem"
#define svrKeyPubFile "certs/server-keyPub.pem"
#define cliCertFile "certs/client-cert.pem"
#define cliCertDerFile "certs/client-cert.der"
#define cliCertFileExt "certs/client-cert-ext.pem"
#define cliCertDerFileExt "certs/client-cert-ext.der"
#define cliKeyFile "certs/client-key.pem"
#define cliKeyPubFile "certs/client-keyPub.pem"
#define dhParamFile "certs/dh2048.pem"
#define cliEccKeyFile "certs/ecc-client-key.pem"
#define cliEccKeyPubFile "certs/ecc-client-keyPub.pem"
#define cliEccCertFile "certs/client-ecc-cert.pem"
#define caEccCertFile "certs/ca-ecc-cert.pem"
#define crlPemDir "certs/crl"
#define edCertFile "certs/ed25519/server-ed25519-cert.pem"
#define edKeyFile "certs/ed25519/server-ed25519-priv.pem"
#define edKeyPubFile "certs/ed25519/server-ed25519-key.pem"
#define cliEdCertFile "certs/ed25519/client-ed25519.pem"
#define cliEdKeyFile "certs/ed25519/client-ed25519-priv.pem"
#define cliEdKeyPubFile "certs/ed25519/client-ed25519-key.pem"
#define caEdCertFile "certs/ed25519/ca-ed25519.pem"
#define ed448CertFile "certs/ed448/server-ed448-cert.pem"
#define ed448KeyFile "certs/ed448/server-ed448-priv.pem"
@ -367,23 +373,29 @@
#define caCertFile "./certs/ca-cert.pem"
#define eccCertFile "./certs/server-ecc.pem"
#define eccKeyFile "./certs/ecc-key.pem"
#define eccKeyPubFile "./certs/ecc-keyPub.pem"
#define eccRsaCertFile "./certs/server-ecc-rsa.pem"
#define svrCertFile "./certs/server-cert.pem"
#define svrKeyFile "./certs/server-key.pem"
#define svrKeyPubFile "./certs/server-keyPub.pem"
#define cliCertFile "./certs/client-cert.pem"
#define cliCertDerFile "./certs/client-cert.der"
#define cliCertFileExt "./certs/client-cert-ext.pem"
#define cliCertDerFileExt "./certs/client-cert-ext.der"
#define cliKeyFile "./certs/client-key.pem"
#define cliKeyPubFile "./certs/client-keyPub.pem"
#define dhParamFile "./certs/dh2048.pem"
#define cliEccKeyFile "./certs/ecc-client-key.pem"
#define cliEccKeyPubFile "./certs/ecc-client-keyPub.pem"
#define cliEccCertFile "./certs/client-ecc-cert.pem"
#define caEccCertFile "./certs/ca-ecc-cert.pem"
#define crlPemDir "./certs/crl"
#define edCertFile "./certs/ed25519/server-ed25519-cert.pem"
#define edKeyFile "./certs/ed25519/server-ed25519-priv.pem"
#define edKeyPubFile "./certs/ed25519/server-ed25519-key.pem"
#define cliEdCertFile "./certs/ed25519/client-ed25519.pem"
#define cliEdKeyFile "./certs/ed25519/client-ed25519-priv.pem"
#define cliEdKeyPubFile "./certs/ed25519/client-ed25519-key.pem"
#define caEdCertFile "./certs/ed25519/ca-ed25519.pem"
#define ed448CertFile "./certs/ed448/server-ed448-cert.pem"
#define ed448KeyFile "./certs/ed448/server-ed448-priv.pem"
@ -443,7 +455,13 @@ typedef struct callback_functions {
ssl_callback ssl_ready;
ssl_callback on_result;
WOLFSSL_CTX* ctx;
const char* caPemFile;
const char* certPemFile;
const char* keyPemFile;
int devId;
int return_code;
unsigned char isSharedCtx:1;
unsigned char loadToSSL:1;
} callback_functions;
typedef struct func_args {