Merge pull request #6544 from TakayukiMatsuo/rpk

Add support for raw-public-key
This commit is contained in:
JacobBarthelmeh 2023-08-17 09:23:18 -06:00 committed by GitHub
commit cc4e327316
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 2504 additions and 3 deletions

View File

@ -140,4 +140,5 @@ include certs/falcon/include.am
include certs/rsapss/include.am
include certs/dilithium/include.am
include certs/sphincs/include.am
include certs/rpk/include.am

View File

@ -687,6 +687,28 @@ run_renewcerts(){
echo "End of section"
echo "---------------------------------------------------------------------"
############################################################
########## update Raw Public Key certificates ##############
############################################################
echo "Updating certificates"
echo "Updating client-cert-rpk.der"
cp client-keyPub.der ./rpk/client-cert-rpk.der
check_result $? "Step 1"
echo "Updating client-ecc-cert-rpk.der"
cp ecc-client-keyPub.der ./rpk/ecc-client-cert-rpk.der
check_result $? "Step 2"
echo "Updating server-cert-rpk.der"
openssl rsa -inform pem -in server-key.pem -outform der -out ./rpk/server-cert-rpk.der -pubout
check_result $? "Step 3"
echo "Updating server-ecc-cert-rpk.der"
openssl ec -inform pem -in ecc-key.pem -outform der -out ./rpk/server-ecc-cert-rpk.der -pubout
check_result $? "Step 4"
echo "End of section"
echo "---------------------------------------------------------------------"
############################################################
###### update the ecc-rsa-server.p12 file ##################
############################################################

Binary file not shown.

Binary file not shown.

9
certs/rpk/include.am Normal file
View File

@ -0,0 +1,9 @@
# vim:ft=automake
# All paths should be given relative to the root
#
EXTRA_DIST += \
certs/rpk/client-cert-rpk.der \
certs/rpk/client-ecc-cert-rpk.der \
certs/rpk/server-cert-rpk.der \
certs/rpk/server-ecc-cert-rpk.der

Binary file not shown.

Binary file not shown.

View File

@ -9515,6 +9515,195 @@ WOLFSSL_METHOD *wolfTLSv1_3_method_ex(void* heap);
*/
WOLFSSL_METHOD *wolfTLSv1_3_method(void);
/*!
\ingroup Setup
\brief Certificateメッセージで送信できる証明書タイプを設定します
Raw Public Key 使
NULLを渡すか0
X509証明書WOLFSSL_CERT_TYPE_X509
\return WOLFSSL_SUCCESS
\return BAD_FUNC_ARG ctxとしてNULLを渡した
MAX_CLIENT_CERT_TYPE_CNT以上のバッファサイズを指定した
\param ctx wolfssl_ctxコンテキストポインタ
\param ctype
\param len
_Example_
\code
int ret;
WOLFSSL_CTX* ctx;
char ctype[] = {WOLFSSL_CERT_TYPE_RPK, WOLFSSL_CERT_TYPE_X509};
int len = sizeof(ctype)/sizeof(byte);
 ...
ret = wolfSSL_CTX_set_client_cert_type(ctx, ctype, len);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len);
/*!
\ingroup Setup
\brief Certificateメッセージで送信できる証明書タイプを設定します
Raw Public Key 使
NULLを渡すか0
X509証明書WOLFSSL_CERT_TYPE_X509
\return WOLFSSL_SUCCESS
\return BAD_FUNC_ARG ctxとしてNULLを渡した
MAX_SERVER_CERT_TYPE_CNT以上のバッファサイズを指定した
\param ctx wolfssl_ctxコンテキストポインタ
\param ctype
\param len
_Example_
\code
int ret;
WOLFSSL_CTX* ctx;
char ctype[] = {WOLFSSL_CERT_TYPE_RPK, WOLFSSL_CERT_TYPE_X509};
int len = sizeof(ctype)/sizeof(byte);
 ...
ret = wolfSSL_CTX_set_server_cert_type(ctx, ctype, len);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_client_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len);
/*!
\ingroup Setup
\brief Certificateメッセージで送信できる証明書タイプを設定します
Raw Public Key 使
NULLを渡すか0
X509証明書WOLFSSL_CERT_TYPE_X509
\return WOLFSSL_SUCCESS
\return BAD_FUNC_ARG sslとしてNULLを渡した
MAX_CLIENT_CERT_TYPE_CNT以上のバッファサイズを指定した
\param ssl WOLFSSL構造体へのポインタ
\param ctype
\param len
_Example_
\code
int ret;
WOLFSSL* ssl;
char ctype[] = {WOLFSSL_CERT_TYPE_RPK, WOLFSSL_CERT_TYPE_X509};
int len = sizeof(ctype)/sizeof(byte);
 ...
ret = wolfSSL_set_client_cert_type(ssl, ctype, len);
\endcode
\sa wolfSSL_CTX_set_client_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_set_client_cert_type(WOLFSSL* ssl, const char* buf, int len);
/*!
\ingroup Setup
\brief Certificateメッセージで送信できる証明書タイプを設定します
Raw Public Key 使
NULLを渡すか0
X509証明書WOLFSSL_CERT_TYPE_X509
\return WOLFSSL_SUCCESS
\return BAD_FUNC_ARG ctxとしてNULLを渡した
MAX_SERVER_CERT_TYPE_CNT以上のバッファサイズを指定した
\param ssl WOLFSSL構造体へのポインタ
\param ctype
\param len
_Example_
\code
int ret;
WOLFSSL* ssl;
char ctype[] = {WOLFSSL_CERT_TYPE_RPK, WOLFSSL_CERT_TYPE_X509};
int len = sizeof(ctype)/sizeof(byte);
 ...
ret = wolfSSL_set_server_cert_type(ssl, ctype, len);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_set_server_cert_type(WOLFSSL* ssl, const char* buf, int len);
/*!
\ingroup SSL
\brief
WOLFSSL_SUCCESSが返されますが
WOLFSSL_CERT_TYPE_UNKNOWNが返されます
\return WOLFSSL_SUCCESS tpに返された証明書タイプはWOLFSSL_CERT_TYPE_X509,
WOLFSSL_CERT_TYPE_RPK WOLFSSL_CERT_TYPE_UNKNOWNのいずれかとなります
\return BAD_FUNC_ARG sslとしてNULLを渡したtpとしてNULLを渡した
\param ssl WOLFSSL構造体へのポインタ
\param tp
_Example_
\code
int ret;
WOLFSSL* ssl;
int tp;
 ...
ret = wolfSSL_get_negotiated_client_cert_type(ssl, &tp);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_client_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp);
/*!
\ingroup SSL
\brief
WOLFSSL_SUCCESSが返されますがWOLFSSL_CERT_TYPE_UNKNOWNが返されます
\return WOLFSSL_SUCCESS tpに返された証明書タイプはWOLFSSL_CERT_TYPE_X509,
WOLFSSL_CERT_TYPE_RPK WOLFSSL_CERT_TYPE_UNKNOWNのいずれかとなります
\return BAD_FUNC_ARG sslとしてNULLを渡したtpとしてNULLを渡した
\param ssl WOLFSSL構造体へのポインタ
\param tp
_Example_
\code
int ret;
WOLFSSL* ssl;
int tp;
 ...
ret = wolfSSL_get_negotiated_server_cert_type(ssl, &tp);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_client_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
*/
int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp);
/*!
\ingroup SSL
\brief /

View File

@ -14490,6 +14490,211 @@ unsigned int wolfSSL_SESSION_get_max_early_data(const WOLFSSL_SESSION *s);
*/
int wolfSSL_CRYPTO_get_ex_new_index(int, void*, void*, void*, void*);
/*!
\ingroup Setup
\brief In case this function is called in a client side, set certificate types
that can be sent to its peer. In case called in a server side,
set certificate types that can be acceptable from its peer. Put cert types in the
buffer with prioritised order. To reset the settings to default, pass NULL
for the buffer or pass zero for len. By default, certificate type is only X509.
In case both side intend to send or accept "Raw public key" cert,
WOLFSSL_CERT_TYPE_RPK should be included in the buffer to set.
\return WOLFSSL_SUCCESS if cert types set successfully
\return BAD_FUNC_ARG if NULL was passed for ctx, illegal value was specified as
cert type, buf size exceed MAX_CLIENT_CERT_TYPE_CNT was specified or
a duplicate value is found in buf.
\param ctx WOLFSSL_CTX object pointer
\param buf A buffer where certificate types are stored
\param len buf size in bytes (same as number of certificate types included)
_Example_
\code
int ret;
WOLFSSL_CTX* ctx;
char buf[] = {WOLFSSL_CERT_TYPE_RPK, WOLFSSL_CERT_TYPE_X509};
int len = sizeof(buf)/sizeof(char);
...
ret = wolfSSL_CTX_set_client_cert_type(ctx, buf, len);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len);
/*!
\ingroup Setup
\brief In case this function is called in a server side, set certificate types
that can be sent to its peer. In case called in a client side,
set certificate types that can be acceptable from its peer. Put cert types in the
buffer with prioritised order. To reset the settings to default, pass NULL
for the buffer or pass zero for len. By default, certificate type is only X509.
In case both side intend to send or accept "Raw public key" cert,
WOLFSSL_CERT_TYPE_RPK should be included in the buffer to set.
\return WOLFSSL_SUCCESS if cert types set successfully
\return BAD_FUNC_ARG if NULL was passed for ctx, illegal value was specified as
cert type, buf size exceed MAX_SERVER_CERT_TYPE_CNT was specified or
a duplicate value is found in buf.
\param ctx WOLFSSL_CTX object pointer
\param buf A buffer where certificate types are stored
\param len buf size in bytes (same as number of certificate types included)
_Example_
\code
int ret;
WOLFSSL_CTX* ctx;
char buf[] = {WOLFSSL_CERT_TYPE_RPK, WOLFSSL_CERT_TYPE_X509};
int len = sizeof(buf)/sizeof(char);
...
ret = wolfSSL_CTX_set_server_cert_type(ctx, buf, len);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_client_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len);
/*!
\ingroup Setup
\brief In case this function is called in a client side, set certificate types
that can be sent to its peer. In case called in a server side,
set certificate types that can be acceptable from its peer. Put cert types in the
buffer with prioritised order. To reset the settings to default, pass NULL
for the buffer or pass zero for len. By default, certificate type is only X509.
In case both side intend to send or accept "Raw public key" cert,
WOLFSSL_CERT_TYPE_RPK should be included in the buffer to set.
\return WOLFSSL_SUCCESS if cert types set successfully
\return BAD_FUNC_ARG if NULL was passed for ctx, illegal value was specified as
cert type, buf size exceed MAX_CLIENT_CERT_TYPE_CNT was specified or
a duplicate value is found in buf.
\param ssl WOLFSSL object pointer
\param buf A buffer where certificate types are stored
\param len buf size in bytes (same as number of certificate types included)
_Example_
\code
int ret;
WOLFSSL* ssl;
char buf[] = {WOLFSSL_CERT_TYPE_RPK, WOLFSSL_CERT_TYPE_X509};
int len = sizeof(buf)/sizeof(char);
...
ret = wolfSSL_set_client_cert_type(ssl, buf, len);
\endcode
\sa wolfSSL_CTX_set_client_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_set_client_cert_type(WOLFSSL* ssl, const char* buf, int len);
/*!
\ingroup Setup
\brief In case this function is called in a server side, set certificate types
that can be sent to its peer. In case called in a client side,
set certificate types that can be acceptable from its peer. Put cert types in the
buffer with prioritised order. To reset the settings to default, pass NULL
for the buffer or pass zero for len. By default, certificate type is only X509.
In case both side intend to send or accept "Raw public key" cert,
WOLFSSL_CERT_TYPE_RPK should be included in the buffer to set.
\return WOLFSSL_SUCCESS if cert types set successfully
\return BAD_FUNC_ARG if NULL was passed for ctx, illegal value was specified as
cert type, buf size exceed MAX_SERVER_CERT_TYPE_CNT was specified or
a duplicate value is found in buf.
\param ctx WOLFSSL_CTX object pointer
\param buf A buffer where certificate types are stored
\param len buf size in bytes (same as number of certificate types included)
_Example_
\code
int ret;
WOLFSSL* ssl;
char buf[] = {WOLFSSL_CERT_TYPE_RPK, WOLFSSL_CERT_TYPE_X509};
int len = sizeof(buf)/sizeof(char);
...
ret = wolfSSL_set_server_cert_type(ssl, buf, len);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_set_server_cert_type(WOLFSSL* ssl, const char* buf, int len);
/*!
\ingroup SSL
\brief This function returns the result of the client certificate type
negotiation done in ClientHello and ServerHello. WOLFSSL_SUCCESS is returned as
a return value if no negotiation occurs and WOLFSSL_CERT_TYPE_UNKNOWN is
returned as the certificate type.
\return WOLFSSL_SUCCESS if a negotiated certificate type could be got
\return BAD_FUNC_ARG if NULL was passed for ctx or tp
\param ssl WOLFSSL object pointer
\param tp A buffer where a certificate type is to be returned. One of three
certificate types will be returned: WOLFSSL_CERT_TYPE_RPK,
WOLFSSL_CERT_TYPE_X509 or WOLFSSL_CERT_TYPE_UNKNOWN.
_Example_
\code
int ret;
WOLFSSL* ssl;
int tp;
...
ret = wolfSSL_get_negotiated_client_cert_type(ssl, &tp);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_client_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_get_negotiated_server_cert_type
*/
int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp);
/*!
\ingroup SSL
\brief This function returns the result of the server certificate type
negotiation done in ClientHello and ServerHello. WOLFSSL_SUCCESS is returned as
a return value if no negotiation occurs and WOLFSSL_CERT_TYPE_UNKNOWN is
returned as the certificate type.
\return WOLFSSL_SUCCESS if a negotiated certificate type could be got
\return BAD_FUNC_ARG if NULL was passed for ctx or tp
\param ssl WOLFSSL object pointer
\param tp A buffer where a certificate type is to be returned. One of three
certificate types will be returned: WOLFSSL_CERT_TYPE_RPK,
WOLFSSL_CERT_TYPE_X509 or WOLFSSL_CERT_TYPE_UNKNOWN.
_Example_
\code
int ret;
WOLFSSL* ssl;
int tp;
 ...
ret = wolfSSL_get_negotiated_server_cert_type(ssl, &tp);
\endcode
\sa wolfSSL_set_client_cert_type
\sa wolfSSL_CTX_set_client_cert_type
\sa wolfSSL_set_server_cert_type
\sa wolfSSL_CTX_set_server_cert_type
\sa wolfSSL_get_negotiated_client_cert_type
*/
int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp);
/*!
\brief Enable use of ConnectionID extensions for the SSL object. See RFC 9146

View File

@ -2279,6 +2279,11 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
#endif /* MICRIUM */
#endif /* WOLFSSL_USER_IO */
#if defined(HAVE_RPK)
wolfSSL_CTX_set_client_cert_type(ctx, NULL, 0); /* set to default */
wolfSSL_CTX_set_server_cert_type(ctx, NULL, 0); /* set to default */
#endif /* HAVE_RPK */
#ifdef HAVE_PQC
#ifdef HAVE_FALCON
if (method->side == WOLFSSL_CLIENT_END)
@ -6671,6 +6676,11 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->buffers.serverDH_G = ctx->serverDH_G;
#endif
#if defined(HAVE_RPK)
ssl->options.rpkConfig = ctx->rpkConfig;
ssl->options.rpkState = ctx->rpkState;
#endif /* HAVE_RPK */
#ifndef NO_CERTS
/* ctx still owns certificate, certChain, key, dh, and cm */
ssl->buffers.certificate = ctx->certificate;
@ -12754,6 +12764,11 @@ void DoCertFatalAlert(WOLFSSL* ssl, int ret)
alertWhy = certificate_revoked;
}
#endif
#if defined(HAVE_RPK)
else if (ret == UNSUPPORTED_CERTIFICATE) {
alertWhy = unsupported_certificate;
}
#endif /* HAVE_RPK */
else if (ret == NO_PEER_CERT) {
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3) {
@ -13344,6 +13359,9 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args,
buffer* cert;
byte* subjectHash = NULL;
int alreadySigner = 0;
#if defined(HAVE_RPK)
int cType;
#endif
#ifdef WOLFSSL_SMALL_CERT_VERIFY
int sigRet = 0;
#endif
@ -13445,6 +13463,37 @@ PRAGMA_GCC_DIAG_POP
/* Parse Certificate */
ret = ParseCertRelative(args->dCert, certType, verify, SSL_CM(ssl));
#if defined(HAVE_RPK)
/* if cert type has negotiated with peer, confirm the cert received has
* the same type.
*/
if (ret == 0 ) {
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (ssl->options.rpkState.received_ServerCertTypeCnt == 1) {
cType = ssl->options.rpkState.received_ServerCertTypes[0];
if ((cType == WOLFSSL_CERT_TYPE_RPK && !args->dCert->isRPK) ||
(cType == WOLFSSL_CERT_TYPE_X509 && args->dCert->isRPK)) {
/* cert type mismatch */
WOLFSSL_MSG("unsuported certificate type received");
ret = UNSUPPORTED_CERTIFICATE;
}
}
}
else if (ssl->options.side == WOLFSSL_SERVER_END) {
if (ssl->options.rpkState.received_ClientCertTypeCnt == 1) {
cType = ssl->options.rpkState.sending_ClientCertTypes[0];
if ((cType == WOLFSSL_CERT_TYPE_RPK && !args->dCert->isRPK) ||
(cType == WOLFSSL_CERT_TYPE_X509 && args->dCert->isRPK)) {
/* cert type mismatch */
WOLFSSL_MSG("unsuported certificate type received");
ret = UNSUPPORTED_CERTIFICATE;
}
}
}
}
#endif /* HAVE_RPK */
/* perform below checks for date failure cases */
if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) {
/* get subject and determine if already loaded */
@ -14265,6 +14314,20 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
* OpenSSL doesn't appear to be performing this check.
* For TLS 1.3 see RFC8446 Section 4.4.2.3 */
if (ssl->options.side == WOLFSSL_SERVER_END) {
#if defined(HAVE_RPK)
if (args->dCert->isRPK) {
/* to verify Raw Public Key cert, DANE(RFC6698)
* should be introduced. Without DANE, no
* authentication is performed.
*/
#if defined(HAVE_DANE)
if (ssl->useDANE) {
/* DANE authentication should be added */
}
#endif /* HAVE_DANE */
}
else /* skip followingx509 version check */
#endif /* HAVE_RPK */
if (args->dCert->version != WOLFSSL_X509_V3) {
WOLFSSL_MSG("Peers certificate was not version 3!");
args->lastErr = ASN_VERSION_E;
@ -24396,6 +24459,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case SOCKET_FILTERED_E:
return "Session stopped by network filter";
case UNSUPPORTED_CERTIFICATE:
return "Unsupported certificate type";
#ifdef HAVE_HTTP_CLIENT
case HTTP_TIMEOUT:
return "HTTP timeout for OCSP or CRL req";

240
src/ssl.c
View File

@ -7406,6 +7406,20 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
#endif
return WOLFSSL_BAD_FILE;
}
#if defined(HAVE_RPK)
if (ssl) {
ssl->options.rpkState.isRPKLoaded = 0;
if (cert->isRPK) {
ssl->options.rpkState.isRPKLoaded = 1;
}
}
else if (ctx) {
ctx->rpkState.isRPKLoaded = 0;
if (cert->isRPK) {
ctx->rpkState.isRPKLoaded = 1;
}
}
#endif /* HAVE_RPK */
if (ssl) {
if (ssl->options.side == WOLFSSL_SERVER_END)
@ -10187,6 +10201,232 @@ int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
#endif /* OPENSSL_EXTRA */
#if defined(HAVE_RPK)
/* Confirm that all the byte data in the buffer is unique.
* return 1 if all the byte data in the buffer is unique, otherwise 0.
*/
static int isArrayUnique(const char* buf, size_t len)
{
size_t i, j;
/* check the array is unique */
for (i = 0; i < len -1; ++i) {
for (j = i+ 1; j < len; ++j) {
if (buf[i] == buf[j]) {
return 0;
}
}
}
return 1;
}
/* Set user preference for the client_cert_type exetnsion.
* Takes byte array containing cert types the caller can provide to its peer.
* Cert types are in preferred order in the array.
*/
WOLFSSL_API int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx,
const char* buf, int bufLen)
{
int i;
if (ctx == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) {
return BAD_FUNC_ARG;
}
/* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/
if (buf == NULL || bufLen == 0) {
ctx->rpkConfig.preferred_ClientCertTypeCnt = 1;
ctx->rpkConfig.preferred_ClientCertTypes[0]= WOLFSSL_CERT_TYPE_X509;
ctx->rpkConfig.preferred_ClientCertTypes[1]= WOLFSSL_CERT_TYPE_X509;
return WOLFSSL_SUCCESS;
}
if (!isArrayUnique(buf, bufLen))
return BAD_FUNC_ARG;
for (i = 0; i < bufLen; i++){
if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509)
return BAD_FUNC_ARG;
ctx->rpkConfig.preferred_ClientCertTypes[i] = buf[i];
}
ctx->rpkConfig.preferred_ClientCertTypeCnt = bufLen;
return WOLFSSL_SUCCESS;
}
/* Set user preference for the server_cert_type exetnsion.
* Takes byte array containing cert types the caller can provide to its peer.
* Cert types are in preferred order in the array.
*/
WOLFSSL_API int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx,
const char* buf, int bufLen)
{
int i;
if (ctx == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) {
return BAD_FUNC_ARG;
}
/* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/
if (buf == NULL || bufLen == 0) {
ctx->rpkConfig.preferred_ServerCertTypeCnt = 1;
ctx->rpkConfig.preferred_ServerCertTypes[0]= WOLFSSL_CERT_TYPE_X509;
ctx->rpkConfig.preferred_ServerCertTypes[1]= WOLFSSL_CERT_TYPE_X509;
return WOLFSSL_SUCCESS;
}
if (!isArrayUnique(buf, bufLen))
return BAD_FUNC_ARG;
for (i = 0; i < bufLen; i++){
if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509)
return BAD_FUNC_ARG;
ctx->rpkConfig.preferred_ServerCertTypes[i] = buf[i];
}
ctx->rpkConfig.preferred_ServerCertTypeCnt = bufLen;
return WOLFSSL_SUCCESS;
}
/* Set user preference for the client_cert_type exetnsion.
* Takes byte array containing cert types the caller can provide to its peer.
* Cert types are in preferred order in the array.
*/
WOLFSSL_API int wolfSSL_set_client_cert_type(WOLFSSL* ssl,
const char* buf, int bufLen)
{
int i;
if (ssl == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) {
return BAD_FUNC_ARG;
}
/* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/
if (buf == NULL || bufLen == 0) {
ssl->options.rpkConfig.preferred_ClientCertTypeCnt = 1;
ssl->options.rpkConfig.preferred_ClientCertTypes[0]
= WOLFSSL_CERT_TYPE_X509;
ssl->options.rpkConfig.preferred_ClientCertTypes[1]
= WOLFSSL_CERT_TYPE_X509;
return WOLFSSL_SUCCESS;
}
if (!isArrayUnique(buf, bufLen))
return BAD_FUNC_ARG;
for (i = 0; i < bufLen; i++){
if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509)
return BAD_FUNC_ARG;
ssl->options.rpkConfig.preferred_ClientCertTypes[i] = buf[i];
}
ssl->options.rpkConfig.preferred_ClientCertTypeCnt = bufLen;
return WOLFSSL_SUCCESS;
}
/* Set user preference for the server_cert_type exetnsion.
* Takes byte array containing cert types the caller can provide to its peer.
* Cert types are in preferred order in the array.
*/
WOLFSSL_API int wolfSSL_set_server_cert_type(WOLFSSL* ssl,
const char* buf, int bufLen)
{
int i;
if (ssl == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) {
return BAD_FUNC_ARG;
}
/* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/
if (buf == NULL || bufLen == 0) {
ssl->options.rpkConfig.preferred_ServerCertTypeCnt = 1;
ssl->options.rpkConfig.preferred_ServerCertTypes[0]
= WOLFSSL_CERT_TYPE_X509;
ssl->options.rpkConfig.preferred_ServerCertTypes[1]
= WOLFSSL_CERT_TYPE_X509;
return WOLFSSL_SUCCESS;
}
if (!isArrayUnique(buf, bufLen))
return BAD_FUNC_ARG;
for (i = 0; i < bufLen; i++){
if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509)
return BAD_FUNC_ARG;
ssl->options.rpkConfig.preferred_ServerCertTypes[i] = buf[i];
}
ssl->options.rpkConfig.preferred_ServerCertTypeCnt = bufLen;
return WOLFSSL_SUCCESS;
}
/* get negotiated certificate type value and return it to the second parameter.
* cert type value:
* -1: WOLFSSL_CERT_TYPE_UNKNOWN
* 0: WOLFSSL_CERT_TYPE_X509
* 2: WOLFSSL_CERT_TYPE_RPK
* return WOLFSSL_SUCCESS on success, otherwise negative value.
* in case no negotiation performed, it returns WOLFSSL_SUCCESS and -1 is for
* cert type.
*/
WOLFSSL_API int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp)
{
int ret = WOLFSSL_SUCCESS;
if (ssl == NULL || tp == NULL)
return BAD_FUNC_ARG;
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (ssl->options.rpkState.received_ClientCertTypeCnt == 1)
*tp = ssl->options.rpkState.received_ClientCertTypes[0];
else
*tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
else {
if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1)
*tp = ssl->options.rpkState.sending_ClientCertTypes[0];
else
*tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
return ret;
}
/* get negotiated certificate type value and return it to the second parameter.
* cert type value:
* -1: WOLFSSL_CERT_TYPE_UNKNOWN
* 0: WOLFSSL_CERT_TYPE_X509
* 2: WOLFSSL_CERT_TYPE_RPK
* return WOLFSSL_SUCCESS on success, otherwise negative value.
* in case no negotiation performed, it returns WOLFSSL_SUCCESS and -1 is for
* cert type.
*/
WOLFSSL_API int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp)
{
int ret = WOLFSSL_SUCCESS;
if (ssl == NULL || tp == NULL)
return BAD_FUNC_ARG;
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (ssl->options.rpkState.received_ServerCertTypeCnt == 1)
*tp = ssl->options.rpkState.received_ServerCertTypes[0];
else
*tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
else {
if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1)
*tp = ssl->options.rpkState.sending_ServerCertTypes[0];
else
*tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
return ret;
}
#endif /* HAVE_RPK */
int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der,
int derSz)
{

542
src/tls.c
View File

@ -10729,6 +10729,497 @@ static int TLSX_QuicTP_Parse(WOLFSSL *ssl, const byte *input, size_t len, int ex
#define CID_FREE(a, b) 0
#endif /* defined(WOLFSSL_DTLS_CID) */
#if defined(HAVE_RPK)
/******************************************************************************/
/* Client_Certificate_Type extension */
/******************************************************************************/
/* return 1 if specified type is included in the given list, otherwise 0 */
static int IsCertTypeListed(byte type, byte cnt, const byte* list)
{
int ret = 0;
int i;
if (cnt == 0 || list == NULL)
return ret;
if (cnt > 0 && cnt <= MAX_CLIENT_CERT_TYPE_CNT) {
for (i = 0; i < cnt; i++) {
if (list[i] == type)
return 1;
}
}
return 0;
}
/* Search both arrays from above to find a common value between the two given
* arrays(a and b). return 1 if it finds a common value, otherwise return 0.
*/
static int GetCommonItem(const byte* a, byte aLen, const byte* b, byte bLen,
byte* type)
{
int i, j;
if (a == NULL || b == NULL)
return 0;
for (i = 0; i < aLen; i++) {
for (j = 0; j < bLen; j++) {
if (a[i] == b[j]) {
*type = a[i];
return 1;
}
}
}
return 0;
}
/* Creates a "client certificate type" extension if necessary.
* Returns 0 if no error occured, negative value otherwise.
* A return of 0, it does not indicae that the extension was created.
*/
static int TLSX_ClientCertificateType_Use(WOLFSSL* ssl, byte isServer)
{
int ret = 0;
if (ssl == NULL)
return BAD_FUNC_ARG;
if (isServer) {
/* [in server side]
*/
if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
ssl->options.rpkConfig.preferred_ClientCertTypes)) {
WOLFSSL_MSG("Adding Client Certificate Type extension");
ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE, ssl,
ssl->heap);
if (ret == 0) {
TLSX_SetResponse(ssl, TLSX_CLIENT_CERTIFICATE_TYPE);
}
}
}
else {
/* [in client side]
* This extension MUST be omitted from the ClientHello unless the RPK
* certificate is preferred by the user and actually loaded.
*/
if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
ssl->options.rpkConfig.preferred_ClientCertTypes)) {
if (ssl->options.rpkState.isRPKLoaded) {
ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
ssl->options.rpkState.sending_ClientCertTypes[0] =
WOLFSSL_CERT_TYPE_RPK;
/* Push new client_certificate_type extension. */
WOLFSSL_MSG("Adding Client Certificate Type extension");
ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE,
ssl, ssl->heap);
}
else {
WOLFSSL_MSG("Willing to use RPK cert but not loaded it");
}
}
else {
WOLFSSL_MSG("No will to use RPK cert");
}
}
return ret;
}
/* Parse a "client certificate type" extension received from peer.
* returns 0 on success and other values indicate failure.
*/
static int TLSX_ClientCertificateType_Parse(WOLFSSL* ssl, const byte* input,
word16 length, byte msgType)
{
byte typeCnt;
int idx = 0;
int ret = 0;
int i;
int populate = 0;
byte cmnType;
if (msgType == client_hello) {
/* [parse ClientHello in server end]
* case 1) if peer verify is disabled, this extension must be omitted
* from ServerHello.
* case 2) if user have not set his preference, find X509 in parsed
* result, then populate "Client Certificate Type" extension.
* case 3) if user have not set his preference and X509 isn't included
* in parsed result, send "unsupported certificate" alert.
* case 4) if user have set his preference, find a common cert type
* in users preference and received cert types.
* case 5) if user have set his preference, but no common cert type
* found.
*/
/* case 1 */
if (ssl->options.verifyNone) {
return ret;
}
/* parse extension */
if (length < OPAQUE8_LEN)
return BUFFER_E;
typeCnt = input[idx];
if (typeCnt > MAX_CLIENT_CERT_TYPE_CNT)
return BUFFER_E;
if ((typeCnt + 1) * OPAQUE8_LEN != length){
return BUFFER_E;
}
ssl->options.rpkState.received_ClientCertTypeCnt = input[idx];
idx += OPAQUE8_LEN;
for (i = 0; i < typeCnt; i++) {
ssl->options.rpkState.received_ClientCertTypes[i] = input[idx];
idx += OPAQUE8_LEN;
}
if (ssl->options.rpkConfig.preferred_ClientCertTypeCnt == 0) {
/* case 2 */
if (IsCertTypeListed(WOLFSSL_CERT_TYPE_X509,
ssl->options.rpkState.received_ClientCertTypeCnt,
ssl->options.rpkState.received_ClientCertTypes)) {
ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
ssl->options.rpkState.sending_ClientCertTypes[0] =
WOLFSSL_CERT_TYPE_X509;
populate = 1;
}
/* case 3 */
else {
WOLFSSL_MSG("No common cert type found in client_certificate_type ext");
SendAlert(ssl, alert_fatal, unsupported_certificate);
return UNSUPPORTED_CERTIFICATE;
}
}
else if (ssl->options.rpkConfig.preferred_ClientCertTypeCnt > 0) {
/* case 4 */
if (GetCommonItem(
ssl->options.rpkConfig.preferred_ClientCertTypes,
ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
ssl->options.rpkState.received_ClientCertTypes,
ssl->options.rpkState.received_ClientCertTypeCnt,
&cmnType)) {
ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
ssl->options.rpkState.sending_ClientCertTypes[0] = cmnType;
populate = 1;
}
/* case 5 */
else {
WOLFSSL_MSG("No common cert type found in client_certificate_type ext");
SendAlert(ssl, alert_fatal, unsupported_certificate);
return UNSUPPORTED_CERTIFICATE;
}
}
/* populate client_certificate_type extension */
if (populate) {
WOLFSSL_MSG("Adding Client Certificate Type extension");
ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE, ssl,
ssl->heap);
if (ret == 0) {
TLSX_SetResponse(ssl, TLSX_CLIENT_CERTIFICATE_TYPE);
}
}
}
else if (msgType == server_hello || msgType == encrypted_extensions) {
/* parse it in client side */
if (length == 1) {
ssl->options.rpkState.received_ClientCertTypeCnt = 1;
ssl->options.rpkState.received_ClientCertTypes[0] = *input;
}
else {
return BUFFER_E;
}
}
return ret;
}
/* Write out the "client certificate type" extension data into the given buffer.
* return the size wrote in the buffer on success, negative value on error.
*/
static word16 TLSX_ClientCertificateType_Write(void* data, byte* output,
byte msgType)
{
WOLFSSL* ssl = (WOLFSSL*)data;
word16 idx = 0;
byte cnt = 0;
int i;
/* skip to write extension if count is zero */
cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;
if (cnt == 0)
return 0;
if (msgType == client_hello) {
/* client side */
*(output + idx) = cnt;
idx += OPAQUE8_LEN;
for (i = 0; i < cnt; i++) {
*(output + idx) = ssl->options.rpkState.sending_ClientCertTypes[i];
idx += OPAQUE8_LEN;
}
return idx;
}
else if (msgType == server_hello || msgType == encrypted_extensions) {
/* sever side */
if (cnt == 1) {
*(output + idx) = ssl->options.rpkState.sending_ClientCertTypes[0];
idx += OPAQUE8_LEN;
}
}
return idx;
}
/* Calculate then return the size of the "client certificate type" extension
* data.
* return the extension data size on success, negative value on error.
*/
static int TLSX_ClientCertificateType_GetSize(WOLFSSL* ssl, byte msgType)
{
int ret = 0;
byte cnt;
if (ssl == NULL)
return BAD_FUNC_ARG;
if (msgType == client_hello) {
/* client side */
cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;
ret = (int)(OPAQUE8_LEN + cnt * OPAQUE8_LEN);
}
else if (msgType == server_hello || msgType == encrypted_extensions) {
/* sever side */
cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;/* must be one */
ret = OPAQUE8_LEN;
}
else {
return SANITY_MSG_E;
}
return ret;
}
#define CCT_GET_SIZE TLSX_ClientCertificateType_GetSize
#define CCT_WRITE TLSX_ClientCertificateType_Write
#define CCT_PARSE TLSX_ClientCertificateType_Parse
#else
#define CCT_GET_SIZE(a) 0
#define CCT_WRITE(a, b) 0
#define CCT_PARSE(a, b, c, d) 0
#endif /* HAVE_RPK */
#if defined(HAVE_RPK)
/******************************************************************************/
/* Server_Certificate_Type extension */
/******************************************************************************/
/* Creates a "server certificate type" extension if necessary.
* Returns 0 if no error occured, negative value otherwise.
* A return of 0, it does not indicae that the extension was created.
*/
static int TLSX_ServerCertificateType_Use(WOLFSSL* ssl, byte isServer)
{
int ret = 0;
byte ctype;
if (ssl == NULL)
return BAD_FUNC_ARG;
if (isServer) {
/* [in server side] */
/* find common cert type to both end */
if (GetCommonItem(
ssl->options.rpkConfig.preferred_ServerCertTypes,
ssl->options.rpkConfig.preferred_ServerCertTypeCnt,
ssl->options.rpkState.received_ServerCertTypes,
ssl->options.rpkState.received_ServerCertTypeCnt,
&ctype)) {
ssl->options.rpkState.sending_ServerCertTypeCnt = 1;
ssl->options.rpkState.sending_ServerCertTypes[0] = ctype;
/* Push new server_certificate_type extension. */
WOLFSSL_MSG("Adding Server Certificate Type extension");
ret = TLSX_Push(&ssl->extensions, TLSX_SERVER_CERTIFICATE_TYPE, ssl,
ssl->heap);
if (ret == 0) {
TLSX_SetResponse(ssl, TLSX_SERVER_CERTIFICATE_TYPE);
}
}
else {
/* no common cert type found */
WOLFSSL_MSG("No common cert type found in server_certificate_type ext");
SendAlert(ssl, alert_fatal, unsupported_certificate);
ret = UNSUPPORTED_CERTIFICATE;
}
}
else {
/* [in client side] */
if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
ssl->options.rpkConfig.preferred_ServerCertTypeCnt,
ssl->options.rpkConfig.preferred_ServerCertTypes)) {
ssl->options.rpkState.sending_ServerCertTypeCnt =
ssl->options.rpkConfig.preferred_ServerCertTypeCnt;
XMEMCPY(ssl->options.rpkState.sending_ServerCertTypes,
ssl->options.rpkConfig.preferred_ServerCertTypes,
ssl->options.rpkConfig.preferred_ServerCertTypeCnt);
/* Push new server_certificate_type extension. */
WOLFSSL_MSG("Adding Server Certificate Type extension");
ret = TLSX_Push(&ssl->extensions, TLSX_SERVER_CERTIFICATE_TYPE, ssl,
ssl->heap);
}
else {
WOLFSSL_MSG("No will to accept RPK cert");
}
}
return ret;
}
/* Parse a "server certificate type" extension received from peer.
* returns 0 on success and other values indicate failure.
*/
static int TLSX_ServerCertificateType_Parse(WOLFSSL* ssl, const byte* input,
word16 length, byte msgType)
{
byte typeCnt;
int idx = 0;
int ret = 0;
int i;
if (msgType == client_hello) {
/* in server side */
if (length < OPAQUE8_LEN)
return BUFFER_E;
typeCnt = input[idx];
if (typeCnt > MAX_SERVER_CERT_TYPE_CNT)
return BUFFER_E;
if ((typeCnt + 1) * OPAQUE8_LEN != length){
return BUFFER_E;
}
ssl->options.rpkState.received_ServerCertTypeCnt = input[idx];
idx += OPAQUE8_LEN;
for (i = 0; i < typeCnt; i++) {
ssl->options.rpkState.received_ServerCertTypes[i] = input[idx];
idx += OPAQUE8_LEN;
}
ret = TLSX_ServerCertificateType_Use(ssl, 1);
if (ret == 0) {
TLSX_SetResponse(ssl, TLSX_SERVER_CERTIFICATE_TYPE);
}
}
else if (msgType == server_hello || msgType == encrypted_extensions) {
/* in client side */
if (length != 1) /* length slould be 1 */
return BUFFER_E;
ssl->options.rpkState.received_ServerCertTypeCnt = 1;
ssl->options.rpkState.received_ServerCertTypes[0] = *input;
}
return 0;
}
/* Write out the "server certificate type" extension data into the given buffer.
* return the size wrote in the buffer on success, negative value on error.
*/
static word16 TLSX_ServerCertificateType_Write(void* data, byte* output,
byte msgType)
{
WOLFSSL* ssl = (WOLFSSL*)data;
word16 idx = 0;
int cnt = 0;
int i;
/* skip to write extension if count is zero */
cnt = ssl->options.rpkState.sending_ServerCertTypeCnt;
if (cnt == 0)
return 0;
if (msgType == client_hello) {
/* in client side */
*(output + idx) = cnt;
idx += OPAQUE8_LEN;
for (i = 0; i < cnt; i++) {
*(output + idx) = ssl->options.rpkState.sending_ServerCertTypes[i];
idx += OPAQUE8_LEN;
}
}
else if (msgType == server_hello || msgType == encrypted_extensions) {
/* in server side */
/* ensure cnt is one */
if (cnt != 1)
return 0;
*(output + idx) = ssl->options.rpkState.sending_ServerCertTypes[0];
idx += OPAQUE8_LEN;
}
return idx;
}
/* Calculate then return the size of the "server certificate type" extension
* data.
* return the extension data size on success, negative value on error.
*/
static int TLSX_ServerCertificateType_GetSize(WOLFSSL* ssl, byte msgType)
{
int ret = 0;
int cnt;
if (ssl == NULL)
return BAD_FUNC_ARG;
if (msgType == client_hello) {
/* in clent side */
cnt = ssl->options.rpkState.sending_ServerCertTypeCnt;
if (cnt > 0) {
ret = (int)(OPAQUE8_LEN + cnt * OPAQUE8_LEN);
}
}
else if (msgType == server_hello || msgType == encrypted_extensions) {
/* in server side */
ret = (int)OPAQUE8_LEN;
}
else {
return SANITY_MSG_E;
}
return ret;
}
#define SCT_GET_SIZE TLSX_ServerCertificateType_GetSize
#define SCT_WRITE TLSX_ServerCertificateType_Write
#define SCT_PARSE TLSX_ServerCertificateType_Parse
#else
#define SCT_GET_SIZE(a) 0
#define SCT_WRITE(a, b) 0
#define SCT_PARSE(a, b, c, d) 0
#endif /* HAVE_RPK */
/******************************************************************************/
/* TLS Extensions Framework */
/******************************************************************************/
@ -11468,6 +11959,13 @@ void TLSX_FreeAll(TLSX* list, void* heap)
switch (extension->type) {
#if defined(HAVE_RPK)
case TLSX_CLIENT_CERTIFICATE_TYPE:
case TLSX_SERVER_CERTIFICATE_TYPE:
/* nothing to do */
break;
#endif
#ifdef HAVE_SNI
case TLSX_SERVER_NAME:
SNI_FREE_ALL((SNI*)extension->data, heap);
@ -11751,6 +12249,16 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
break;
#endif
#ifdef HAVE_RPK
case TLSX_CLIENT_CERTIFICATE_TYPE:
length += CCT_GET_SIZE((WOLFSSL*)extension->data, msgType);
break;
case TLSX_SERVER_CERTIFICATE_TYPE:
length += SCT_GET_SIZE((WOLFSSL*)extension->data, msgType);
break;
#endif /* HAVE_RPK */
#ifdef WOLFSSL_QUIC
case TLSX_KEY_QUIC_TP_PARAMS:
FALL_THROUGH; /* followed by */
@ -11962,6 +12470,19 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
offset += SRTP_WRITE((TlsxSrtp*)extension->data, output+offset);
break;
#endif
#ifdef HAVE_RPK
case TLSX_CLIENT_CERTIFICATE_TYPE:
WOLFSSL_MSG("Client Certificate Type extension to write");
offset += CCT_WRITE(extension->data, output + offset, msgType);
break;
case TLSX_SERVER_CERTIFICATE_TYPE:
WOLFSSL_MSG("Server Certificate Type extension to write");
offset += SCT_WRITE(extension->data, output + offset, msgType);
break;
#endif /* HAVE_RPK */
#ifdef WOLFSSL_QUIC
case TLSX_KEY_QUIC_TP_PARAMS:
FALL_THROUGH;
@ -12258,6 +12779,16 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
/* server will add extension depending on what is parsed from client */
if (!isServer) {
#if defined(HAVE_RPK)
ret = TLSX_ClientCertificateType_Use(ssl, isServer);
if (ret != 0)
return ret;
ret = TLSX_ServerCertificateType_Use(ssl, isServer);
if (ret != 0)
return ret;
#endif /* HAVE_RPK */
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (!ssl->options.disallowEncThenMac) {
ret = TLSX_EncryptThenMac_Use(ssl);
@ -14080,6 +14611,17 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
break;
#endif /* defined(WOLFSSL_DTLS_CID) */
#if defined(HAVE_RPK)
case TLSX_CLIENT_CERTIFICATE_TYPE:
WOLFSSL_MSG("Client Certificate Type extension received");
ret = CCT_PARSE(ssl, input + offset, size, msgType);
break;
case TLSX_SERVER_CERTIFICATE_TYPE:
WOLFSSL_MSG("Server Certificate Type extension received");
ret = SCT_PARSE(ssl, input + offset, size, msgType);
break;
#endif /* HAVE_RPK */
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
case TLSX_ECH:
ret = ECH_PARSE(ssl, input + offset, size, msgType);

File diff suppressed because it is too large Load Diff

View File

@ -15055,6 +15055,54 @@ static int DecodeCertInternal(DecodedCert* cert, int verify, int* criticalExt,
int stopAfterPubKey);
#endif
/* Assumes the target is a Raw-Public-Key certificate and parsed up to the
* public key. Returns CRYPTOCB_UNAVAILABLE if it determines that the cert is
* different from the Paw-Public-Key cert. In that case, cert->srcIdx is not
* consumed so as successing parse function can take over.
* In case that the target is Raw-Public-Key cert and contains a public key,
* returns 0 and consumes cert->srcIdx so as a public key retrieval function
* can follow.
*/
#if defined(HAVE_RPK)
int TryDecodeRPKToKey(DecodedCert* cert)
{
int ret = 0, len;
word32 tmpIdx;
word32 oid;
WOLFSSL_ENTER("TryDecodeRPKToKey");
if (cert == NULL)
return BAD_FUNC_ARG;
tmpIdx = cert->srcIdx;
/* both X509 cert and RPK cert should start with a Sequence tag */
if (ret == 0) {
if (GetSequence(cert->source, &tmpIdx, &len, cert->maxIdx) < 0)
ret = ASN_PARSE_E;
}
/* TBSCertificate of X509 or AlgorithmIdentifier of RPK cert */
if (ret == 0) {
if (GetSequence(cert->source, &tmpIdx, &len, cert->maxIdx) < 0)
ret = ASN_PARSE_E;
}
/* OBJ ID should be next in RPK cert */
if (ret == 0) {
if (GetObjectId(cert->source, &tmpIdx, &oid, oidKeyType, cert->maxIdx)
< 0)
ret = CRYPTOCB_UNAVAILABLE;
}
/* consume cert->srcIdx */
if (ret == 0) {
WOLFSSL_MSG("Looks like RPK certificate");
cert->srcIdx = tmpIdx;
}
WOLFSSL_LEAVE("TryDecodeRPKToKey", ret);
return ret;
}
#endif /* HAVE_RPK */
/* Parse the certificate up to the X.509 public key.
*
* If cert data is invalid then badDate get set to error value.
@ -15147,6 +15195,20 @@ int DecodeToKey(DecodedCert* cert, int verify)
int badDate = 0;
int ret;
#if defined(HAVE_RPK)
/* Raw Public Key certificate has only a SubjectPublicKeyInfo structure
* as its contents. So try to call GetCertKey to get public key from it.
* If it fails, the cert should be a X509 cert and proceed to process as
* x509 cert. */
ret = GetCertKey(cert, cert->source, &cert->srcIdx, cert->maxIdx);
if (ret == 0) {
WOLFSSL_MSG("Raw Public Key certificate found and parsed");
cert->isRPK = 1;
return ret;
}
#endif /* HAVE_RPK */
if ( (ret = wc_GetPubX509(cert, verify, &badDate)) < 0)
return ret;
@ -20751,6 +20813,41 @@ end:
}
#ifdef WOLFSSL_ASN_TEMPLATE
#if defined(HAVE_RPK)
/* ASN template for a Raw Public Key certificate defined RFC7250. */
static const ASNItem RPKCertASN[] = {
/* SubjectPublicKeyInfo ::= SEQUENCE */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* algorithm AlgorithmIdentifier */
/* AlgorithmIdentifier ::= SEQUENCE */ { 1, ASN_SEQUENCE, 1, 1, 0 },
/* Algorithm OBJECT IDENTIFIER */
/* TBS_SPUBKEYINFO_ALGO_OID */ { 2, ASN_OBJECT_ID, 0, 0, 0 },
/* parameters ANY defined by algorithm OPTIONAL */
/* TBS_SPUBKEYINFO_ALGO_NULL */ { 2, ASN_TAG_NULL, 0, 0, 2 },
/* TBS_SPUBKEYINFO_ALGO_CURVEID */ { 2, ASN_OBJECT_ID, 0, 0, 2 },
#ifdef WC_RSA_PSS
/* TBS_SPUBKEYINFO_ALGO_P_SEQ */ { 2, ASN_SEQUENCE, 1, 0, 2 },
#endif
/* subjectPublicKey BIT STRING */
/* TBS_SPUBKEYINFO_PUBKEY */ { 1, ASN_BIT_STRING, 0, 0, 0 },
};
/* Number of items in ASN template for a RawPublicKey certificate. */
#define RPKCertASN_Length (sizeof(RPKCertASN) / sizeof(ASNItem))
enum {
RPKCERTASN_IDX_SPUBKEYINFO_SEQ = 0,
RPKCERTASN_IDX_SPUBKEYINFO_ALGO_SEQ,
RPKCERTASN_IDX_SPUBKEYINFO_ALGO_OID,
RPKCERTASN_IDX_SPUBKEYINFO_ALGO_NULL,
RPKCERTASN_IDX_SPUBKEYINFO_ALGO_CURVEID,
#ifdef WC_RSA_PSS
RPKCERTASN_IDX_SPUBKEYINFO_ALGO_P_SEQ,
#endif
RPKCERTASN_IDX_SPUBKEYINFO_PUBKEY,
};
#endif /* HAVE_RPK */
/* ASN template for an X509 certificate.
* X.509: RFC 5280, 4.1 - Basic Certificate Fields.
*/
@ -20955,6 +21052,40 @@ static int DecodeCertInternal(DecodedCert* cert, int verify, int* criticalExt,
word32 pubKeyEnd = 0;
int done = 0;
#if defined(HAVE_RPK)
/* try to parse the cert as Raw Public Key cert */
DECL_ASNGETDATA(RPKdataASN, RPKCertASN_Length);
CALLOC_ASNGETDATA(RPKdataASN, RPKCertASN_Length, ret, cert->heap);
GetASN_OID(&RPKdataASN[RPKCERTASN_IDX_SPUBKEYINFO_ALGO_OID],
oidKeyType);
GetASN_OID(&RPKdataASN[RPKCERTASN_IDX_SPUBKEYINFO_ALGO_CURVEID],
oidCurveType);
ret = GetASN_Items(RPKCertASN, RPKdataASN, RPKCertASN_Length, 1,
cert->source, &cert->srcIdx, cert->maxIdx);
if (ret == 0) {
cert->keyOID =
RPKdataASN[RPKCERTASN_IDX_SPUBKEYINFO_ALGO_OID].data.oid.sum;
/* Parse the public key. */
pubKeyOffset = RPKdataASN[RPKCERTASN_IDX_SPUBKEYINFO_SEQ].offset;
pubKeyEnd = cert->maxIdx;
ret = GetCertKey(cert, cert->source, &pubKeyOffset, pubKeyEnd);
if (ret == 0) {
WOLFSSL_MSG("Raw Public Key certificate found and parsed");
cert->isRPK = 1;
}
}
/* Dispose of memory before allocating for extension decoding. */
FREE_ASNGETDATA(RPKdataASN, cert->heap);
if (ret == 0) {
return ret;
}
else {
ret = 0; /* proceed to the original x509 parsing */
}
#endif /* HAVE_RPK */
CALLOC_ASNGETDATA(dataASN, x509CertASN_Length, ret, cert->heap);
if (ret == 0) {
@ -22536,7 +22667,11 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
}
WOLFSSL_MSG("Parsed Past Key");
#if defined(HAVE_RPK)
if (cert->isRPK) {
return ret;
}
#endif /* HAVE_RPK */
#ifdef WOLFSSL_CERT_REQ
/* Read attributes */
@ -22781,6 +22916,11 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
WOLFSSL_ERROR_VERBOSE(ret);
return ret;
}
#if defined(HAVE_RPK)
if (cert->isRPK) {
return ret;
}
#endif /* HAVE_RPK */
}
#endif

View File

@ -191,7 +191,8 @@ enum wolfSSL_ErrorCodes {
COMPRESSION_ERROR = -502, /* compression mismatch */
KEY_SHARE_ERROR = -503, /* key share mismatch */
POST_HAND_AUTH_ERROR = -504, /* client won't do post-hand auth */
HRR_COOKIE_ERROR = -505 /* HRR msg cookie mismatch */
HRR_COOKIE_ERROR = -505, /* HRR msg cookie mismatch */
UNSUPPORTED_CERTIFICATE = -506 /* unsupported certificate type */
/* end negotiation parameter errors only 10 for now */
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */

View File

@ -2790,6 +2790,10 @@ typedef enum {
#endif
TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */
TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */
#ifdef HAVE_RPK
TLSX_CLIENT_CERTIFICATE_TYPE = 0x0013, /* RFC8446 */
TLSX_SERVER_CERTIFICATE_TYPE = 0x0014, /* RFC8446 */
#endif
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
TLSX_ENCRYPT_THEN_MAC = 0x0016, /* RFC 7366 */
#endif
@ -2835,6 +2839,36 @@ typedef enum {
#endif
} TLSX_Type;
/* TLS Certificate type defined RFC7250
* https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#tls-extensiontype-values-3
*/
#if defined(HAVE_RPK)
typedef struct RpkConfig {
/* user's preference */
byte preferred_ClientCertTypeCnt;
byte preferred_ClientCertTypes[MAX_CLIENT_CERT_TYPE_CNT];
byte preferred_ServerCertTypeCnt;
byte preferred_ServerCertTypes[MAX_CLIENT_CERT_TYPE_CNT];
/* reflect to client_certificate_type extension in xxxHello */
} RpkConfig;
typedef struct RpkState {
byte sending_ClientCertTypeCnt;
byte sending_ClientCertTypes[MAX_CLIENT_CERT_TYPE_CNT];
/* reflect to server_certificate_type extension in xxxHello */
byte sending_ServerCertTypeCnt;
byte sending_ServerCertTypes[MAX_SERVER_CERT_TYPE_CNT];
/* client_certificate_type extension in received yyyHello */
byte received_ClientCertTypeCnt;
byte received_ClientCertTypes[MAX_CLIENT_CERT_TYPE_CNT];
/* server_certificate_type extension in received yyyHello */
byte received_ServerCertTypeCnt;
byte received_ServerCertTypes[MAX_SERVER_CERT_TYPE_CNT];
/* set if Raw-public-key cert is loaded as own certificate */
int isRPKLoaded;
} RpkState;
#endif /* HAVE_RPK */
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
typedef enum {
@ -3585,7 +3619,10 @@ struct WOLFSSL_CTX {
#endif
word16 minProto:1; /* sets min to min available */
word16 maxProto:1; /* sets max to max available */
#if defined(HAVE_RPK)
RpkConfig rpkConfig;
RpkState rpkState;
#endif /* HAVE_RPK */
#ifdef WOLFSSL_SRTP
word16 dtlsSrtpProfiles; /* DTLS-with-SRTP mode
* (list of selected profiles - up to 16) */
@ -4689,6 +4726,13 @@ struct Options {
#ifdef WOLFSSL_SEND_HRR_COOKIE
word16 cookieGood:1;
#endif
#if defined(HAVE_DANE)
word16 useDANE:1;
#endif /* HAVE_DANE */
#if defined(HAVE_RPK)
RpkConfig rpkConfig;
RpkState rpkState;
#endif /* HAVE_RPK */
/* need full byte values for this section */
byte processReply; /* nonblocking resume */

View File

@ -5138,6 +5138,29 @@ WOLFSSL_API int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
const unsigned char** key, unsigned int* keySz);
#endif
#ifdef HAVE_RPK
/* cert type for client_certificate_type/server_certificate_type extensions */
enum {
WOLFSSL_CERT_TYPE_UNKNOWN = -1,
WOLFSSL_CERT_TYPE_X509 = 0,
WOLFSSL_CERT_TYPE_RPK = 2,
};
#define MAX_CLIENT_CERT_TYPE_CNT 2
#define MAX_SERVER_CERT_TYPE_CNT 2
WOLFSSL_API int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx,
const char* buf, int len);
WOLFSSL_API int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx,
const char* buf, int len);
WOLFSSL_API int wolfSSL_set_client_cert_type(WOLFSSL* ssl,
const char* buf, int len);
WOLFSSL_API int wolfSSL_set_server_cert_type(WOLFSSL* ssl,
const char* buf, int len);
WOLFSSL_API int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp);
WOLFSSL_API int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp);
#endif /* HAVE_RPK */
#if defined(OPENSSL_EXTRA)
#ifndef WOLFCRYPT_ONLY
WOLFSSL_API int wolfSSL_EVP_PKEY_param_check(WOLFSSL_EVP_PKEY_CTX* ctx);

View File

@ -1925,6 +1925,9 @@ struct DecodedCert {
#ifdef WOLFSSL_CERT_REQ
byte isCSR : 1; /* Do we intend on parsing a CSR? */
#endif
#ifdef HAVE_RPK
byte isRPK : 1; /* indicate the cert is Raw-Public-Key cert in RFC7250 */
#endif
#if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \
&& defined(HAVE_OID_DECODING)
wc_UnknownExtCallback unknownExtCallback;
@ -2106,6 +2109,7 @@ WOLFSSL_LOCAL int DecodeToKey(DecodedCert* cert, int verify);
#ifdef WOLFSSL_ASN_TEMPLATE
WOLFSSL_LOCAL int DecodeCert(DecodedCert* cert, int verify, int* criticalExt);
#endif
WOLFSSL_LOCAL int TryDecodeRPKToKey(DecodedCert* cert);
WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate);
WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz);