Skip to content
Draft
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
1 change: 1 addition & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,7 @@ WOLFSSL_NO_RSA_KEY_CHECK
WOLFSSL_NO_SERVER_GROUPS_EXT
WOLFSSL_NO_SESSION_STATS
WOLFSSL_NO_SIGALG
WOLFSSL_NO_SIGNER_DER_CERT
WOLFSSL_NO_SOCKADDR_UN
WOLFSSL_NO_STRICT_CIPHER_SUITE
WOLFSSL_NO_TICKET_EXPIRE
Expand Down
90 changes: 29 additions & 61 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -15963,59 +15963,6 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int cert_err,
if (args->certIdx > 0) {
use_cb = 1;
}
#endif
#if defined(OPENSSL_EXTRA)
/* Perform domain and IP check only for the leaf certificate */
if (args->certIdx == 0) {
/* perform domain name check on the peer certificate */
if (args->dCertInit && args->dCert && (ssl != NULL) &&
ssl->param && ssl->param->hostName[0]) {
/* If altNames names is present, then subject common name is ignored */
if (args->dCert->altNames != NULL) {
if (CheckForAltNames(args->dCert, ssl->param->hostName,
(word32)XSTRLEN(ssl->param->hostName), NULL, 0, 0) != 1) {
if (cert_err == 0) {
ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
}
}
#ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY
else {
if (args->dCert->subjectCN) {
if (MatchDomainName(
args->dCert->subjectCN,
args->dCert->subjectCNLen,
ssl->param->hostName,
(word32)XSTRLEN(ssl->param->hostName), 0) == 0) {
if (cert_err == 0) {
ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
}
}
}
#else
else {
if (cert_err == 0) {
ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
}
#endif /* !WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY */
}

/* perform IP address check on the peer certificate */
if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) &&
(ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) {
if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) {
if (cert_err == 0) {
ret = IPADDR_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
}
}
}
#endif
/* if verify callback has been set */
if ((use_cb && (ssl != NULL) && ((ssl->verifyCallback != NULL)
Expand Down Expand Up @@ -18749,6 +18696,14 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif

domainName = (char*)ssl->buffers.domainName.buffer;
#ifdef OPENSSL_EXTRA
/* X509_VERIFY_PARAM_set1_host() is the OpenSSL way of naming
* the expected peer. */
if ((domainName == NULL) && (ssl->param != NULL) &&
(ssl->param->hostName[0] != '\0')) {
domainName = ssl->param->hostName;
}
#endif
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_ECH)
/* RFC 9849 s6.1.7: ECH offered but rejected by the server...
* verify cert is valid for ECHConfig.public_name */
Expand Down Expand Up @@ -18823,16 +18778,29 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif /* WOLFSSL_ALL_NO_CN_IN_SAN */
}

#ifndef OPENSSL_EXTRA
if (!ssl->options.verifyNone && ssl->buffers.ipasc.buffer) {
if (CheckIPAddr(args->dCert,
(const char*)ssl->buffers.ipasc.buffer) != 0) {
WOLFSSL_MSG("IPAddr match on alt names failed");
ret = IPADDR_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
{
const char* ipasc = NULL;

if (ssl->buffers.ipasc.buffer != NULL) {
ipasc = (const char*)ssl->buffers.ipasc.buffer;
}
#ifdef OPENSSL_EXTRA
/* X509_VERIFY_PARAM_set1_ip() sets the expected address
* here rather than on the WOLFSSL buffers. */
else if ((ssl->param != NULL) &&
(ssl->param->ipasc[0] != '\0')) {
ipasc = ssl->param->ipasc;
}
#endif

if (!ssl->options.verifyNone && (ipasc != NULL)) {
if (CheckIPAddr(args->dCert, ipasc) != 0) {
WOLFSSL_MSG("IPAddr match on alt names failed");
ret = IPADDR_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
}
}
#endif

/* decode peer key */
if (ProcessPeerCertDecodeKey(ssl, args, &ret))
Expand Down
200 changes: 194 additions & 6 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -4830,13 +4830,43 @@ int wolfSSL_get_peer_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey)
}
#endif

*pkey = ret;
#ifdef HAVE_ECC
if (ret != NULL)
return WOLFSSL_SUCCESS;
else
#ifdef HAVE_CURVE25519
if ((ret == NULL) && (ssl->peerX25519Key != NULL) &&
ssl->peerX25519KeyPresent) {
byte pub[CURVE25519_PUB_KEY_SIZE];
word32 pubSz = (word32)sizeof(pub);

/* Raw X25519 keys are little-endian (RFC 7748). */
if (wc_curve25519_export_public_ex(ssl->peerX25519Key, pub, &pubSz,
EC25519_LITTLE_ENDIAN) != 0) {
WOLFSSL_MSG("get curve25519 public key failed");
return WOLFSSL_FAILURE;
}
Comment on lines +4840 to +4844
ret = wolfSSL_EVP_PKEY_new_raw_public_key(WC_EVP_PKEY_X25519, NULL,
pub, (size_t)pubSz);
}
#endif
return WOLFSSL_FAILURE;

#ifdef HAVE_CURVE448
if ((ret == NULL) && (ssl->peerX448Key != NULL) &&
ssl->peerX448KeyPresent) {
byte pub[CURVE448_PUB_KEY_SIZE];
word32 pubSz = (word32)sizeof(pub);

/* Raw X448 keys are little-endian (RFC 7748). */
if (wc_curve448_export_public_ex(ssl->peerX448Key, pub, &pubSz,
EC448_LITTLE_ENDIAN) != 0) {
WOLFSSL_MSG("get curve448 public key failed");
return WOLFSSL_FAILURE;
}
ret = wolfSSL_EVP_PKEY_new_raw_public_key(WC_EVP_PKEY_X448, NULL,
pub, (size_t)pubSz);
}
#endif

*pkey = ret;

return (ret != NULL) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
}

#endif /* !NO_WOLFSSL_SERVER */
Expand Down Expand Up @@ -9403,6 +9433,25 @@ const WOLF_EC_NIST_NAME kNistCurves[] = {
#endif
#endif /* WOLFSSL_MLKEM_KYBER */
#endif /* WOLFSSL_HAVE_MLKEM */
#ifndef NO_DH
/* Finite field groups have no NID; OpenSSL identifies them by TLS group
* code point, so use that for both fields. */
#ifdef HAVE_FFDHE_2048
{CURVE_NAME("ffdhe2048"), WOLFSSL_FFDHE_2048, WOLFSSL_FFDHE_2048},
#endif
#ifdef HAVE_FFDHE_3072
{CURVE_NAME("ffdhe3072"), WOLFSSL_FFDHE_3072, WOLFSSL_FFDHE_3072},
#endif
#ifdef HAVE_FFDHE_4096
{CURVE_NAME("ffdhe4096"), WOLFSSL_FFDHE_4096, WOLFSSL_FFDHE_4096},
#endif
#ifdef HAVE_FFDHE_6144
{CURVE_NAME("ffdhe6144"), WOLFSSL_FFDHE_6144, WOLFSSL_FFDHE_6144},
#endif
#ifdef HAVE_FFDHE_8192
{CURVE_NAME("ffdhe8192"), WOLFSSL_FFDHE_8192, WOLFSSL_FFDHE_8192},
#endif
#endif /* !NO_DH */
#ifdef WOLFSSL_SM2
{CURVE_NAME("SM2"), WC_NID_sm2, WOLFSSL_ECC_SM2P256V1},
#endif
Expand Down Expand Up @@ -9565,6 +9614,145 @@ int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names,
return ret;
}

/* Get the group used for key exchange.
*
* Mirrors OpenSSL's SSL_get_negotiated_group(): the NID is returned for groups
* wolfSSL gives one, the IANA code point otherwise. NID values are wolfSSL's
* WC_NID_* (not every one matches OpenSSL's), so compare against those rather
* than against literals. The result can be passed to wolfSSL_group_to_name().
*
* @param [in] ssl SSL/TLS object.
* @return Group identifier on success.
* @return 0 when ssl is NULL or no group has been negotiated.
*/
int wolfSSL_get_negotiated_group(const WOLFSSL* ssl)
{
word16 group;
const WOLF_EC_NIST_NAME* nist_name;

WOLFSSL_ENTER("wolfSSL_get_negotiated_group");

if (ssl == NULL)
return 0;

group = ssl->namedGroup;

#ifdef HAVE_CURVE25519
if ((group == 0) && (ssl->ecdhCurveOID == ECC_X25519_OID))
group = WOLFSSL_ECC_X25519;
#endif
#ifdef HAVE_CURVE448
if ((group == 0) && (ssl->ecdhCurveOID == ECC_X448_OID))
group = WOLFSSL_ECC_X448;
#endif
#ifdef HAVE_ECC
if ((group == 0) && (ssl->ecdhCurveOID != 0))
group = GetCurveByOID((int)ssl->ecdhCurveOID);
#endif

if (group == 0)
return 0;

for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
if (nist_name->curve == group)
return nist_name->nid;
}

return (int)group;
}

/* Names OpenSSL gives the TLS supported groups. These are the TLS group
* registry spellings, which differ from both the NIST curve names in
* kNistCurves ("P-256" is "secp256r1" here) and from wolfSSL_get_curve_name().
*/
static const struct {
word16 group;
const char* name;
} kTlsGroupNames[] = {
#ifdef HAVE_ECC
{WOLFSSL_ECC_SECP256R1, "secp256r1"},
{WOLFSSL_ECC_SECP384R1, "secp384r1"},
{WOLFSSL_ECC_SECP521R1, "secp521r1"},
{WOLFSSL_ECC_SECP224R1, "secp224r1"},
{WOLFSSL_ECC_SECP192R1, "secp192r1"},
{WOLFSSL_ECC_SECP256K1, "secp256k1"},
#ifdef HAVE_ECC_BRAINPOOL
{WOLFSSL_ECC_BRAINPOOLP256R1, "brainpoolP256r1"},
{WOLFSSL_ECC_BRAINPOOLP384R1, "brainpoolP384r1"},
{WOLFSSL_ECC_BRAINPOOLP512R1, "brainpoolP512r1"},
{WOLFSSL_ECC_BRAINPOOLP256R1TLS13, "brainpoolP256r1tls13"},
{WOLFSSL_ECC_BRAINPOOLP384R1TLS13, "brainpoolP384r1tls13"},
{WOLFSSL_ECC_BRAINPOOLP512R1TLS13, "brainpoolP512r1tls13"},
#endif
#endif /* HAVE_ECC */
#ifdef HAVE_CURVE25519
{WOLFSSL_ECC_X25519, "x25519"},
#endif
#ifdef HAVE_CURVE448
{WOLFSSL_ECC_X448, "x448"},
#endif
#ifndef NO_DH
{WOLFSSL_FFDHE_2048, "ffdhe2048"},
{WOLFSSL_FFDHE_3072, "ffdhe3072"},
{WOLFSSL_FFDHE_4096, "ffdhe4096"},
{WOLFSSL_FFDHE_6144, "ffdhe6144"},
{WOLFSSL_FFDHE_8192, "ffdhe8192"},
#endif
#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM)
{WOLFSSL_ML_KEM_512, "MLKEM512"},
{WOLFSSL_ML_KEM_768, "MLKEM768"},
{WOLFSSL_ML_KEM_1024, "MLKEM1024"},
#if defined(HAVE_ECC) && defined(WOLFSSL_PQC_HYBRIDS)
{WOLFSSL_SECP256R1MLKEM768, "SecP256r1MLKEM768"},
{WOLFSSL_SECP384R1MLKEM1024, "SecP384r1MLKEM1024"},
#ifdef HAVE_CURVE25519
{WOLFSSL_X25519MLKEM768, "X25519MLKEM768"},
#endif
#endif
#endif /* WOLFSSL_HAVE_MLKEM && !WOLFSSL_NO_ML_KEM */
{0, NULL}
};

/* Get the name of a group.
*
* @param [in] ssl SSL/TLS object. Unused, present for OpenSSL compatibility.
* @param [in] id NID or IANA code point of the group.
* @return Name of the group on success.
* @return NULL when the group is unknown.
*/
const char* wolfSSL_group_to_name(const WOLFSSL* ssl, int id)
{
const WOLF_EC_NIST_NAME* nist_name;
int group = id;
int i;

WOLFSSL_ENTER("wolfSSL_group_to_name");

(void)ssl;

/* wolfSSL_get_negotiated_group() reports a NID where one exists, so map
* NIDs back to their code point before looking the name up. */
for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
if (nist_name->nid == id) {
group = (int)nist_name->curve;
break;
}
}

for (i = 0; kTlsGroupNames[i].name != NULL; i++) {
if ((int)kTlsGroupNames[i].group == group)
return kTlsGroupNames[i].name;
}

/* Not a group OpenSSL names - fall back to the wolfSSL name. */
for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
if ((int)nist_name->curve == group)
return nist_name->name;
}

return NULL;
}

#endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) */
#endif /* OPENSSL_EXTRA || HAVE_CURL */

Expand Down
23 changes: 18 additions & 5 deletions src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -9759,8 +9759,9 @@ static int TLSX_KeyShare_ProcessX25519_ex(WOLFSSL* ssl,
* falls through to the cleanup code below. */
}

/* done with key share, release resources */
if (ssl->peerX25519Key != NULL) {
/* done with key share, release resources unless the peer key was asked
* for - wolfSSL_get_peer_tmp_key() needs it after the handshake */
if ((ssl->peerX25519Key != NULL) && !ssl->options.keepResources) {
wc_curve25519_free(ssl->peerX25519Key);
XFREE(ssl->peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX);
ssl->peerX25519Key = NULL;
Expand Down Expand Up @@ -9872,8 +9873,18 @@ static int TLSX_KeyShare_ProcessX448_ex(WOLFSSL* ssl,
ssOutput, ssOutSz, EC448_LITTLE_ENDIAN);
}

wc_curve448_free(peerX448Key);
XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX);
/* Keep the peer key when it was asked for - wolfSSL_get_peer_tmp_key()
* needs it after the handshake. Freed with the other peer keys on
* teardown. */
if ((ret == 0) && ssl->options.keepResources) {
FreeKey(ssl, DYNAMIC_TYPE_CURVE448, (void**)&ssl->peerX448Key);
ssl->peerX448Key = peerX448Key;
ssl->peerX448KeyPresent = 1;
}
else {
wc_curve448_free(peerX448Key);
XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX);
}
wc_curve448_free((curve448_key*)keyShareEntry->key);
XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
keyShareEntry->key = NULL;
Expand Down Expand Up @@ -10046,11 +10057,13 @@ static int TLSX_KeyShare_ProcessEcc_ex(WOLFSSL* ssl,
#endif
}

/* done with key share, release resources */
/* done with key share, release resources unless the peer key was asked
* for - wolfSSL_get_peer_tmp_key() needs it after the handshake */
if (ssl->peerEccKey != NULL
#ifdef HAVE_PK_CALLBACKS
&& ssl->ctx->EccSharedSecretCb == NULL
#endif
&& !ssl->options.keepResources
) {
wc_ecc_free(ssl->peerEccKey);
XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
Expand Down
Loading
Loading