Browse Source

Add support for raw-public-key

TakayukiMatsuo 10 months ago
parent
commit
3a5739a8fa

+ 1 - 0
certs/include.am

@@ -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
 

+ 22 - 0
certs/renewcerts.sh

@@ -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 ##################
     ############################################################

BIN
certs/rpk/client-cert-rpk.der


BIN
certs/rpk/client-ecc-cert-rpk.der


+ 9 - 0
certs/rpk/include.am

@@ -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

BIN
certs/rpk/server-cert-rpk.der


BIN
certs/rpk/server-ecc-cert-rpk.der


+ 189 - 0
doc/dox_comments/header_files-ja/ssl.h

@@ -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  この関数はテストのための固定/静的なエフェラルキーを設定します。

+ 205 - 0
doc/dox_comments/header_files/ssl.h

@@ -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

+ 66 - 0
src/internal.c

@@ -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;
@@ -12751,6 +12761,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) {
@@ -13341,6 +13356,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
@@ -13442,6 +13460,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 */
@@ -14262,6 +14311,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;
@@ -24387,6 +24450,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 - 0
src/ssl.c

@@ -7402,6 +7402,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)
@@ -10183,6 +10197,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 - 0
src/tls.c

@@ -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
+ 1013 - 0
tests/api.c


+ 141 - 1
wolfcrypt/src/asn.c

@@ -15054,6 +15054,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.
@@ -15146,6 +15194,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;
 
@@ -20748,6 +20810,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.
  */
@@ -20952,6 +21049,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) {
@@ -22533,7 +22664,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 */
@@ -22778,6 +22913,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
 

+ 2 - 1
wolfssl/error-ssl.h

@@ -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 !!!!! */
 

+ 45 - 1
wolfssl/internal.h

@@ -2796,6 +2796,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
@@ -2841,6 +2845,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 {
@@ -3591,7 +3625,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) */
@@ -4695,6 +4732,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 */

+ 23 - 0
wolfssl/ssl.h

@@ -5131,6 +5131,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);

+ 4 - 0
wolfssl/wolfcrypt/asn.h

@@ -1931,6 +1931,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;
@@ -2112,6 +2115,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);

Some files were not shown because too many files changed in this diff