diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index c13aaf7ab61..e6901921d05 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -15257,6 +15257,239 @@ RFC 9146 and RFC 9147. const unsigned char* wolfSSL_dtls_cid_parse(const unsigned char* msg, unsigned int msgSz, unsigned int cidSz); +/*! + \ingroup TLS + \brief On the server, this sets a list of CA names to be sent to clients in + certificate requests as a hint for which CA's are supported by the server. + + On the client, this function has no effect. + + \param [in] ctx Pointer to the wolfSSL context + \param [in] names List of names to be set + + \sa wolfSSL_set_client_CA_list + \sa wolfSSL_CTX_get_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_CTX_set0_CA_list + \sa wolfSSL_set0_CA_list + \sa wolfSSL_CTX_get0_CA_list + \sa wolfSSL_get0_CA_list + \sa wolfSSL_get0_peer_CA_list +*/ +void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names); + +/*! + \ingroup TLS + \brief This retrieves the list previously set via + wolfSSL_CTX_set_client_CA_list, or NULL if no list has been set. + + \param [in] ctx Pointer to the wolfSSL context + \return A stack of WOLFSSL_X509_NAMEs containing the CA names + + \sa wolfSSL_set_client_CA_list + \sa wolfSSL_CTX_set_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_CTX_set0_CA_list + \sa wolfSSL_set0_CA_list + \sa wolfSSL_CTX_get0_CA_list + \sa wolfSSL_get0_CA_list + \sa wolfSSL_get0_peer_CA_list +*/ +WOLFSSL_STACK *wolfSSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *ctx); + +/*! + \ingroup TLS + \brief Same as wolfSSL_CTX_set_client_CA_list, but specific to a session. + If a CA list is set on both the context and the session, the list on the + session is used. + + \param [in] ssl Pointer to the WOLFSSL object + \param [in] names List of names to be set. + + \sa wolfSSL_CTX_set_client_CA_list + \sa wolfSSL_CTX_get_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_CTX_set0_CA_list + \sa wolfSSL_set0_CA_list + \sa wolfSSL_CTX_get0_CA_list + \sa wolfSSL_get0_CA_list + \sa wolfSSL_get0_peer_CA_list +*/ +void wolfSSL_set_client_CA_list(WOLFSSL* ssl, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names); + +/*! + \ingroup TLS + \brief On the server, this retrieves the list previously set via + wolfSSL_set_client_CA_list. If none was set, returns the list previously + set via wolfSSL_CTX_set_client_CA_list. If no list at all was set, returns + NULL. + + On the client, this retrieves the list that was received from the server, + or NULL if none was received. wolfSSL_CTX_set_cert_cb can be used to + register a callback to dynamically load certificates when a certificate + request is received from the server. + + \param [in] ssl Pointer to the WOLFSSL object + \return A stack of WOLFSSL_X509_NAMEs containing the CA names + + \sa wolfSSL_CTX_set_cert_cb + \sa wolfSSL_CTX_set_client_CA_list + \sa wolfSSL_CTX_get_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_CTX_set0_CA_list + \sa wolfSSL_set0_CA_list + \sa wolfSSL_CTX_get0_CA_list + \sa wolfSSL_get0_CA_list + \sa wolfSSL_get0_peer_CA_list +*/ +WOLFSSL_STACK* wolfSSL_get_client_CA_list( + const WOLFSSL* ssl); + +/*! + \ingroup TLS + \brief This function sets a list of CA names to be sent to the peer as a + hint for which CA's are supported for its authentication. + + In TLS >= 1.3, this is supported in both directions between the client and + the server. On the server, the CA names will be sent as part of a + CertificateRequest, making this function an equivalent of *_set_client_CA_list; + on the client, these are sent as part of ClientHello. + + In TLS < 1.3, sending CA names from the client to the server is not + supported, therefore this function is equivalent to + wolfSSL_CTX_set_client_CA_list. + + Note that the lists set via *_set_client_CA_list and *_set0_CA_list are + separate internally, i.e. calling *_get_client_CA_list will not retrieve a + list set via *_set0_CA_list and vice versa. If both are set, the server will + ignore *_set0_CA_list when sending CA names to the client. + + \param [in] ctx Pointer to the wolfSSL context + \param [in] names List of names to be set + + \sa wolfSSL_CTX_set_client_CA_list + \sa wolfSSL_set_client_CA_list + \sa wolfSSL_CTX_get_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_set0_CA_list + \sa wolfSSL_CTX_get0_CA_list + \sa wolfSSL_get0_CA_list + \sa wolfSSL_get0_peer_CA_list +*/ +void wolfSSL_CTX_set0_CA_list(WOLFSSL_CTX *ctx, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names); + +/*! + \ingroup TLS + \brief This retrieves the list previously set via + wolfSSL_CTX_set0_CA_list, or NULL if no list has been set. + + \param [in] ctx Pointer to the wolfSSL context + \return A stack of WOLFSSL_X509_NAMEs containing the CA names + + \sa wolfSSL_CTX_set_client_CA_list + \sa wolfSSL_set_client_CA_list + \sa wolfSSL_CTX_get_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_CTX_set0_CA_list + \sa wolfSSL_set0_CA_list + \sa wolfSSL_get0_CA_list + \sa wolfSSL_get0_peer_CA_list +*/ +WOLFSSL_STACK *wolfSSL_CTX_get0_CA_list( + const WOLFSSL_CTX *ctx); + +/*! + \ingroup TLS + \brief Same as wolfSSL_CTX_set0_CA_list, but specific to a session. + If a CA list is set on both the context and the session, the list on the + session is used. + + \param [in] ssl Pointer to the WOLFSSL object + \param [in] names List of names to be set. + + \sa wolfSSL_CTX_set_client_CA_list + \sa wolfSSL_set_client_CA_list + \sa wolfSSL_CTX_get_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_CTX_set0_CA_list + \sa wolfSSL_CTX_get0_CA_list + \sa wolfSSL_get0_CA_list + \sa wolfSSL_get0_peer_CA_list +*/ +void wolfSSL_set0_CA_list(WOLFSSL *ssl, + WOLF_STACK_OF(WOLFSSL_X509_NAME) *names); + +/*! + \ingroup TLS + \brief This retrieves the list previously set via wolfSSL_set0_CA_list. If + none was set, returns the list previously set via + wolfSSL_CTX_set0_CA_list. If no list at all was set, returns NULL. + + \param [in] ssl Pointer to the WOLFSSL object + \return A stack of WOLFSSL_X509_NAMEs containing the CA names + + \sa wolfSSL_CTX_set_client_CA_list + \sa wolfSSL_set_client_CA_list + \sa wolfSSL_CTX_get_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_CTX_set0_CA_list + \sa wolfSSL_set0_CA_list + \sa wolfSSL_CTX_get0_CA_list + \sa wolfSSL_get0_peer_CA_list +*/ +WOLFSSL_STACK *wolfSSL_get0_CA_list( + const WOLFSSL *ssl); + +/*! + \ingroup TLS + \brief This returns the CA list received from the peer. + + On the client, this is the list sent by the server in a CertificateRequest, + and this function is equivalent to wolfSSL_get_client_CA_list. + + On the server, this is the list sent by the client in the ClientHello message + in TLS >= 1.3; in TLS < 1.3, the function always returns NULL on the server + side. + + wolfSSL_CTX_set_cert_cb can be used to register a callback to dynamically + load certificates when a CA list is received from the peer. + + \param [in] ssl Pointer to the WOLFSSL object + \return A stack of WOLFSSL_X509_NAMEs containing the CA names + + \sa wolfSSL_CTX_set_cert_cb + \sa wolfSSL_CTX_set_client_CA_list + \sa wolfSSL_set_client_CA_list + \sa wolfSSL_CTX_get_client_CA_list + \sa wolfSSL_get_client_CA_list + \sa wolfSSL_CTX_set0_CA_list + \sa wolfSSL_set0_CA_list + \sa wolfSSL_CTX_get0_CA_list + \sa wolfSSL_get0_CA_list +*/ +WOLFSSL_STACK *wolfSSL_get0_peer_CA_list(const WOLFSSL *ssl); + +/*! + \ingroup TLS + \brief This function sets a callback that will be called whenever a + certificate is about to be used, to allow the application to inspect, set + or clear any certificates, for example to react to a CA list sent from the + peer. + + \param [in] ctx Pointer to the wolfSSL context + \param [in] cb Function pointer to the callback + \param [in] arg Pointer that will be passed to the callback + + \sa wolfSSL_get0_peer_CA_list + \sa wolfSSL_get_client_CA_list +*/ +void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx, + int (*cb)(WOLFSSL *, void *), void *arg); + /*! \ingroup TLS diff --git a/src/internal.c b/src/internal.c index 4608839eb84..36418b91905 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2877,6 +2877,8 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) #ifndef WOLFSSL_NO_CA_NAMES wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL); ctx->client_ca_names = NULL; + wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL); + ctx->ca_names = NULL; #endif #ifdef OPENSSL_EXTRA if (ctx->x509Chain) { @@ -6667,9 +6669,11 @@ int InitSSL_Suites(WOLFSSL* ssl) byte haveAnon = 0; byte haveRSA = 0; byte haveMcast = 0; + byte haveCertSetupCb = 0; (void)haveAnon; /* Squash unused var warnings */ (void)haveMcast; + (void)haveCertSetupCb; if (!ssl) return BAD_FUNC_ARG; @@ -6688,6 +6692,10 @@ int InitSSL_Suites(WOLFSSL* ssl) haveMcast = (byte)ssl->options.haveMcast; #endif /* WOLFSSL_MULTICAST */ #endif /* !NO_CERTS && !WOLFSSL_SESSION_EXPORT */ +#if defined(WOLFSSL_TLS13) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA) + if (ssl->ctx->certSetupCb != NULL) + haveCertSetupCb = 1; +#endif /* WOLFSSL_TLS13 && !NO_CERTS && OPENSSL_EXTRA */ #ifdef WOLFSSL_EARLY_DATA if (ssl->options.side == WOLFSSL_SERVER_END) @@ -6715,10 +6723,11 @@ int InitSSL_Suites(WOLFSSL* ssl) } #if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) - /* make sure server has cert and key unless using PSK, Anon, or - * Multicast. This should be true even if just switching ssl ctx */ + /* make sure server has cert and key unless using PSK, Anon, + * Multicast or cert setup callback. This should be true even if just + * switching ssl ctx */ if (ssl->options.side == WOLFSSL_SERVER_END && - !havePSK && !haveAnon && !haveMcast) { + !havePSK && !haveAnon && !haveMcast && !haveCertSetupCb) { /* server certificate must be loaded */ if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) { @@ -8789,6 +8798,10 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl) #ifndef WOLFSSL_NO_CA_NAMES wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL); ssl->client_ca_names = NULL; + wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL); + ssl->ca_names = NULL; + wolfSSL_sk_X509_NAME_pop_free(ssl->peer_ca_names, NULL); + ssl->peer_ca_names = NULL; #endif #ifdef WOLFSSL_DTLS13 Dtls13FreeFsmResources(ssl); @@ -24823,7 +24836,7 @@ int SendCertificateRequest(WOLFSSL* ssl) #ifndef WOLFSSL_NO_CA_NAMES /* Certificate Authorities */ - names = SSL_CA_NAMES(ssl); + names = SSL_PRIORITY_CA_NAMES(ssl); while (names != NULL) { byte seq[MAX_SEQ_SZ]; WOLFSSL_X509_NAME* name = names->data.name; @@ -24915,7 +24928,7 @@ int SendCertificateRequest(WOLFSSL* ssl) c16toa((word16)dnLen, &output[i]); /* auth's */ i += REQ_HEADER_SZ; #ifndef WOLFSSL_NO_CA_NAMES - names = SSL_CA_NAMES(ssl); + names = SSL_PRIORITY_CA_NAMES(ssl); while (names != NULL) { byte seq[MAX_SEQ_SZ]; WOLFSSL_X509_NAME* name = names->data.name; @@ -31745,10 +31758,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, return BUFFER_ERROR; #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) - if (ssl->client_ca_names != ssl->ctx->client_ca_names) - wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL); - ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL); - if (ssl->client_ca_names == NULL) { + wolfSSL_sk_X509_NAME_pop_free(ssl->peer_ca_names, NULL); + ssl->peer_ca_names = wolfSSL_sk_X509_NAME_new(NULL); + if (ssl->peer_ca_names == NULL) { return MEMORY_ERROR; } #endif @@ -31793,7 +31805,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, } if (ret == 0) { - if (wolfSSL_sk_X509_NAME_push(ssl->client_ca_names, name) + if (wolfSSL_sk_X509_NAME_push(ssl->peer_ca_names, name) <= 0) { ret = MEMORY_ERROR; diff --git a/src/ssl.c b/src/ssl.c index 794e5991e61..1a691029205 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -12276,7 +12276,28 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ssl->client_ca_names = names; } } -#endif + + void wolfSSL_CTX_set0_CA_list(WOLFSSL_CTX* ctx, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) + { + WOLFSSL_ENTER("wolfSSL_CTX_set0_CA_list"); + if (ctx != NULL) { + wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL); + ctx->ca_names = names; + } + } + + void wolfSSL_set0_CA_list(WOLFSSL* ssl, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) + { + WOLFSSL_ENTER("wolfSSL_set0_CA_list"); + if (ssl != NULL) { + if (ssl->ca_names != ssl->ctx->ca_names) + wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL); + ssl->ca_names = names; + } + } +#endif /* WOLFSSL_NO_CA_NAMES */ #ifdef OPENSSL_EXTRA /* registers client cert callback, called during handshake if server @@ -12508,8 +12529,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return ctx->client_ca_names; } - /* returns the CA's set on server side or the CA's sent from server when - * on client side */ + /* On server side: returns the CAs set via *_set_client_CA_list(); + * On client side: returns the CAs received from server -- same as + * wolfSSL_get0_peer_CA_list() */ WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( const WOLFSSL* ssl) { @@ -12520,21 +12542,79 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return NULL; } + if (ssl->options.side == WOLFSSL_CLIENT_END) + return ssl->peer_ca_names; + else + return SSL_CLIENT_CA_NAMES(ssl); + } + + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get0_CA_list( + const WOLFSSL_CTX *ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_get0_CA_list"); + + if (ctx == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get0_CA_list"); + return NULL; + } + + return ctx->ca_names; + } + + /* Always returns the CA's set via *_set0_CA_list */ + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_CA_list(const WOLFSSL *ssl) + { + WOLFSSL_ENTER("wolfSSL_get0_CA_list"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_CA_list"); + return NULL; + } + return SSL_CA_NAMES(ssl); } + /* Always returns the CA's received from the peer */ + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_peer_CA_list( + const WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_get0_peer_CA_list"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_peer_CA_list"); + return NULL; + } + + return ssl->peer_ca_names; + } + #if !defined(NO_CERTS) - int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + static int add_to_CA_list(WOLFSSL_STACK* ca_names, WOLFSSL_X509* x509) { WOLFSSL_X509_NAME *nameCopy = NULL; - WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); + nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509)); + if (nameCopy == NULL) { + WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); + return WOLFSSL_FAILURE; + } - if (ctx == NULL || x509 == NULL){ - WOLFSSL_MSG("Bad argument"); + if (wolfSSL_sk_X509_NAME_push(ca_names, nameCopy) <= 0) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); + wolfSSL_X509_NAME_free(nameCopy); return WOLFSSL_FAILURE; } + return WOLFSSL_SUCCESS; + } + + int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); + if (ctx == NULL || x509 == NULL) { + WOLFSSL_MSG("Bad argument"); + return WOLFSSL_FAILURE; + } if (ctx->client_ca_names == NULL) { ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL); if (ctx->client_ca_names == NULL) { @@ -12542,22 +12622,60 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return WOLFSSL_FAILURE; } } + return add_to_CA_list(ctx->client_ca_names, x509); + } - nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509)); - if (nameCopy == NULL) { - WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); + int wolfSSL_add_client_CA(WOLFSSL* ssl, WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_add_client_CA"); + if (ssl == NULL || x509 == NULL) { + WOLFSSL_MSG("Bad argument"); return WOLFSSL_FAILURE; } + if (ssl->client_ca_names == NULL) { + ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL); + if (ssl->client_ca_names == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); + return WOLFSSL_FAILURE; + } + } + return add_to_CA_list(ssl->client_ca_names, x509); + } - if (wolfSSL_sk_X509_NAME_push(ctx->client_ca_names, nameCopy) <= 0) { - WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); - wolfSSL_X509_NAME_free(nameCopy); + int wolfSSL_CTX_add1_to_CA_list(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_CTX_add1_to_CA_list"); + if (ctx == NULL || x509 == NULL) { + WOLFSSL_MSG("Bad argument"); return WOLFSSL_FAILURE; } + if (ctx->ca_names == NULL) { + ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL); + if (ctx->ca_names == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); + return WOLFSSL_FAILURE; + } + } + return add_to_CA_list(ctx->ca_names, x509); + } - return WOLFSSL_SUCCESS; + int wolfSSL_add1_to_CA_list(WOLFSSL* ssl, WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_add1_to_CA_list"); + if (ssl == NULL || x509 == NULL) { + WOLFSSL_MSG("Bad argument"); + return WOLFSSL_FAILURE; + } + if (ssl->ca_names == NULL) { + ssl->ca_names = wolfSSL_sk_X509_NAME_new(NULL); + if (ssl->ca_names == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); + return WOLFSSL_FAILURE; + } + } + return add_to_CA_list(ssl->ca_names, x509); } - #endif + #endif /* !NO_CERTS */ #ifndef NO_BIO #if !defined(NO_RSA) && !defined(NO_CERTS) diff --git a/src/tls.c b/src/tls.c index 7ce76aacc56..c8828234d70 100644 --- a/src/tls.c +++ b/src/tls.c @@ -7427,18 +7427,9 @@ static word16 TLSX_CA_Names_GetSize(void* data) WOLF_STACK_OF(WOLFSSL_X509_NAME)* names; word16 size = 0; - if (ssl->options.side == WOLFSSL_CLIENT_END) { - /* To add support use a different member like ssl->ca_names and - * add accessor functions: - * - *_set0_CA_list - * - *_get0_CA_list */ - WOLFSSL_MSG("We don't currently support sending the client's list."); - return 0; - } - /* Length of names */ size += OPAQUE16_LEN; - for (names = SSL_CA_NAMES(ssl); names != NULL; names = names->next) { + for (names = SSL_PRIORITY_CA_NAMES(ssl); names != NULL; names = names->next) { byte seq[MAX_SEQ_SZ]; WOLFSSL_X509_NAME* name = names->data.name; @@ -7457,19 +7448,10 @@ static word16 TLSX_CA_Names_Write(void* data, byte* output) WOLF_STACK_OF(WOLFSSL_X509_NAME)* names; byte* len; - if (ssl->options.side == WOLFSSL_CLIENT_END) { - /* To add support use a different member like ssl->ca_names and - * add accessor functions: - * - *_set0_CA_list - * - *_get0_CA_list */ - WOLFSSL_MSG("We don't currently support sending the client's list."); - return 0; - } - /* Reserve space for the length value */ len = output; output += OPAQUE16_LEN; - for (names = SSL_CA_NAMES(ssl); names != NULL; names = names->next) { + for (names = SSL_PRIORITY_CA_NAMES(ssl); names != NULL; names = names->next) { byte seq[MAX_SEQ_SZ]; WOLFSSL_X509_NAME* name = names->data.name; @@ -7494,19 +7476,9 @@ static int TLSX_CA_Names_Parse(WOLFSSL *ssl, const byte* input, (void)isRequest; - if (ssl->options.side == WOLFSSL_SERVER_END) { - /* To add support use a different member like ssl->ca_names and - * add accessor functions: - * - *_set0_CA_list - * - *_get0_CA_list */ - WOLFSSL_MSG("We don't currently support parsing the client's list."); - return 0; - } - - if (ssl->client_ca_names != ssl->ctx->client_ca_names) - wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL); - ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL); - if (ssl->client_ca_names == NULL) + wolfSSL_sk_X509_NAME_pop_free(ssl->peer_ca_names, NULL); + ssl->peer_ca_names = wolfSSL_sk_X509_NAME_new(NULL); + if (ssl->peer_ca_names == NULL) return MEMORY_ERROR; if (length < OPAQUE16_LEN) @@ -7558,7 +7530,7 @@ static int TLSX_CA_Names_Parse(WOLFSSL *ssl, const byte* input, if (ret == 0) { CopyDecodedName(name, cert, ASN_SUBJECT); - if (wolfSSL_sk_X509_NAME_push(ssl->client_ca_names, name) <= 0) + if (wolfSSL_sk_X509_NAME_push(ssl->peer_ca_names, name) <= 0) ret = MEMORY_ERROR; } @@ -14745,13 +14717,12 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif #ifdef WOLFSSL_TLS13 #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) - if (isServer && IsAtLeastTLSv1_3(ssl->version)) { - if (SSL_CA_NAMES(ssl) != NULL) { - WOLFSSL_MSG("Adding certificate authorities extension"); - if ((ret = TLSX_Push(&ssl->extensions, - TLSX_CERTIFICATE_AUTHORITIES, ssl, ssl->heap)) != 0) { - return ret; - } + if (IsAtLeastTLSv1_3(ssl->version) && + SSL_PRIORITY_CA_NAMES(ssl) != NULL) { + WOLFSSL_MSG("Adding certificate authorities extension"); + if ((ret = TLSX_Push(&ssl->extensions, + TLSX_CERTIFICATE_AUTHORITIES, ssl, ssl->heap)) != 0) { + return ret; } } #endif @@ -15237,10 +15208,13 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word32* pLength) #ifdef WOLFSSL_POST_HANDSHAKE_AUTH TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH)); #endif - #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) + } + #endif + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) + if (!IsAtLeastTLSv1_3(ssl->version) || + SSL_CA_NAMES(ssl) == NULL) { TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES)); - #endif } #endif #endif /* WOLFSSL_TLS13 */ @@ -15263,8 +15237,10 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word32* pLength) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); #endif #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) - if (SSL_CA_NAMES(ssl) != NULL) - TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES)); + if (SSL_PRIORITY_CA_NAMES(ssl) != NULL) { + TURN_OFF(semaphore, + TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES)); + } #endif /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, OID_FILTERS * TLSX_STATUS_REQUEST @@ -15477,16 +15453,18 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word32* pOffset) #ifdef WOLFSSL_POST_HANDSHAKE_AUTH TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH)); #endif - #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) - TURN_ON(semaphore, - TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES)); - #endif #ifdef WOLFSSL_DUAL_ALG_CERTS TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CKS)); #endif } #endif + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) + if (!IsAtLeastTLSv1_3(ssl->version) || SSL_CA_NAMES(ssl) == NULL) { + TURN_ON(semaphore, + TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES)); + } + #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Must write Pre-shared Key extension at the end in TLS v1.3. * Must not write out Pre-shared Key extension in earlier versions of @@ -15513,7 +15491,7 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word32* pOffset) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); #endif #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) - if (SSL_CA_NAMES(ssl) != NULL) { + if (SSL_PRIORITY_CA_NAMES(ssl) != NULL) { TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES)); } diff --git a/src/tls13.c b/src/tls13.c index f984cc1bbf9..0ded4ca255e 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5765,11 +5765,6 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); #endif -#ifdef OPENSSL_EXTRA - if ((ret = CertSetupCbWrapper(ssl)) != 0) - return ret; -#endif - if (OPAQUE8_LEN > size) return BUFFER_ERROR; @@ -5814,6 +5809,11 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, } *inOutIdx += len; +#ifdef OPENSSL_EXTRA + if ((ret = CertSetupCbWrapper(ssl)) != 0) + return ret; +#endif + if ((ssl->buffers.certificate && ssl->buffers.certificate->buffer && ((ssl->buffers.key && ssl->buffers.key->buffer) #ifdef HAVE_PK_CALLBACKS diff --git a/tests/api.c b/tests/api.c index 1ae524f780d..6aaf3eab884 100644 --- a/tests/api.c +++ b/tests/api.c @@ -51074,6 +51074,8 @@ TEST_DECL(test_wc_RsaPSS_DigitalSignVerify), #endif TEST_DECL(test_tls_ems_downgrade), TEST_DECL(test_wolfSSL_DisableExtendedMasterSecret), + TEST_DECL(test_certificate_authorities_certificate_request), + TEST_DECL(test_certificate_authorities_client_hello), TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation), TEST_DECL(test_wolfSSL_SCR_Reconnect), TEST_DECL(test_tls_ext_duplicate), diff --git a/tests/api/test_tls_ext.c b/tests/api/test_tls_ext.c index 58a808b146c..2d6248b2c4b 100644 --- a/tests/api/test_tls_ext.c +++ b/tests/api/test_tls_ext.c @@ -127,3 +127,282 @@ int test_wolfSSL_DisableExtendedMasterSecret(void) #endif return EXPECT_RESULT(); } + + +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + !defined(WOLFSSL_NO_CA_NAMES) && !defined(NO_BIO) && \ + !defined(NO_CERTS) && !defined(NO_TLS) && (defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) && (defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) && \ + (defined(WOLFSSL_TLS13) || !defined(WOLFSSL_NO_TLS12)) +struct client_cb_arg { + WOLF_STACK_OF(X509_NAME) *names1; + WOLF_STACK_OF(X509_NAME) *names2; +}; + +static int certificate_authorities_client_cb(WOLFSSL *ssl, void *_arg) { + struct client_cb_arg *arg = (struct client_cb_arg *)_arg; + arg->names1 = wolfSSL_get_client_CA_list(ssl); + arg->names2 = wolfSSL_get0_peer_CA_list(ssl); + + if (!wolfSSL_use_certificate_file(ssl, cliCertFile, SSL_FILETYPE_PEM)) + return 0; + if (!wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, SSL_FILETYPE_PEM)) + return 0; + return 1; +} +#endif + +int test_certificate_authorities_certificate_request(void) { + EXPECT_DECLS; +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + !defined(WOLFSSL_NO_CA_NAMES) && !defined(NO_BIO) && \ + !defined(NO_CERTS) && !defined(NO_TLS) && (defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) && (defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) && \ + (defined(WOLFSSL_TLS13) || !defined(WOLFSSL_NO_TLS12)) + struct test_params { + method_provider client_meth; + method_provider server_meth; + int doUdp; + } params[] = { +#ifdef WOLFSSL_TLS13 + /* TLS 1.3 uses certificate_authorities extension */ + {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, 0}, +#endif +#if !defined(WOLFSSL_NO_TLS12) && (defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) + /* TLS 1.2 directly embeds CA names in CertificateRequest */ + {wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, 0}, +#endif +#ifdef WOLFSSL_DTLS13 + {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, 1}, +#endif +#if defined(WOLFSSL_DTLS) && (defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) + {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, 1}, +#endif + }; + size_t i; + + for (i = 0; i < sizeof(params) / sizeof(*params); i++) { + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_srv = NULL; + WOLFSSL *ssl_srv = NULL; + WOLFSSL_CTX *ctx_cli = NULL; + WOLFSSL *ssl_cli = NULL; + WOLF_STACK_OF(X509_NAME) *names1 = NULL, *names2 = NULL; + X509_NAME *name = NULL; + struct client_cb_arg cb_arg = { NULL, NULL }; + const char *expected_names[] = { + "/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048" + "/CN=www.wolfssl.com/emailAddress=info@wolfssl.com", + "/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting" + "/CN=www.wolfssl.com/emailAddress=info@wolfssl.com" + }; + + if (EXPECT_FAIL()) + break; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + + ExpectIntEQ(0, test_memio_setup(&test_ctx, &ctx_cli, &ctx_srv, + &ssl_cli, NULL, params[i].client_meth, + params[i].server_meth)); + + wolfSSL_CTX_set_verify(ctx_srv, + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + ExpectIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx_srv, cliCertFile, NULL)); + + ExpectNotNull(ssl_srv = wolfSSL_new(ctx_srv)); + wolfSSL_SetIOReadCtx(ssl_srv, &test_ctx); + wolfSSL_SetIOWriteCtx(ssl_srv, &test_ctx); + + names1 = wolfSSL_load_client_CA_file(cliCertFile); + ExpectNotNull(names1); + names2 = wolfSSL_load_client_CA_file(caCertFile); + ExpectNotNull(names2); + ExpectNotNull(name = wolfSSL_sk_X509_NAME_value(names2, 0)); + ExpectIntEQ(2, wolfSSL_sk_X509_NAME_push(names1, name)); + if (EXPECT_FAIL()) { + wolfSSL_X509_NAME_free(name); + name = NULL; + } + wolfSSL_sk_X509_NAME_free(names2); + names2 = wolfSSL_load_client_CA_file(caCertFile); + ExpectNotNull(names2); + + /* Check that client_CA_list and CA_list are separate internally */ + wolfSSL_CTX_set_client_CA_list(ctx_srv, names1); + wolfSSL_CTX_set0_CA_list(ctx_srv, names2); + ExpectNotNull(names1 = wolfSSL_CTX_get_client_CA_list(ctx_srv)); + ExpectNotNull(names2 = wolfSSL_CTX_get0_CA_list(ctx_srv)); + ExpectIntEQ(2, wolfSSL_sk_X509_NAME_num(names1)); + ExpectIntEQ(1, wolfSSL_sk_X509_NAME_num(names2)); + + /* Check that get_client_CA_list and get0_CA_list on ssl return same as + * ctx when not set */ + ExpectNotNull(names1 = wolfSSL_get_client_CA_list(ssl_srv)); + ExpectNotNull(names2 = wolfSSL_get0_CA_list(ssl_srv)); + ExpectIntEQ(2, wolfSSL_sk_X509_NAME_num(names1)); + ExpectIntEQ(1, wolfSSL_sk_X509_NAME_num(names2)); + + /* Same checks as before, but on ssl rather than ctx */ + names1 = wolfSSL_load_client_CA_file(cliCertFile); + ExpectNotNull(names1); + names2 = wolfSSL_load_client_CA_file(caCertFile); + ExpectNotNull(names2); + ExpectNotNull(name = wolfSSL_sk_X509_NAME_value(names2, 0)); + ExpectIntEQ(2, wolfSSL_sk_X509_NAME_push(names1, name)); + if (EXPECT_FAIL()) { + wolfSSL_X509_NAME_free(name); + name = NULL; + } + wolfSSL_sk_X509_NAME_free(names2); + names2 = wolfSSL_load_client_CA_file(caCertFile); + ExpectNotNull(names2); + + wolfSSL_set_client_CA_list(ssl_srv, names1); + wolfSSL_set0_CA_list(ssl_srv, names2); + ExpectNotNull(names1 = wolfSSL_get_client_CA_list(ssl_srv)); + ExpectNotNull(names2 = wolfSSL_get0_CA_list(ssl_srv)); + ExpectIntEQ(2, wolfSSL_sk_X509_NAME_num(names1)); + ExpectIntEQ(1, wolfSSL_sk_X509_NAME_num(names2)); + + + /* Certs will be loaded in callback */ + wolfSSL_CTX_set_cert_cb(ctx_cli, + certificate_authorities_client_cb, &cb_arg); + + ExpectIntEQ(0, test_memio_do_handshake(ssl_cli, ssl_srv, 10, NULL)); + + ExpectNotNull(cb_arg.names1); + ExpectNotNull(cb_arg.names2); + ExpectIntEQ(2, wolfSSL_sk_X509_NAME_num(cb_arg.names1)); + ExpectIntEQ(2, wolfSSL_sk_X509_NAME_num(cb_arg.names2)); + + if (EXPECT_SUCCESS()) { + ExpectStrEQ(wolfSSL_sk_X509_NAME_value(cb_arg.names1, 0)->name, + expected_names[0]); + ExpectStrEQ(wolfSSL_sk_X509_NAME_value(cb_arg.names1, 1)->name, + expected_names[1]); + } + + wolfSSL_shutdown(ssl_cli); + wolfSSL_free(ssl_cli); + wolfSSL_CTX_free(ctx_cli); + wolfSSL_free(ssl_srv); + wolfSSL_CTX_free(ctx_srv); + } +#endif + return EXPECT_RESULT(); +} + + +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + !defined(WOLFSSL_NO_CA_NAMES) && !defined(NO_BIO) && \ + !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) && (defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) && defined(WOLFSSL_TLS13) +static int certificate_authorities_server_cb(WOLFSSL *ssl, void *_arg) { + WOLF_STACK_OF(X509_NAME) **names_out = (WOLF_STACK_OF(X509_NAME) **)_arg; + WOLF_STACK_OF(X509_NAME) *names = wolfSSL_get0_peer_CA_list(ssl); + *names_out = names; + if (!wolfSSL_use_certificate_file(ssl, svrCertFile, SSL_FILETYPE_PEM)) + return 0; + if (!wolfSSL_use_PrivateKey_file(ssl, svrKeyFile, SSL_FILETYPE_PEM)) + return 0; + return 1; +} +#endif + +int test_certificate_authorities_client_hello(void) { + EXPECT_DECLS; +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + !defined(WOLFSSL_NO_CA_NAMES) && !defined(NO_BIO) && \ + !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) && (defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) && defined(WOLFSSL_TLS13) + + struct test_params { + method_provider client_meth; + method_provider server_meth; + int doUdp; + } params[] = { + /* TLS >= 1.3 only */ +#ifdef WOLFSSL_TLS13 + {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, 0}, +#endif +#ifdef WOLFSSL_DTLS13 + {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, 1}, +#endif + }; + size_t i; + + for (i = 0; i < sizeof(params) / sizeof(*params); i++) { + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_srv = NULL; + WOLFSSL *ssl_srv = NULL; + WOLFSSL_CTX *ctx_cli = NULL; + WOLFSSL *ssl_cli = NULL; + WOLF_STACK_OF(X509_NAME) *cb_arg = NULL; + WOLF_STACK_OF(X509_NAME) *names1 = NULL, *names2 = NULL; + X509_NAME *name = NULL; + const char *expected_names[] = { + "/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting" + "/CN=www.wolfssl.com/emailAddress=info@wolfssl.com", + "/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048" + "/CN=www.wolfssl.com/emailAddress=info@wolfssl.com" + }; + + if (EXPECT_FAIL()) + break; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + + ExpectIntEQ(0, test_memio_setup(&test_ctx, &ctx_cli, &ctx_srv, + &ssl_cli, &ssl_srv, params[i].client_meth, + params[i].server_meth)); + + wolfSSL_CTX_set_cert_cb(ctx_srv, certificate_authorities_server_cb, + &cb_arg); + + names1 = wolfSSL_load_client_CA_file(caCertFile); + ExpectNotNull(names1); + names2 = wolfSSL_load_client_CA_file(cliCertFile); + ExpectNotNull(names2); + ExpectNotNull(name = wolfSSL_sk_X509_NAME_value(names2, 0)); + ExpectIntEQ(2, wolfSSL_sk_X509_NAME_push(names1, name)); + if (EXPECT_FAIL()) { + wolfSSL_X509_NAME_free(name); + name = NULL; + } + wolfSSL_sk_X509_NAME_free(names2); + names2 = wolfSSL_load_client_CA_file(cliCertFile); + ExpectNotNull(names2); + + /* verify that set0_CA_list takes precedence */ + wolfSSL_set0_CA_list(ssl_cli, names1); + wolfSSL_CTX_set0_CA_list(ctx_cli, names2); + + ExpectIntEQ(0, test_memio_do_handshake(ssl_cli, ssl_srv, 10, NULL)); + + ExpectIntEQ(wolfSSL_sk_X509_NAME_num(cb_arg), 2); + + if (EXPECT_SUCCESS()) { + ExpectStrEQ(wolfSSL_sk_X509_NAME_value(cb_arg, 0)->name, + expected_names[0]); + ExpectStrEQ(wolfSSL_sk_X509_NAME_value(cb_arg, 1)->name, + expected_names[1]); + } + + wolfSSL_shutdown(ssl_cli); + wolfSSL_free(ssl_cli); + wolfSSL_CTX_free(ctx_cli); + wolfSSL_free(ssl_srv); + wolfSSL_CTX_free(ctx_srv); + } +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_tls_ext.h b/tests/api/test_tls_ext.h index a6d7287f21b..3506d02e967 100644 --- a/tests/api/test_tls_ext.h +++ b/tests/api/test_tls_ext.h @@ -24,5 +24,7 @@ int test_tls_ems_downgrade(void); int test_wolfSSL_DisableExtendedMasterSecret(void); +int test_certificate_authorities_certificate_request(void); +int test_certificate_authorities_client_hello(void); #endif /* TESTS_API_TEST_TLS_EMS_H */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 82876b27ca1..65023af1c33 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1090,11 +1090,22 @@ #undef WSSL_HARDEN_TLS -/* Client CA Names feature */ +/* CA Names feature */ #if !defined(WOLFSSL_NO_CA_NAMES) && defined(OPENSSL_EXTRA) - #define SSL_CA_NAMES(ssl) ((ssl)->client_ca_names != NULL ? \ + #define SSL_CLIENT_CA_NAMES(ssl) ((ssl)->client_ca_names != NULL ? \ (ssl)->client_ca_names : \ (ssl)->ctx->client_ca_names) + #define SSL_CA_NAMES(ssl) ((ssl)->ca_names != NULL ? \ + (ssl)->ca_names : \ + (ssl)->ctx->ca_names) + /* On the server, client_ca_names has priority over ca_names if both are + * set. This mimics OpenSSL's API: + * https://docs.openssl.org/3.6/man3/SSL_CTX_set0_CA_list/ */ + #define SSL_PRIORITY_CA_NAMES(ssl) \ + (((ssl)->options.side == WOLFSSL_SERVER_END && \ + SSL_CLIENT_CA_NAMES(ssl) != NULL) ? \ + SSL_CLIENT_CA_NAMES(ssl) : \ + SSL_CA_NAMES(ssl)) #else #undef WOLFSSL_NO_CA_NAMES #define WOLFSSL_NO_CA_NAMES @@ -3830,6 +3841,7 @@ struct WOLFSSL_CTX { /* chain after self, in DER, with leading size for each cert */ #ifndef WOLFSSL_NO_CA_NAMES WOLF_STACK_OF(WOLFSSL_X509_NAME)* client_ca_names; + WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; #endif #ifdef OPENSSL_EXTRA WOLF_STACK_OF(WOLFSSL_X509)* x509Chain; @@ -6310,7 +6322,12 @@ struct WOLFSSL { byte serverFinished_len; #endif #ifndef WOLFSSL_NO_CA_NAMES - WOLF_STACK_OF(WOLFSSL_X509_NAME)* client_ca_names; + WOLF_STACK_OF(WOLFSSL_X509_NAME)* client_ca_names; /* Used in *_set/get_client_CA_list + (server only) */ + WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; /* Used in *_set0/get0_CA_list */ + WOLF_STACK_OF(WOLFSSL_X509_NAME)* peer_ca_names; /* Used in *_get0_peer_CA_list + and (client only) + wolfSSL_get_client_CA_list */ #endif #if defined(WOLFSSL_IOTSAFE) && defined(HAVE_PK_CALLBACKS) IOTSAFE iotsafe; diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 326f0fd5be2..582f9b75457 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1044,6 +1044,8 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_get_client_CA_list wolfSSL_CTX_get_client_CA_list #define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list +#define SSL_CTX_get0_CA_list wolfSSL_CTX_get0_CA_list +#define SSL_CTX_set0_CA_list wolfSSL_CTX_set0_CA_list #define SSL_CTX_set_client_cert_cb wolfSSL_CTX_set_client_cert_cb #define SSL_CTX_set_cert_store wolfSSL_CTX_set_cert_store #ifdef OPENSSL_ALL @@ -1054,6 +1056,9 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((x)) #define SSL_get_client_CA_list wolfSSL_get_client_CA_list #define SSL_set_client_CA_list wolfSSL_set_client_CA_list +#define SSL_get0_CA_list wolfSSL_get0_CA_list +#define SSL_set0_CA_list wolfSSL_set0_CA_list +#define SSL_get0_peer_CA_list wolfSSL_get0_peer_CA_list #define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx #define SSL_get_ex_data wolfSSL_get_ex_data @@ -1743,6 +1748,9 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; #ifdef OPENSSL_EXTRA #define SSL_CTX_add_client_CA wolfSSL_CTX_add_client_CA +#define SSL_add_client_CA wolfSSL_add_client_CA +#define SSL_CTX_add1_to_CA_list wolfSSL_CTX_add1_to_CA_list +#define SSL_add1_to_CA_list wolfSSL_add1_to_CA_list #define SSL_CTX_set_srp_password wolfSSL_CTX_set_srp_password #define SSL_CTX_set_srp_username wolfSSL_CTX_set_srp_username #define SSL_CTX_set_srp_strength wolfSSL_CTX_set_srp_strength diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 7b056684d49..8f370ee1a53 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -2425,6 +2425,17 @@ WOLFSSL_API void wolfSSL_set_client_CA_list(WOLFSSL* ssl, WOLF_STACK_OF(WOLFSSL_X509_NAME)*); WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( const WOLFSSL* ssl); + +WOLFSSL_API void wolfSSL_CTX_set0_CA_list(WOLFSSL_CTX *ctx, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names); +WOLFSSL_API void wolfSSL_set0_CA_list(WOLFSSL *ssl, + WOLF_STACK_OF(WOLFSSL_X509_NAME) *names); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_CTX_get0_CA_list( + const WOLFSSL_CTX *ctx); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_get0_CA_list( + const WOLFSSL *ssl); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_get0_peer_CA_list( + const WOLFSSL *ssl); #endif /* !WOLFSSL_NO_CA_NAMES */ typedef int (*client_cert_cb)(WOLFSSL *ssl, WOLFSSL_X509 **x509, @@ -2536,6 +2547,9 @@ WOLFSSL_API long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg); WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg( WOLFSSL_CTX* ctx, void* arg); WOLFSSL_API int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509); +WOLFSSL_API int wolfSSL_add_client_CA(WOLFSSL *ssl, WOLFSSL_X509 *x509); +WOLFSSL_API int wolfSSL_CTX_add1_to_CA_list(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x509); +WOLFSSL_API int wolfSSL_add1_to_CA_list(WOLFSSL *ssl, WOLFSSL_X509 *x509); WOLFSSL_API int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password); WOLFSSL_API int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username); WOLFSSL_API int wolfSSL_CTX_set_srp_strength(WOLFSSL_CTX *ctx, int strength);