Merge pull request #5244 from julek-wolfssl/wpas-dpp

Support for new DPP and EAP-TEAP/EAP-FAST in wpa_supplicant
This commit is contained in:
David Garske
2022-07-06 11:35:52 -07:00
committed by GitHub
10 changed files with 210 additions and 47 deletions

View File

@@ -1242,6 +1242,11 @@ AC_ARG_ENABLE([wpas-dpp],
[ ENABLED_WPAS_DPP=no ]
)
if test "$ENABLED_WPAS_DPP" = "yes"
then
ENABLED_WPAS="yes"
fi
# ntp support
AC_ARG_ENABLE([ntp],
[AS_HELP_STRING([--enable-ntp],[Enable ntp support (default: disabled)])],
@@ -1249,11 +1254,6 @@ AC_ARG_ENABLE([ntp],
[ ENABLED_NTP=no ]
)
if test "$ENABLED_WPAS_DPP" = "yes"
then
ENABLED_WPAS="yes"
fi
# Fortress build
AC_ARG_ENABLE([fortress],
[AS_HELP_STRING([--enable-fortress],[Enable SSL fortress build (default: disabled)])],
@@ -1548,6 +1548,8 @@ then
AM_CFLAGS="$AM_CFLAGS -DKEEP_PEER_CERT"
AM_CFLAGS="$AM_CFLAGS -DHAVE_KEYING_MATERIAL"
AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE_REF"
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT"
AM_CFLAGS="$AM_CFLAGS -DWC_CTC_NAME_SIZE=128"
if test "$ENABLED_OPENSSLEXTRA" = "no"
then
@@ -2687,6 +2689,10 @@ AC_ARG_ENABLE([certreq],
[ ENABLED_CERTREQ=no ]
)
if test "$ENABLED_WPAS_DPP" = "yes"
then
ENABLED_CERTREQ="yes"
fi
# CERT REQUEST EXTENSION
AC_ARG_ENABLE([certext],
@@ -2825,6 +2831,11 @@ AC_ARG_ENABLE([ecccustcurves],
[ ENABLED_ECCCUSTCURVES=no ]
)
if test "$ENABLED_WPAS_DPP" = "yes"
then
ENABLED_ECCCUSTCURVES="all"
fi
if test "$ENABLED_ECCCUSTCURVES" != "no"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES"
@@ -4823,6 +4834,11 @@ AC_ARG_ENABLE([pkcs7],
[ ENABLED_PKCS7=no ]
)
if test "x$ENABLED_WPAS_DPP" = "xyes"
then
ENABLED_PKCS7=yes
fi
# wolfSSH Options
AC_ARG_ENABLE([wolfssh],
[AS_HELP_STRING([--enable-wolfssh],[Enable wolfSSH options (default: disabled)])],
@@ -6460,7 +6476,7 @@ if test "$ENABLED_SP_MATH" = "yes"; then
if test "$ENABLED_SP" = "no"; then
AC_MSG_ERROR([Must have SP enabled with SP math: --enable-sp])
fi
if test "$ENABLED_ECCCUSTCURVES" = "yes"; then
if test "$ENABLED_ECCCUSTCURVES" != "no"; then
AC_MSG_ERROR([Cannot use single precision math and custom curves])
fi
if test "$ENABLED_DSA" = "yes"; then

View File

@@ -1416,8 +1416,8 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
\brief This function converts the ECC public key to DER format. It
returns the size of buffer used. The public ECC key in DER format is stored
in output buffer. with_AlgCurve is a flag for when to include a header that
has the Algorithm and Curve information.
in output buffer. The with_AlgCurve flag will include a header that
has the Algorithm and Curve information
\return >0 Success, size of buffer used
\return BAD_FUNC_ARG Returned if output or key is null.
@@ -1436,7 +1436,7 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
wc_ecc_init(&key);
WC_WC_RNG rng;
wc_InitRng(&rng);
wc_ecc_make_key(&rng, 24, &key);
wc_ecc_make_key(&rng, 32, &key);
int derSz = // Some appropriate size for der;
byte der[derSz];
@@ -1452,6 +1452,51 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
int wc_EccPublicKeyToDer(ecc_key* key, byte* output,
word32 inLen, int with_AlgCurve);
/*!
\ingroup ASN
\brief This function converts the ECC public key to DER format. It
returns the size of buffer used. The public ECC key in DER format is stored
in output buffer. The with_AlgCurve flag will include a header that
has the Algorithm and Curve information. The comp parameter determines if
the public key will be exported as compressed.
\return >0 Success, size of buffer used
\return BAD_FUNC_ARG Returned if output or key is null.
\return LENGTH_ONLY_E Error in getting ECC public key size.
\return BUFFER_E Returned when output buffer is too small.
\param key Pointer to ECC key
\param output Pointer to output buffer to write to.
\param inLen Size of buffer.
\param with_AlgCurve a flag for when to include a header that has the
Algorithm and Curve information.
\param comp If 1 (non-zero) the ECC public key will be written in
compressed form. If 0 it will be written in an uncompressed format.
_Example_
\code
ecc_key key;
wc_ecc_init(&key);
WC_WC_RNG rng;
wc_InitRng(&rng);
wc_ecc_make_key(&rng, 32, &key);
int derSz = // Some appropriate size for der;
byte der[derSz];
// Write out a compressed ECC key
if(wc_EccPublicKeyToDer_ex(&key, der, derSz, 1, 1) < 0)
{
// Error converting ECC public key to der
}
\endcode
\sa wc_EccKeyToDer
\sa wc_EccPublicKeyDecode
*/
int wc_EccPublicKeyToDer_ex(ecc_key* key, byte* output,
word32 inLen, int with_AlgCurve, int comp);
/*!
\ingroup ASN

View File

@@ -14781,6 +14781,32 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
}
if (ssl->options.side == WOLFSSL_CLIENT_END) {
switch (type) {
case certificate:
case server_key_exchange:
case certificate_request:
case server_hello_done:
if (ssl->options.resuming) {
#ifdef WOLFSSL_WPAS
/* This can occur when ssl->sessionSecretCb is set. EAP-FAST
* (RFC 4851) allows for detecting server session resumption
* based on the msg received after the ServerHello. */
WOLFSSL_MSG("Not resuming as thought");
ssl->options.resuming = 0;
/* No longer resuming, reset peer authentication state. */
ssl->options.peerAuthGood = 0;
#else
/* Fatal error. Only try to send an alert. RFC 5246 does not
* allow for reverting back to a full handshake after the
* server has indicated the intention to do a resumption. */
(void)SendAlert(ssl, alert_fatal, unexpected_message);
return OUT_OF_ORDER_E;
#endif
}
}
}
#ifdef OPENSSL_EXTRA
if (ssl->CBIS != NULL){
ssl->cbmode = SSL_CB_MODE_READ;
@@ -14895,12 +14921,6 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
*inOutIdx += MacSize(ssl);
#endif
}
if (ssl->options.resuming) {
WOLFSSL_MSG("Not resuming as thought");
ssl->options.resuming = 0;
/* CLIENT: No longer resuming, reset peer authentication state. */
ssl->options.peerAuthGood = 0;
}
break;
case finished:
@@ -24639,8 +24659,12 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
#ifdef HAVE_SECRET_CALLBACK
/* If a session secret callback exists, we are using that
* key instead of the saved session key. */
ret = ret || (ssl->sessionSecretCb != NULL);
* key instead of the saved session key. Requires a ticket. */
ret = ret || (ssl->sessionSecretCb != NULL
#ifdef HAVE_SESSION_TICKET
&& ssl->session->ticketLen > 0
#endif
);
#endif
#ifdef HAVE_SESSION_TICKET
@@ -24987,7 +25011,11 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
}
#ifdef HAVE_SECRET_CALLBACK
if (ssl->sessionSecretCb != NULL) {
if (ssl->sessionSecretCb != NULL
#ifdef HAVE_SESSION_TICKET
&& ssl->session->ticketLen > 0
#endif
) {
int secretSz = SECRET_LEN;
ret = ssl->sessionSecretCb(ssl, ssl->session->masterSecret,
&secretSz, ssl->sessionSecretCtx);

View File

@@ -10509,9 +10509,11 @@ int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx)
ssl->sessionSecretCb = cb;
ssl->sessionSecretCtx = ctx;
/* If using a pre-set key, assume session resumption. */
ssl->session->sessionIDSz = 0;
ssl->options.resuming = 1;
if (cb != NULL) {
/* If using a pre-set key, assume session resumption. */
ssl->session->sessionIDSz = 0;
ssl->options.resuming = 1;
}
return WOLFSSL_SUCCESS;
}
@@ -12181,6 +12183,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
/* CLIENT: Fail-safe for Server Authentication. */
if (!ssl->options.peerAuthGood) {
WOLFSSL_MSG("Server authentication did not happen");
ssl->error = NO_PEER_VERIFY;
return WOLFSSL_FATAL_ERROR;
}

View File

@@ -3934,7 +3934,11 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ssl->options.serverState = SERVER_HELLO_COMPLETE;
#ifdef HAVE_SECRET_CALLBACK
if (ssl->sessionSecretCb != NULL) {
if (ssl->sessionSecretCb != NULL
#ifdef HAVE_SESSION_TICKET
&& ssl->session->ticketLen > 0
#endif
) {
int secretSz = SECRET_LEN;
ret = ssl->sessionSecretCb(ssl, ssl->session->masterSecret,
&secretSz, ssl->sessionSecretCtx);

View File

@@ -24715,7 +24715,7 @@ static int test_wc_ecc_export_x963_ex (void)
if (ret == BAD_FUNC_ARG) {
ret = wc_ecc_export_x963_ex(&key, out, &badOutLen, COMP);
}
if (ret == BUFFER_E) {
if (ret == LENGTH_ONLY_E) {
key.idx = -4;
ret = wc_ecc_export_x963_ex(&key, out, &outlen, COMP);
}
@@ -30578,7 +30578,7 @@ static void test_wc_GetPubKeyDerFromCert(void)
XFCLOSE(fp);
wc_InitDecodedCert(&decoded, certBuf, certBufSz, NULL);
ret = wc_ParseCert(&decoded, CERTREQ_TYPE, NO_VERIFY, NULL);
ret = wc_ParseCert(&decoded, CERTREQ_TYPE, VERIFY, NULL);
AssertIntEQ(ret, 0);
/* good test case - RSA DER certificate request */

View File

@@ -13055,9 +13055,16 @@ int DecodeToKey(DecodedCert* cert, int verify)
return ret;
/* Determine if self signed */
cert->selfSigned = XMEMCMP(cert->issuerHash,
cert->subjectHash,
KEYID_SIZE) == 0 ? 1 : 0;
#ifdef WOLFSSL_CERT_REQ
if (cert->isCSR)
cert->selfSigned = 1;
else
#endif
{
cert->selfSigned = XMEMCMP(cert->issuerHash,
cert->subjectHash,
KEYID_SIZE) == 0 ? 1 : 0;
}
ret = GetCertKey(cert, cert->source, &cert->srcIdx, cert->maxIdx);
if (ret != 0)
@@ -18120,8 +18127,15 @@ static int DecodeCertInternal(DecodedCert* cert, int verify, int* criticalExt,
}
if (ret == 0) {
/* Determine if self signed by comparing issuer and subject hashes. */
cert->selfSigned = XMEMCMP(cert->issuerHash, cert->subjectHash,
KEYID_SIZE) == 0 ? 1 : 0;
#ifdef WOLFSSL_CERT_REQ
if (cert->isCSR)
cert->selfSigned = 1;
else
#endif
{
cert->selfSigned = XMEMCMP(cert->issuerHash, cert->subjectHash,
KEYID_SIZE) == 0 ? 1 : 0;
}
if (stopAtPubKey) {
/* Return any bad date error through badDateRet and return offset of
@@ -19783,6 +19797,22 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
}
#endif /* IGNORE_NAME_CONSTRAINTS */
}
#ifdef WOLFSSL_CERT_REQ
else if (type == CERTREQ_TYPE) {
if ((ret = ConfirmSignature(&cert->sigCtx,
cert->source + cert->certBegin,
cert->sigIndex - cert->certBegin,
cert->publicKey, cert->pubKeySize,
cert->keyOID, cert->signature,
cert->sigLength, cert->signatureOID,
sce_tsip_encRsaKeyIdx)) != 0) {
if (ret != WC_PENDING_E) {
WOLFSSL_MSG("Confirm signature failed");
}
return ret;
}
}
#endif
else {
/* no signer */
WOLFSSL_MSG("No CA signer to verify with");
@@ -22119,7 +22149,7 @@ enum {
* @return MEMORY_E when dynamic memory allocation failed.
*/
static int SetEccPublicKey(byte* output, ecc_key* key, int outLen,
int with_header)
int with_header, int comp)
{
#ifndef WOLFSSL_ASN_TEMPLATE
int ret, idx = 0, algoSz, curveSz, bitStringSz;
@@ -22129,7 +22159,10 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int outLen,
/* public size */
pubSz = key->dp ? key->dp->size : MAX_ECC_BYTES;
pubSz = 1 + 2 * pubSz;
if (comp)
pubSz = 1 + pubSz;
else
pubSz = 1 + 2 * pubSz;
/* check for buffer overflow */
if (output != NULL && pubSz > (word32)outLen) {
@@ -22172,7 +22205,7 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int outLen,
/* pub */
if (output) {
PRIVATE_KEY_UNLOCK();
ret = wc_ecc_export_x963(key, output + idx, &pubSz);
ret = wc_ecc_export_x963_ex(key, output + idx, &pubSz, comp);
PRIVATE_KEY_LOCK();
if (ret != 0) {
return ret;
@@ -22196,7 +22229,7 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int outLen,
if (ret == 0) {
/* Calculate the size of the encoded public point. */
PRIVATE_KEY_UNLOCK();
ret = wc_ecc_export_x963(key, NULL, &pubSz);
ret = wc_ecc_export_x963_ex(key, NULL, &pubSz, comp);
PRIVATE_KEY_LOCK();
/* LENGTH_ONLY_E on success. */
if (ret == LENGTH_ONLY_E) {
@@ -22266,7 +22299,7 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int outLen,
if ((ret == 0) && (output != NULL)) {
/* Encode public point. */
PRIVATE_KEY_UNLOCK();
ret = wc_ecc_export_x963(key, output, &pubSz);
ret = wc_ecc_export_x963_ex(key, output, &pubSz, comp);
PRIVATE_KEY_LOCK();
}
if (ret == 0) {
@@ -22294,12 +22327,18 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int outLen,
int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen,
int with_AlgCurve)
{
return SetEccPublicKey(output, key, inLen, with_AlgCurve);
return SetEccPublicKey(output, key, inLen, with_AlgCurve, 0);
}
int wc_EccPublicKeyToDer_ex(ecc_key* key, byte* output, word32 inLen,
int with_AlgCurve, int comp)
{
return SetEccPublicKey(output, key, inLen, with_AlgCurve, comp);
}
int wc_EccPublicKeyDerSize(ecc_key* key, int with_AlgCurve)
{
return SetEccPublicKey(NULL, key, 0, with_AlgCurve);
return SetEccPublicKey(NULL, key, 0, with_AlgCurve, 0);
}
#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
@@ -24159,7 +24198,7 @@ static int EncodePublicKey(int keyType, byte* output, int outLen,
#endif
#ifdef HAVE_ECC
case ECC_KEY:
ret = SetEccPublicKey(output, eccKey, outLen, 1);
ret = SetEccPublicKey(output, eccKey, outLen, 1, 0);
if (ret <= 0) {
ret = PUBLIC_KEY_E;
}
@@ -24839,7 +24878,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
if (eccKey == NULL)
return PUBLIC_KEY_E;
der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey,
sizeof(der->publicKey), 1);
sizeof(der->publicKey), 1, 0);
}
#endif
@@ -26094,7 +26133,7 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey,
if (eccKey == NULL)
return PUBLIC_KEY_E;
der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey,
sizeof(der->publicKey), 1);
sizeof(der->publicKey), 1, 0);
}
#endif
@@ -26577,7 +26616,7 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
if ((ret == 0) && (sz > (int)derSz)) {
ret = BUFFER_E;
}
if (ret == 0) {
if (ret == 0 && derBuffer != NULL) {
/* Encode certificate request body into buffer. */
SetASN_Items(certReqBodyASN, dataASN, certReqBodyASN_Length, derBuffer);
@@ -26593,14 +26632,15 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
&cert->subject, cert->heap);
}
}
if (ret >= 0) {
if (ret >= 0 && derBuffer != NULL) {
/* Encode public key into space in buffer. */
ret = EncodePublicKey(cert->keyType,
(byte*)dataASN[CERTREQBODYASN_IDX_SPUBKEYINFO_SEQ].data.buffer.data,
dataASN[CERTREQBODYASN_IDX_SPUBKEYINFO_SEQ].data.buffer.length,
rsaKey, eccKey, ed25519Key, ed448Key, dsaKey);
}
if ((ret >= 0) && (!dataASN[CERTREQBODYASN_IDX_EXT_BODY].noOut)) {
if ((ret >= 0 && derBuffer != NULL) &&
(!dataASN[CERTREQBODYASN_IDX_EXT_BODY].noOut)) {
/* Encode extensions into space in buffer. */
ret = EncodeExtensions(cert,
(byte*)dataASN[CERTREQBODYASN_IDX_EXT_BODY].data.buffer.data,
@@ -26826,7 +26866,7 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey,
#ifdef HAVE_ECC
/* ECC public key */
if (eckey != NULL)
bufferSz = SetEccPublicKey(buf, eckey, MAX_PUBLIC_KEY_SZ, 0);
bufferSz = SetEccPublicKey(buf, eckey, MAX_PUBLIC_KEY_SZ, 0, 0);
#endif
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT)
/* ED25519 public key */

View File

@@ -13715,7 +13715,7 @@ static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen
word32 numlen;
int ret = MP_OKAY;
if (key == NULL || out == NULL || outLen == NULL)
if (key == NULL || outLen == NULL)
return BAD_FUNC_ARG;
if (key->type == ECC_PRIVATEKEY_ONLY)
@@ -13729,9 +13729,12 @@ static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen
if (*outLen < (1 + numlen)) {
*outLen = 1 + numlen;
return BUFFER_E;
return LENGTH_ONLY_E;
}
if (out == NULL)
return BAD_FUNC_ARG;
/* store first byte */
out[0] = mp_isodd(key->pubkey.y) == MP_YES ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;

View File

@@ -11995,7 +11995,7 @@ WOLFSSL_TEST_SUBROUTINE int memory_test(void)
static const char* certDerFile = CERT_WRITE_TEMP_DIR "cert.der";
static const char* otherCertPemFile = CERT_WRITE_TEMP_DIR "othercert.pem";
static const char* certPemFile = CERT_WRITE_TEMP_DIR "cert.pem";
#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
#if defined(WOLFSSL_CERT_REQ) && !defined(WOLFSSL_NO_MALLOC)
static const char* certReqDerFile = CERT_WRITE_TEMP_DIR "certreq.der";
static const char* certReqPemFile = CERT_WRITE_TEMP_DIR "certreq.pem";
#endif
@@ -15559,10 +15559,13 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void)
goto exit_rsa;
#endif
#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
#if defined(WOLFSSL_CERT_REQ) && !defined(WOLFSSL_NO_MALLOC)
{
Cert *req;
int derSz;
#ifndef WOLFSSL_SMALL_STACK
byte* der = NULL;
#endif
req = (Cert *)XMALLOC(sizeof *req, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (! req)
@@ -15656,6 +15659,13 @@ WOLFSSL_TEST_SUBROUTINE int rsa_test(void)
ERROR_OUT(-7974, exit_rsa);
}
/* Test getting the size of the buffer without providing the buffer.
* derSz is set to the "largest buffer" we are willing to allocate. */
derSz = wc_MakeCertReq(req, NULL, 10000, key, NULL);
if (derSz < 0) {
ERROR_OUT(-7975, exit_rsa);
}
XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(req, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
der = NULL;
@@ -22561,6 +22571,17 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize)
ERROR_OUT(-9890, done);
}
#ifdef HAVE_COMP_KEY
/* test export of compressed public key */
derSz = wc_EccPublicKeyToDer_ex(userA, der, ECC_BUFSIZE, 1, 1);
if (derSz < 0) {
ERROR_OUT(derSz, done);
}
if (derSz == 0) {
ERROR_OUT(-9890, done);
}
#endif
ret = SaveDerAndPem(der, derSz, eccPubKeyDerFile, NULL, 0, -8348);
if (ret != 0) {
goto done;

View File

@@ -657,6 +657,9 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz);
ecc_key* key, word32 inSz);
WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key* key, byte* output,
word32 inLen, int with_AlgCurve);
WOLFSSL_API int wc_EccPublicKeyToDer_ex(ecc_key* key, byte* output,
word32 inLen, int with_AlgCurve,
int comp);
WOLFSSL_API int wc_EccPublicKeyDerSize(ecc_key* key, int with_AlgCurve);
#endif