Merge pull request #5860 from superna9999/4745-psa-jpake-api-fixes

PSA J-PAKE API has missing elements and confusing documentation
diff --git a/3rdparty/everest/CMakeLists.txt b/3rdparty/everest/CMakeLists.txt
index ff9da7a..4ad367e 100644
--- a/3rdparty/everest/CMakeLists.txt
+++ b/3rdparty/everest/CMakeLists.txt
@@ -23,5 +23,5 @@
 
 install(TARGETS everest
   EXPORT MbedTLSTargets
-  DESTINATION ${LIB_INSTALL_DIR}
+  DESTINATION ${CMAKE_INSTALL_LIBDIR}
   PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9006c2d..b97368f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,8 @@
     project("mbed TLS" C)
 endif()
 
+include(GNUInstallDirs)
+
 # Determine if mbed TLS is being built as a subproject using add_subdirectory()
 if(NOT DEFINED MBEDTLS_AS_SUBPROJECT)
   set(MBEDTLS_AS_SUBPROJECT ON)
@@ -252,8 +254,7 @@
 endif(CMAKE_BUILD_TYPE STREQUAL "Coverage")
 
 if(LIB_INSTALL_DIR)
-else()
-    set(LIB_INSTALL_DIR lib)
+    set(CMAKE_INSTALL_LIBDIR "${LIB_INSTALL_DIR}")
 endif()
 
 add_subdirectory(include)
diff --git a/ChangeLog.d/cmake_fix_dll_install.txt b/ChangeLog.d/cmake_fix_dll_install.txt
new file mode 100644
index 0000000..df51c65
--- /dev/null
+++ b/ChangeLog.d/cmake_fix_dll_install.txt
@@ -0,0 +1,3 @@
+Changes
+   * cmake: Fix runtime library install location in mingw
+     This install DLLs in bin directory instead of lib.
diff --git a/ChangeLog.d/cmake_use_GnuInstallDirs.txt b/ChangeLog.d/cmake_use_GnuInstallDirs.txt
new file mode 100644
index 0000000..d848755
--- /dev/null
+++ b/ChangeLog.d/cmake_use_GnuInstallDirs.txt
@@ -0,0 +1,5 @@
+Changes
+   * cmake: Use GnuInstallDirs to customize install directories
+     Replace custom LIB_INSTALL_DIR variable with standard CMAKE_INSTALL_LIBDIR
+     variable. For backward compatibility, set CMAKE_INSTALL_LIBDIR if
+     LIB_INSTALL_DIR is set.
diff --git a/ChangeLog.d/static_link_common_runtime_msvc.txt b/ChangeLog.d/static_link_common_runtime_msvc.txt
new file mode 100644
index 0000000..6104943
--- /dev/null
+++ b/ChangeLog.d/static_link_common_runtime_msvc.txt
@@ -0,0 +1,3 @@
+Changes
+   * Add a CMake option that enables static linking of the runtime library
+     in Microsoft Visual C++ compiler. Contributed by Microplankton.
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index e381c11..144bd89 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -553,7 +553,7 @@
  *             for example, with 96-bit random nonces, you should not encrypt
  *             more than 2**32 messages with the same key.
  *
- *             Note that for both stategies, sizes are measured in blocks and
+ *             Note that for both strategies, sizes are measured in blocks and
  *             that an AES block is 16 bytes.
  *
  * \warning    Upon return, \p stream_block contains sensitive data. Its
diff --git a/include/mbedtls/aria.h b/include/mbedtls/aria.h
index 296f9a8..71540c8 100644
--- a/include/mbedtls/aria.h
+++ b/include/mbedtls/aria.h
@@ -306,7 +306,7 @@
  *             for example, with 96-bit random nonces, you should not encrypt
  *             more than 2**32 messages with the same key.
  *
- *             Note that for both stategies, sizes are measured in blocks and
+ *             Note that for both strategies, sizes are measured in blocks and
  *             that an ARIA block is 16 bytes.
  *
  * \warning    Upon return, \p stream_block contains sensitive data. Its
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index 45d3119..5277f56 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -955,7 +955,7 @@
  *                 generate yourself and that are supposed to be prime, then
  *                 \p rounds should be at least the half of the security
  *                 strength of the cryptographic algorithm. On the other hand,
- *                 if \p X is chosen uniformly or non-adversially (as is the
+ *                 if \p X is chosen uniformly or non-adversarially (as is the
  *                 case when mbedtls_mpi_gen_prime calls this function), then
  *                 \p rounds can be much lower.
  *
diff --git a/include/mbedtls/camellia.h b/include/mbedtls/camellia.h
index 6feeaf0..6b0a871 100644
--- a/include/mbedtls/camellia.h
+++ b/include/mbedtls/camellia.h
@@ -262,7 +262,7 @@
  *             encrypted: for example, with 96-bit random nonces, you should
  *             not encrypt more than 2**32 messages with the same key.
  *
- *             Note that for both stategies, sizes are measured in blocks and
+ *             Note that for both strategies, sizes are measured in blocks and
  *             that a CAMELLIA block is \c 16 Bytes.
  *
  * \warning    Upon return, \p stream_block contains sensitive data. Its
diff --git a/include/mbedtls/chachapoly.h b/include/mbedtls/chachapoly.h
index 3f4318f..2b49402 100644
--- a/include/mbedtls/chachapoly.h
+++ b/include/mbedtls/chachapoly.h
@@ -158,7 +158,7 @@
  * \param ctx       The ChaCha20-Poly1305 context. This must be initialized
  *                  and bound to a key.
  * \param nonce     The nonce/IV to use for the message.
- *                  This must be a redable buffer of length \c 12 Bytes.
+ *                  This must be a readable buffer of length \c 12 Bytes.
  * \param mode      The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
  *                  #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning).
  *
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index 395db14..ac8b7c0 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -262,7 +262,7 @@
 #if !defined(MBEDTLS_ECP_WINDOW_SIZE)
 /*
  * Maximum "window" size used for point multiplication.
- * Default: a point where higher memory usage yields disminishing performance
+ * Default: a point where higher memory usage yields diminishing performance
  *          returns.
  * Minimum value: 2. Maximum value: 7.
  *
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 016b219..9c8ec11 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -25,7 +25,7 @@
  */
 
 /**
- * This is an optional version symbol that enables comatibility handling of
+ * This is an optional version symbol that enables compatibility handling of
  * config files.
  *
  * It is equal to the #MBEDTLS_VERSION_NUMBER of the Mbed TLS version that
@@ -2390,7 +2390,7 @@
  *
  * Requires: MBEDTLS_MD_C
  *
- * Uncomment to enable the HMAC_DRBG random number geerator.
+ * Uncomment to enable the HMAC_DRBG random number generator.
  */
 #define MBEDTLS_HMAC_DRBG_C
 
diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index 836e455..a031fe2 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -140,7 +140,7 @@
 #define MBEDTLS_OID_AT_GIVEN_NAME               MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */
 #define MBEDTLS_OID_AT_INITIALS                 MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */
 #define MBEDTLS_OID_AT_GENERATION_QUALIFIER     MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */
-#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER        MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */
+#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER        MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */
 #define MBEDTLS_OID_AT_DN_QUALIFIER             MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */
 #define MBEDTLS_OID_AT_PSEUDONYM                MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */
 
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index 5225c57..207aed0 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -411,6 +411,38 @@
  */
 int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type );
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/**
+ * \brief           Tell if context can do the operation given by PSA algorithm
+ *
+ * \param ctx       The context to query. It must have been initialized.
+ * \param alg       PSA algorithm to check against, the following are allowed:
+ *                  PSA_ALG_RSA_PKCS1V15_SIGN(hash),
+ *                  PSA_ALG_RSA_PSS(hash),
+ *                  PSA_ALG_RSA_PKCS1V15_CRYPT,
+ *                  PSA_ALG_ECDSA(hash),
+ *                  PSA_ALG_ECDH, where hash is a specific hash.
+ * \param usage  PSA usage flag to check against, must be composed of:
+ *                  PSA_KEY_USAGE_SIGN_HASH
+ *                  PSA_KEY_USAGE_DECRYPT
+ *                  PSA_KEY_USAGE_DERIVE.
+ *                  Context key must match all passed usage flags.
+ *
+ * \warning         Since the set of allowed algorithms and usage flags may be
+ *                  expanded in the future, the return value \c 0 should not
+ *                  be taken in account for non-allowed algorithms and usage
+ *                  flags.
+ *
+ * \return          1 if the context can do operations on the given type.
+ * \return          0 if the context cannot do the operations on the given
+ *                  type, for non-allowed algorithms and usage flags, or
+ *                  for a context that has been initialized but not set up
+ *                  or that has been cleared with mbedtls_pk_free().
+ */
+int mbedtls_pk_can_do_ext( const mbedtls_pk_context *ctx, psa_algorithm_t alg,
+                           psa_key_usage_t usage );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
 /**
  * \brief           Verify signature (including padding if relevant).
  *
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index 5d2fefc..ecd36da 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -122,7 +122,7 @@
  *
  * This macro has an empty expansion. It exists for documentation purposes:
  * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function
- * has been analyzed for return-check usefuless, whereas the lack of
+ * has been analyzed for return-check usefulness, whereas the lack of
  * an annotation indicates that the function has not been analyzed and its
  * return-check usefulness is unknown.
  */
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index 7562d1c..e43ef96 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -634,7 +634,7 @@
  * \note             The output buffer must be as large as the size
  *                   of ctx->N. For example, 128 Bytes if RSA-1024 is used.
  *
- * \param ctx        The initnialized RSA context to use.
+ * \param ctx        The initialized RSA context to use.
  * \param f_rng      The RNG function to use. This is needed for padding
  *                   generation and is mandatory.
  * \param p_rng      The RNG context to be passed to \p f_rng. This may
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 06860e2..0a99693 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -492,6 +492,7 @@
 #define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT      110  /* 0x6E */
 #define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME    112  /* 0x70 */
 #define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115  /* 0x73 */
+#define MBEDTLS_SSL_ALERT_MSG_CERT_REQUIRED        116  /* 0x74 */
 #define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */
 
 #define MBEDTLS_SSL_HS_HELLO_REQUEST            0
@@ -1357,7 +1358,7 @@
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
-    /** Callback to create & write a cookie for ClientHello veirifcation    */
+    /** Callback to create & write a cookie for ClientHello verification    */
     int (*MBEDTLS_PRIVATE(f_cookie_write))( void *, unsigned char **, unsigned char *,
                            const unsigned char *, size_t );
     /** Callback to verify validity of a ClientHello cookie                 */
@@ -2845,7 +2846,7 @@
  *                 successfully cached, return 1 otherwise.
  *
  * \param conf           SSL configuration
- * \param p_cache        parmater (context) for both callbacks
+ * \param p_cache        parameter (context) for both callbacks
  * \param f_get_cache    session get callback
  * \param f_set_cache    session set callback
  */
@@ -2907,7 +2908,7 @@
 /**
  * \brief          Load serialized session data into a session structure.
  *                 On client, this can be used for loading saved sessions
- *                 before resuming them with mbedstls_ssl_set_session().
+ *                 before resuming them with mbedtls_ssl_set_session().
  *                 On server, this can be used for alternative implementations
  *                 of session cache or session tickets.
  *
@@ -4007,7 +4008,7 @@
  *                 \c mbedtls_ssl_get_record_expansion().
  *
  * \note           For DTLS, it is also possible to set a limit for the total
- *                 size of daragrams passed to the transport layer, including
+ *                 size of datagrams passed to the transport layer, including
  *                 record overhead, see \c mbedtls_ssl_set_mtu().
  *
  * \param conf     SSL configuration
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 9ed2bbe..3e331d4 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -114,7 +114,7 @@
 typedef struct mbedtls_x509_san_other_name
 {
     /**
-     * The type_id is an OID as deifned in RFC 5280.
+     * The type_id is an OID as defined in RFC 5280.
      * To check the value of the type id, you should use
      * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
      */
@@ -1084,7 +1084,7 @@
  * \param is_ca     is this a CA certificate
  * \param max_pathlen   maximum length of certificate chains below this
  *                      certificate (only for CA certificates, -1 is
- *                      inlimited)
+ *                      unlimited)
  *
  * \return          0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED
  */
diff --git a/include/psa/crypto_config.h b/include/psa/crypto_config.h
index 46cf126..e437750 100644
--- a/include/psa/crypto_config.h
+++ b/include/psa/crypto_config.h
@@ -60,7 +60,6 @@
 #define PSA_WANT_ALG_CMAC                       1
 #define PSA_WANT_ALG_CFB                        1
 #define PSA_WANT_ALG_CHACHA20_POLY1305          1
-#define PSA_WANT_ALG_CMAC                       1
 #define PSA_WANT_ALG_CTR                        1
 #define PSA_WANT_ALG_DETERMINISTIC_ECDSA        1
 #define PSA_WANT_ALG_ECB_NO_PADDING             1
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 6bb2ad3..886fc68 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -187,6 +187,18 @@
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code")
 endif(CMAKE_COMPILER_IS_CLANG)
 
+if(CMAKE_COMPILER_IS_MSVC)
+    option(MSVC_STATIC_RUNTIME "Build the libraries with /MT compiler flag" OFF)
+    if(MSVC_STATIC_RUNTIME)
+        foreach(flag_var
+            CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+            CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
+            CMAKE_C_FLAGS_CHECK)
+            string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+        endforeach(flag_var)
+    endif()
+endif()
+
 if(WIN32)
     set(libs ${libs} ws2_32)
 endif(WIN32)
@@ -291,7 +303,9 @@
     install(
         TARGETS ${target}
         EXPORT MbedTLSTargets
-        DESTINATION ${LIB_INSTALL_DIR}
+        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
         PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
 endforeach(target)
 
diff --git a/library/pk.c b/library/pk.c
index 42ff432..1eab65a 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -232,6 +232,127 @@
     return( ctx->pk_info->can_do( type ) );
 }
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/*
+ * Tell if a PK can do the operations of the given PSA algorithm
+ */
+int mbedtls_pk_can_do_ext( const mbedtls_pk_context *ctx, psa_algorithm_t alg,
+                           psa_key_usage_t usage )
+{
+    psa_key_usage_t key_usage;
+
+    /* A context with null pk_info is not set up yet and can't do anything.
+     * For backward compatibility, also accept NULL instead of a context
+     * pointer. */
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( 0 );
+
+    /* Filter out non allowed algorithms */
+    if( PSA_ALG_IS_ECDSA( alg ) == 0 &&
+        PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) == 0 &&
+        PSA_ALG_IS_RSA_PSS( alg ) == 0 &&
+        alg != PSA_ALG_RSA_PKCS1V15_CRYPT &&
+        PSA_ALG_IS_ECDH( alg ) == 0 )
+        return( 0 );
+
+    /* Filter out non allowed usage flags */
+    if( usage == 0 ||
+        ( usage & ~( PSA_KEY_USAGE_SIGN_HASH |
+                     PSA_KEY_USAGE_DECRYPT |
+                     PSA_KEY_USAGE_DERIVE ) ) != 0 )
+        return( 0 );
+
+    /* Wildcard hash is not allowed */
+    if( PSA_ALG_IS_SIGN_HASH( alg ) &&
+        PSA_ALG_SIGN_GET_HASH( alg ) == PSA_ALG_ANY_HASH )
+        return( 0 );
+
+    if( mbedtls_pk_get_type( ctx ) != MBEDTLS_PK_OPAQUE )
+    {
+        mbedtls_pk_type_t type;
+
+        if( PSA_ALG_IS_ECDSA( alg ) || PSA_ALG_IS_ECDH( alg ) )
+            type = MBEDTLS_PK_ECKEY;
+        else if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ||
+                 alg == PSA_ALG_RSA_PKCS1V15_CRYPT )
+            type = MBEDTLS_PK_RSA;
+        else if( PSA_ALG_IS_RSA_PSS( alg ) )
+            type = MBEDTLS_PK_RSASSA_PSS;
+        else
+            return( 0 );
+
+        if( ctx->pk_info->can_do( type ) == 0 )
+            return( 0 );
+
+        switch( type )
+        {
+            case MBEDTLS_PK_ECKEY:
+                key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE;
+                break;
+            case MBEDTLS_PK_RSA:
+            case MBEDTLS_PK_RSASSA_PSS:
+                key_usage = PSA_KEY_USAGE_SIGN_HASH |
+                            PSA_KEY_USAGE_SIGN_MESSAGE |
+                            PSA_KEY_USAGE_DECRYPT;
+                break;
+            default:
+                /* Should never happen */
+                return( 0 );
+        }
+
+        return( ( key_usage & usage ) == usage );
+    }
+
+    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t key_alg, key_alg2;
+    psa_status_t status;
+
+    status = psa_get_key_attributes( *key, &attributes );
+    if( status != PSA_SUCCESS )
+        return( 0 );
+
+    key_alg = psa_get_key_algorithm( &attributes );
+    key_alg2 = psa_get_key_enrollment_algorithm( &attributes );
+    key_usage = psa_get_key_usage_flags( &attributes );
+    psa_reset_key_attributes( &attributes );
+
+    if( ( key_usage & usage ) != usage )
+        return( 0 );
+
+    /*
+     * Common case: the key alg or alg2 only allows alg.
+     * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH
+     * directly.
+     * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with
+     * a fixed hash on key_alg/key_alg2.
+     */
+    if( alg == key_alg || alg == key_alg2 )
+            return( 1 );
+
+    /*
+     * If key_alg or key_alg2 is a hash-and-sign with a wildcard for the hash,
+     * and alg is the same hash-and-sign family with any hash,
+     * then alg is compliant with this key alg
+     */
+    if( PSA_ALG_IS_SIGN_HASH( alg ) )
+    {
+
+        if( PSA_ALG_IS_SIGN_HASH( key_alg ) &&
+            PSA_ALG_SIGN_GET_HASH( key_alg ) == PSA_ALG_ANY_HASH &&
+            ( alg & ~PSA_ALG_HASH_MASK ) == ( key_alg & ~PSA_ALG_HASH_MASK ) )
+            return( 1 );
+
+        if( PSA_ALG_IS_SIGN_HASH( key_alg2 ) &&
+            PSA_ALG_SIGN_GET_HASH( key_alg2 ) == PSA_ALG_ANY_HASH &&
+            ( alg & ~PSA_ALG_HASH_MASK ) == ( key_alg2 & ~PSA_ALG_HASH_MASK ) )
+            return( 1 );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
 /*
  * Helper for mbedtls_pk_sign and mbedtls_pk_verify
  */
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 9fcb2b2..9912d6c 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -509,6 +509,12 @@
     uint8_t sni_authmode;               /*!< authmode from SNI callback     */
 #endif
 
+#if defined(MBEDTLS_SSL_SRV_C)
+    /* Flag indicating if a CertificateRequest message has been sent
+     * to the client or not. */
+    uint8_t certificate_request_sent;
+#endif /* MBEDTLS_SSL_SRV_C */
+
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     uint8_t new_session_ticket;         /*!< use NewSessionTicket?    */
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index d092633..1c9e5cd 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -2504,8 +2504,9 @@
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if ( mbedtls_ssl_ciphersuite_uses_ec(
-         mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) )
+    const mbedtls_ssl_ciphersuite_t *suite =
+        mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite );
+    if ( suite != NULL && mbedtls_ssl_ciphersuite_uses_ec( suite) )
     {
         ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
         ext_len += olen;
@@ -2825,7 +2826,14 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) )
+    const mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
+    if( private_key == NULL)
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no server private key" ) );
+        return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
+    }
+
+    if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_ECKEY ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
         return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
@@ -3160,6 +3168,12 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
     if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
     {
+        if( dig_signed == NULL )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        }
+
         size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
         size_t hashlen = 0;
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 305ac00..e9250fc 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1750,6 +1750,15 @@
     if( ret != 0 )
         return( ret );
 
+    ret = mbedtls_ssl_tls13_compute_application_transform( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+        return( ret );
+    }
+
 #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
     mbedtls_ssl_handshake_set_state(
         ssl,
@@ -1825,6 +1834,14 @@
     if( ret != 0 )
         return( ret );
 
+    ret = mbedtls_ssl_tls13_generate_resumption_master_secret( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1,
+                "mbedtls_ssl_tls13_generate_resumption_master_secret ", ret );
+        return ( ret );
+    }
+
     mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_FLUSH_BUFFERS );
     return( 0 );
 }
@@ -1844,11 +1861,6 @@
  */
 static int ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl )
 {
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to application keys for inbound traffic" ) );
-    mbedtls_ssl_set_inbound_transform ( ssl, ssl->transform_application );
-
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to application keys for outbound traffic" ) );
-    mbedtls_ssl_set_outbound_transform( ssl, ssl->transform_application );
 
     mbedtls_ssl_tls13_handshake_wrapup( ssl );
 
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index f5e38ab..239be53 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -367,14 +367,10 @@
 
 /*
  *
- * STATE HANDLING: Incoming Certificate, client-side only currently.
+ * STATE HANDLING: Incoming Certificate.
  *
  */
 
-/*
- * Implementation
- */
-
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
 /*
@@ -439,6 +435,13 @@
         mbedtls_free( ssl->session_negotiate->peer_cert );
     }
 
+    if( certificate_list_len == 0 )
+    {
+        ssl->session_negotiate->peer_cert = NULL;
+        ret = 0;
+        goto exit;
+    }
+
     if( ( ssl->session_negotiate->peer_cert =
           mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ) ) == NULL )
     {
@@ -515,6 +518,7 @@
         p += extensions_len;
     }
 
+exit:
     /* Check that all the message is consumed. */
     if( p != end )
     {
@@ -547,10 +551,58 @@
 static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl )
 {
     int ret = 0;
+    int authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
     mbedtls_x509_crt *ca_chain;
     mbedtls_x509_crl *ca_crl;
     uint32_t verify_result = 0;
 
+    /* If SNI was used, overwrite authentication mode
+     * from the configuration. */
+#if defined(MBEDTLS_SSL_SRV_C)
+    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+        authmode = ssl->conf->authmode;
+#endif
+
+    /*
+     * If the peer hasn't sent a certificate ( i.e. it sent
+     * an empty certificate chain ), this is reflected in the peer CRT
+     * structure being unset.
+     * Check for that and handle it depending on the
+     * authentication mode.
+     */
+    if( ssl->session_negotiate->peer_cert == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer has not sent a certificate" ) );
+
+#if defined(MBEDTLS_SSL_SRV_C)
+        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+        {
+            /* The client was asked for a certificate but didn't send
+             * one. The client should know what's going on, so we
+             * don't send an alert.
+             */
+            ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
+            if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
+                return( 0 );
+            else
+            {
+                MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_NO_CERT,
+                                              MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE  );
+                return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
+            }
+        }
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+        {
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_NO_CERT,
+                                          MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE );
+            return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE );
+        }
+#endif /* MBEDTLS_SSL_CLI_C */
+    }
+
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
     if( ssl->handshake->sni_ca_chain != NULL )
     {
@@ -593,8 +645,20 @@
             ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
     }
 
+    /* mbedtls_x509_crt_verify_with_profile is supposed to report a
+     * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
+     * with details encoded in the verification flags. All other kinds
+     * of error codes, including those from the user provided f_vrfy
+     * functions, are treated as fatal and lead to a failure of
+     * ssl_tls13_parse_certificate even if verification was optional. */
+    if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
+        ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
+          ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE ) )
+    {
+        ret = 0;
+    }
 
-    if( ca_chain == NULL )
+    if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
         ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
@@ -663,7 +727,8 @@
                           &buf, &buf_len ) );
 
     /* Parse the certificate chain sent by the peer. */
-    MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_certificate( ssl, buf, buf + buf_len ) );
+    MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_certificate( ssl, buf,
+                                                       buf + buf_len ) );
     /* Validate the certificate chain and set the verification results. */
     MBEDTLS_SSL_PROC_CHK( ssl_tls13_validate_certificate( ssl ) );
 
@@ -671,12 +736,9 @@
                                         buf, buf_len );
 
 cleanup:
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
-#else
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-    ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
     return( ret );
 }
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
@@ -1120,80 +1182,6 @@
     return( 0 );
 }
 
-#if defined(MBEDTLS_SSL_CLI_C)
-static int ssl_tls13_postprocess_server_finished_message( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_ssl_key_set traffic_keys;
-    mbedtls_ssl_transform *transform_application = NULL;
-
-    ret = mbedtls_ssl_tls13_key_schedule_stage_application( ssl );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1,
-           "mbedtls_ssl_tls13_key_schedule_stage_application", ret );
-        goto cleanup;
-    }
-
-    ret = mbedtls_ssl_tls13_generate_application_keys( ssl, &traffic_keys );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1,
-            "mbedtls_ssl_tls13_generate_application_keys", ret );
-        goto cleanup;
-    }
-
-    transform_application =
-        mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) );
-    if( transform_application == NULL )
-    {
-        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
-        goto cleanup;
-    }
-
-    ret = mbedtls_ssl_tls13_populate_transform(
-                                    transform_application,
-                                    ssl->conf->endpoint,
-                                    ssl->session_negotiate->ciphersuite,
-                                    &traffic_keys,
-                                    ssl );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_populate_transform", ret );
-        goto cleanup;
-    }
-
-    ssl->transform_application = transform_application;
-
-cleanup:
-
-    mbedtls_platform_zeroize( &traffic_keys, sizeof( traffic_keys ) );
-    if( ret != 0 )
-    {
-        mbedtls_free( transform_application );
-        MBEDTLS_SSL_PEND_FATAL_ALERT(
-                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
-                MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
-    }
-    return( ret );
-}
-#endif /* MBEDTLS_SSL_CLI_C */
-
-static int ssl_tls13_postprocess_finished_message( mbedtls_ssl_context *ssl )
-{
-
-#if defined(MBEDTLS_SSL_CLI_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
-    {
-        return( ssl_tls13_postprocess_server_finished_message( ssl ) );
-    }
-#else
-    ((void) ssl);
-#endif /* MBEDTLS_SSL_CLI_C */
-
-    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-}
-
 int mbedtls_ssl_tls13_process_finished_message( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1211,7 +1199,6 @@
     MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_finished_message( ssl, buf, buf + buf_len ) );
     mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_FINISHED,
                                         buf, buf_len );
-    MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_finished_message( ssl ) );
 
 cleanup:
 
@@ -1248,14 +1235,6 @@
     return( 0 );
 }
 
-static int ssl_tls13_finalize_finished_message( mbedtls_ssl_context *ssl )
-{
-    // TODO: Add back resumption keys calculation after MVP.
-    ((void) ssl);
-
-    return( 0 );
-}
-
 static int ssl_tls13_write_finished_message_body( mbedtls_ssl_context *ssl,
                                                   unsigned char *buf,
                                                   unsigned char *end,
@@ -1296,7 +1275,6 @@
     mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_FINISHED,
                                         buf, msg_len );
 
-    MBEDTLS_SSL_PROC_CHK( ssl_tls13_finalize_finished_message( ssl ) );
     MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg(
                               ssl, buf_len, msg_len ) );
 cleanup:
@@ -1310,6 +1288,12 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) );
 
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to application keys for inbound traffic" ) );
+    mbedtls_ssl_set_inbound_transform ( ssl, ssl->transform_application );
+
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to application keys for outbound traffic" ) );
+    mbedtls_ssl_set_outbound_transform( ssl, ssl->transform_application );
+
     /*
      * Free the previous session and switch to the current one.
      */
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
index f3437a3..91cc4d9 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -1473,9 +1473,6 @@
                                    handshake->tls13_master_secrets.app,
                                    transcript, transcript_len,
                                    app_secrets );
-    /* Erase master secrets */
-    mbedtls_platform_zeroize( &ssl->handshake->tls13_master_secrets,
-                              sizeof( ssl->handshake->tls13_master_secrets ) );
     if( ret != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1,
@@ -1598,4 +1595,67 @@
     return( ret );
 }
 
+int mbedtls_ssl_tls13_generate_resumption_master_secret(
+    mbedtls_ssl_context *ssl )
+{
+    /* Erase master secrets */
+    mbedtls_platform_zeroize( &ssl->handshake->tls13_master_secrets,
+                              sizeof( ssl->handshake->tls13_master_secrets ) );
+    return( 0 );
+}
+
+int mbedtls_ssl_tls13_compute_application_transform( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_key_set traffic_keys;
+    mbedtls_ssl_transform *transform_application = NULL;
+
+    ret = mbedtls_ssl_tls13_key_schedule_stage_application( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1,
+           "mbedtls_ssl_tls13_key_schedule_stage_application", ret );
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_generate_application_keys( ssl, &traffic_keys );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1,
+            "mbedtls_ssl_tls13_generate_application_keys", ret );
+        goto cleanup;
+    }
+
+    transform_application =
+        mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) );
+    if( transform_application == NULL )
+    {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_populate_transform(
+                                    transform_application,
+                                    ssl->conf->endpoint,
+                                    ssl->session_negotiate->ciphersuite,
+                                    &traffic_keys,
+                                    ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_populate_transform", ret );
+        goto cleanup;
+    }
+
+    ssl->transform_application = transform_application;
+
+cleanup:
+
+    mbedtls_platform_zeroize( &traffic_keys, sizeof( traffic_keys ) );
+    if( ret != 0 )
+    {
+        mbedtls_free( transform_application );
+    }
+    return( ret );
+}
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/library/ssl_tls13_keys.h b/library/ssl_tls13_keys.h
index 676ebae..693b6c4 100644
--- a/library/ssl_tls13_keys.h
+++ b/library/ssl_tls13_keys.h
@@ -611,6 +611,19 @@
     mbedtls_ssl_context* ssl, mbedtls_ssl_key_set *traffic_keys );
 
 /**
+ * \brief Compute TLS 1.3 resumption master secret.
+ *
+ * \param ssl  The SSL context to operate on. This must be in
+ *             key schedule stage \c Application, see
+ *             mbedtls_ssl_tls13_key_schedule_stage_application().
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+int mbedtls_ssl_tls13_generate_resumption_master_secret(
+    mbedtls_ssl_context *ssl );
+
+/**
  * \brief Calculate the verify_data value for the client or server TLS 1.3
  * Finished message.
  *
@@ -649,6 +662,17 @@
  */
 int mbedtls_ssl_tls13_compute_handshake_transform( mbedtls_ssl_context *ssl );
 
+/**
+ * \brief Compute TLS 1.3 application transform
+ *
+ * \param ssl  The SSL context to operate on. The early secret must have been
+ *             computed.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+int mbedtls_ssl_tls13_compute_application_transform( mbedtls_ssl_context *ssl );
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 2aa62bf..f3843b1 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -1342,6 +1342,8 @@
     if( authmode == MBEDTLS_SSL_VERIFY_NONE )
         return( SSL_CERTIFICATE_REQUEST_SKIP );
 
+    ssl->handshake->certificate_request_sent = 1;
+
     return( SSL_CERTIFICATE_REQUEST_SEND_REQUEST );
 }
 
@@ -1477,6 +1479,78 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 /*
+ * Handler for MBEDTLS_SSL_SERVER_FINISHED
+ */
+static int ssl_tls13_write_server_finished( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_ssl_tls13_write_finished_message( ssl );
+    if( ret != 0 )
+        return( ret );
+
+    ret = mbedtls_ssl_tls13_compute_application_transform( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+        return( ret );
+    }
+
+    if( ssl->handshake->certificate_request_sent )
+    {
+        mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE );
+
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
+        mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake );
+    }
+    else
+        mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CLIENT_FINISHED
+ */
+static int ssl_tls13_process_client_finished( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if( ! ssl->handshake->certificate_request_sent )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "Switch to handshake traffic keys for inbound traffic" ) );
+        mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake );
+    }
+    ret = mbedtls_ssl_tls13_process_finished_message( ssl );
+    if( ret != 0 )
+        return( ret );
+
+    ret = mbedtls_ssl_tls13_generate_resumption_master_secret( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1,
+            "mbedtls_ssl_tls13_generate_resumption_master_secret ", ret );
+    }
+
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP
+ */
+static int ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+
+    mbedtls_ssl_tls13_handshake_wrapup( ssl );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_OVER );
+    return( 0 );
+}
+
+/*
  * TLS 1.3 State Machine -- server side
  */
 int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl )
@@ -1540,6 +1614,39 @@
             break;
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
+        case MBEDTLS_SSL_SERVER_FINISHED:
+            ret = ssl_tls13_write_server_finished( ssl );
+            break;
+
+        case MBEDTLS_SSL_CLIENT_FINISHED:
+            ret = ssl_tls13_process_client_finished( ssl );
+            break;
+
+        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
+            ret = ssl_tls13_handshake_wrapup( ssl );
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE:
+            ret = mbedtls_ssl_tls13_process_certificate( ssl );
+            if( ret == 0 && ssl->session_negotiate->peer_cert != NULL )
+            {
+                mbedtls_ssl_handshake_set_state(
+                    ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY );
+            }
+            else
+                mbedtls_ssl_handshake_set_state(
+                    ssl, MBEDTLS_SSL_CLIENT_FINISHED );
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:
+            ret = mbedtls_ssl_tls13_process_certificate_verify( ssl );
+            if( ret == 0 )
+            {
+                mbedtls_ssl_handshake_set_state(
+                    ssl, MBEDTLS_SSL_CLIENT_FINISHED );
+            }
+            break;
+
         default:
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
             return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 470ae66..21d17f9 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -81,7 +81,7 @@
 if [ -n "${OPENSSL_NEXT:-}" ]; then
     O_NEXT_SRV="$OPENSSL_NEXT s_server -www -cert data_files/server5.crt -key data_files/server5.key"
     O_NEXT_SRV_NO_CERT="$OPENSSL_NEXT s_server -www "
-    O_NEXT_CLI="echo 'GET / HTTP/1.0' | $OPENSSL_NEXT s_client"
+    O_NEXT_CLI="echo 'GET / HTTP/1.0' | $OPENSSL_NEXT s_client -CAfile data_files/test-ca_cat12.crt"
 else
     O_NEXT_SRV=false
     O_NEXT_SRV_NO_CERT=false
@@ -11224,23 +11224,22 @@
             -c "Protocol is TLSv1.3" \
             -c "HTTP/1.0 200 OK"
 
+requires_openssl_tls1_3
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_DEBUG_C
 requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_openssl_tls1_3
 run_test    "TLS 1.3: Server side check - openssl" \
             "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=0" \
-            "$O_NEXT_CLI -msg -debug -tls1_3" \
-            1 \
+            "$O_NEXT_CLI -msg -debug -tls1_3 -no_middlebox" \
+            0 \
             -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_CERTIFICATE" \
             -s "tls13 server state: MBEDTLS_SSL_CERTIFICATE_VERIFY" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_FINISHED" \
-            -s "SSL - The requested feature is not available" \
-            -s "=> parse client hello" \
-            -s "<= parse client hello"
+            -s "tls13 server state: MBEDTLS_SSL_CLIENT_FINISHED" \
+            -s "tls13 server state: MBEDTLS_SSL_HANDSHAKE_WRAPUP"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_DEBUG_C
@@ -11248,8 +11247,8 @@
 requires_openssl_tls1_3
 run_test    "TLS 1.3: Server side check - openssl with client authentication" \
             "$P_SRV debug_level=4 auth_mode=required crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=0" \
-            "$O_NEXT_CLI -msg -debug -cert data_files/server5.crt -key data_files/server5.key -tls1_3" \
-            1 \
+            "$O_NEXT_CLI -msg -debug -cert data_files/server5.crt -key data_files/server5.key -tls1_3 -no_middlebox" \
+            0 \
             -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
@@ -11258,7 +11257,6 @@
             -s "tls13 server state: MBEDTLS_SSL_CERTIFICATE_VERIFY" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_FINISHED" \
             -s "=> write certificate request" \
-            -s "SSL - The requested feature is not available" \
             -s "=> parse client hello" \
             -s "<= parse client hello"
 
@@ -11270,16 +11268,16 @@
 run_test    "TLS 1.3: Server side check - gnutls" \
             "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=0" \
             "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%NO_TICKETS:%DISABLE_TLS13_COMPAT_MODE -V" \
-            1 \
+            0 \
             -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_CERTIFICATE" \
             -s "tls13 server state: MBEDTLS_SSL_CERTIFICATE_VERIFY" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_FINISHED" \
-            -s "SSL - The requested feature is not available" \
-            -s "=> parse client hello" \
-            -s "<= parse client hello"
+            -s "tls13 server state: MBEDTLS_SSL_CLIENT_FINISHED" \
+            -s "tls13 server state: MBEDTLS_SSL_HANDSHAKE_WRAPUP" \
+            -c "HTTP/1.0 200 OK"
 
 requires_gnutls_tls1_3
 requires_gnutls_next_no_ticket
@@ -11289,7 +11287,7 @@
 run_test    "TLS 1.3: Server side check - gnutls with client authentication" \
             "$P_SRV debug_level=4 auth_mode=required crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=0" \
             "$G_NEXT_CLI localhost -d 4 --x509certfile data_files/server5.crt --x509keyfile data_files/server5.key --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%NO_TICKETS:%DISABLE_TLS13_COMPAT_MODE -V" \
-            1 \
+            0 \
             -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
@@ -11298,7 +11296,6 @@
             -s "tls13 server state: MBEDTLS_SSL_CERTIFICATE_VERIFY" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_FINISHED" \
             -s "=> write certificate request" \
-            -s "SSL - The requested feature is not available" \
             -s "=> parse client hello" \
             -s "<= parse client hello"
 
@@ -11309,16 +11306,17 @@
 run_test    "TLS 1.3: Server side check - mbedtls" \
             "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=0" \
             "$P_CLI debug_level=4 force_version=tls13" \
-            1 \
+            0 \
             -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
+            -s "tls13 server state: MBEDTLS_SSL_CERTIFICATE_REQUEST" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_CERTIFICATE" \
-            -s "=> write certificate request" \
-            -c "client state: MBEDTLS_SSL_CERTIFICATE_REQUEST" \
-            -s "SSL - The requested feature is not available" \
-            -s "=> parse client hello" \
-            -s "<= parse client hello"
+            -s "tls13 server state: MBEDTLS_SSL_CERTIFICATE_VERIFY" \
+            -s "tls13 server state: MBEDTLS_SSL_SERVER_FINISHED" \
+            -s "tls13 server state: MBEDTLS_SSL_CLIENT_FINISHED" \
+            -s "tls13 server state: MBEDTLS_SSL_HANDSHAKE_WRAPUP" \
+            -c "HTTP/1.0 200 OK"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_DEBUG_C
@@ -11327,19 +11325,50 @@
 run_test    "TLS 1.3: Server side check - mbedtls with client authentication" \
             "$P_SRV debug_level=4 auth_mode=required crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=0" \
             "$P_CLI debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13" \
+            0 \
+            -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
+            -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
+            -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
+            -s "tls13 server state: MBEDTLS_SSL_SERVER_CERTIFICATE" \
+            -s "=> write certificate request" \
+            -c "client state: MBEDTLS_SSL_CERTIFICATE_REQUEST" \
+            -s "=> parse client hello" \
+            -s "<= parse client hello"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+run_test    "TLS 1.3: Server side check - mbedtls with client empty certificate" \
+            "$P_SRV debug_level=4 auth_mode=required crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=0" \
+            "$P_CLI debug_level=4 crt_file=none key_file=none force_version=tls13" \
             1 \
             -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
             -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
-            -s "tls13 server state: MBEDTLS_SSL_CERTIFICATE_REQUEST" \
             -s "tls13 server state: MBEDTLS_SSL_SERVER_CERTIFICATE" \
-            -s "tls13 server state: MBEDTLS_SSL_CERTIFICATE_VERIFY" \
-            -s "tls13 server state: MBEDTLS_SSL_SERVER_FINISHED" \
+            -s "=> write certificate request" \
+            -s "SSL - No client certification received from the client, but required by the authentication mode" \
             -c "client state: MBEDTLS_SSL_CERTIFICATE_REQUEST" \
-            -s "SSL - The requested feature is not available" \
             -s "=> parse client hello" \
             -s "<= parse client hello"
 
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+run_test    "TLS 1.3: Server side check - mbedtls with optional client authentication" \
+            "$P_SRV debug_level=4 auth_mode=optional crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=0" \
+            "$P_CLI debug_level=4 force_version=tls13 crt_file=none key_file=none" \
+            0 \
+            -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
+            -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
+            -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
+            -s "tls13 server state: MBEDTLS_SSL_SERVER_CERTIFICATE" \
+            -s "=> write certificate request" \
+            -c "client state: MBEDTLS_SSL_CERTIFICATE_REQUEST" \
+            -s "=> parse client hello" \
+            -s "<= parse client hello"
 
 requires_config_enabled MBEDTLS_DEBUG_C
 requires_config_enabled MBEDTLS_SSL_CLI_C
@@ -11348,14 +11377,13 @@
 run_test "TLS 1.3: server: HRR check - mbedtls" \
          "$P_SRV debug_level=4 force_version=tls13 curves=secp384r1" \
          "$P_CLI debug_level=4 force_version=tls13 curves=secp256r1,secp384r1" \
-         1 \
+         0 \
         -s "tls13 server state: MBEDTLS_SSL_CLIENT_HELLO" \
         -s "tls13 server state: MBEDTLS_SSL_SERVER_HELLO" \
         -s "tls13 server state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
         -s "tls13 server state: MBEDTLS_SSL_HELLO_RETRY_REQUEST" \
         -c "client state: MBEDTLS_SSL_ENCRYPTED_EXTENSIONS" \
         -s "selected_group: secp384r1" \
-        -s "SSL - The requested feature is not available" \
         -s "=> write hello retry request" \
         -s "<= write hello retry request"
 
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index f17711d..6fd595c 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -49,6 +49,266 @@
 depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
 pk_psa_utils:1
 
+PK can do ext: ECDSA(ANY)/NONE, invalid check STREAM_CIPHER
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:256:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: ECDSA(ANY)/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:256:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: ECDSA(ANY)/NONE, invalid check RSA_PKCS1V15_CRYPT
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:256:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: ECDSA(ANY)/NONE, invalid check RSA_PSS(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:256:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: ECDSA(ANY)/NONE, invalid check ECDH
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:256:PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: ECDSA(ANY)/NONE, check ECDSA(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: ECDSA(SHA256)/NONE, check ECDSA(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_NONE:256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: NONE/ECDSA(ANY_HASH), check ECDSA(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: NONE/ECDSA(SHA256), check ECDSA(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: ECDSA(SHA256)/NONE, invalid check ECDSA(ANY)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_NONE:256:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: ECDSA(SHA1)/NONE, invalid check ECDSA(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA(PSA_ALG_SHA_1):PSA_ALG_NONE:256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: ECDH/NONE, invalid check STREAM_CIPHER
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_NONE:256:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_DERIVE:0
+
+PK can do ext: ECDH/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_NONE:256:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:0
+
+PK can do ext: ECDH/NONE, invalid check RSA_PKCS1V15_CRYPT
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_NONE:256:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DERIVE:0
+
+PK can do ext: ECDH/NONE, invalid check RSA_PSS(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_NONE:256:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:0
+
+PK can do ext: ECDH/NONE, invalid check ECDSA(SHA256)
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_NONE:256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:0
+
+PK can do ext: ECDH/NONE, check ECDH
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_NONE:256:PSA_ALG_ECDH:PSA_KEY_USAGE_DERIVE:1
+
+PK can do ext: ECDH/ECDSA(ANY), check ECDH+SIGN
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: ECDH/ECDSA(ANY), check ECDH+DERIVE
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDH:PSA_KEY_USAGE_DERIVE:1
+
+PK can do ext: ECDH/ECDSA(ANY), check ECDH+DERIVE|SIGN
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDH:PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: ECDH/ECDSA(ANY), check ECDSA(SHA256)+DERIVE|SIGN
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: ECDH/ECDSA(ANY), check ECDSA(SHA256)+SIGN
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: ECDH/ECDSA(ANY), check ECDSA(SHA256)+DERIVE
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:1
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check not allowed COPY usage
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_COPY:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check STREAM_CIPHER
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check ECDSA(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check ECDH
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check RSA_PKCS1V15_CRYPT
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check non-present usage
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(SHA256)/NONE, check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: NONE, RSA_PKCS1V15_SIGN(ANY), check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: NONE, RSA_PKCS1V15_SIGN(SHA256), check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: RSA_PKCS1V15_SIGN(SHA256)/NONE, invalid check RSA_PKCS1V15_SIGN(ANY)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(SHA1)/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PSS(ANY)/NONE, invalid check STREAM_CIPHER
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PSS(ANY)/NONE, invalid check ECDSA(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PSS(ANY)/NONE, invalid check RSA_PKCS1V15_CRYPT
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PSS(ANY)/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PSS(ANY)/NONE, check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: RSA_PSS(SHA256)/NONE, check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: NONE, RSA_PSS(ANY), check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: NONE, RSA_PSS(SHA256), check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: RSA_PSS(SHA256)/NONE, invalid check RSA_PSS(ANY)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PSS(SHA1)/NONE, invalid check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_1):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PKCS1V15_SIGN_RAW/NONE, check RSA_PKCS1V15_SIGN_RAW
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: RSA_PKCS1V15_SIGN_RAW/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
+
+PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check STREAM_CIPHER
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
+
+PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check ECDSA(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
+
+PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check ECDH
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_ECDH:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
+
+PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
+
+PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
+
+PK can do ext: RSA_PKCS1V15_CRYPT/NONE, check RSA_PKCS1V15_CRYPT
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
+
+PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check RSA_PKCS1V15_CRYPT
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
+
+PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_DECRYPT:1
+
+PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check non allowed ENCRYPT usage
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT:0
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/RSA_PSS(ANY), check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: RSA_PKCS1V15_SIGN(ANY)/RSA_PSS(ANY), check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: MBEDTLS_PK_ECKEY, check ECDSA(SHA256)
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:0:MBEDTLS_PK_ECKEY:0:0:0:MBEDTLS_ECP_DP_SECP256R1:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: MBEDTLS_PK_ECKEY, check ECDH
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_can_do_ext:0:MBEDTLS_PK_ECKEY:0:0:0:MBEDTLS_ECP_DP_SECP256R1:PSA_ALG_ECDH:PSA_KEY_USAGE_DERIVE:1
+
+PK can do ext: MBEDTLS_PK_RSA, check RSA_PKCS1V15_SIGN(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
+PK can do ext: MBEDTLS_PK_RSA, check PSA_ALG_RSA_PKCS1V15_CRYPT
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
+
+PK can do ext: MBEDTLS_PK_RSA, check invalid PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_ENCRYPT:0
+
+PK can do ext: MBEDTLS_PK_RSA, check RSA_PSS(SHA256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
+
 RSA verify test vector #1 (good)
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_PKCS1_V15
 pk_rsa_verify_test_vec:"206ef4bf396c6087f8229ef196fd35f37ccb8de5efcdb238f20d556668f114257a11fbe038464a67830378e62ae9791453953dac1dbd7921837ba98e84e856eb80ed9487e656d0b20c28c8ba5e35db1abbed83ed1c7720a97701f709e3547a4bfcabca9c89c57ad15c3996577a0ae36d7c7b699035242f37954646c1cd5c08ac":MBEDTLS_MD_SHA1:1024:16:"e28a13548525e5f36dccb24ecb7cc332cc689dfd64012604c9c7816d72a16c3f5fcdc0e86e7c03280b1c69b586ce0cd8aec722cc73a5d3b730310bf7dfebdc77ce5d94bbc369dc18a2f7b07bd505ab0f82224aef09fdc1e5063234255e0b3c40a52e9e8ae60898eb88a766bdd788fe9493d8fd86bcdd2884d5c06216c65469e5":16:"3":"5abc01f5de25b70867ff0c24e222c61f53c88daf42586fddcd56f3c4588f074be3c328056c063388688b6385a8167957c6e5355a510e005b8a851d69c96b36ec6036644078210e5d7d326f96365ee0648882921492bc7b753eb9c26cdbab37555f210df2ca6fec1b25b463d38b81c0dcea202022b04af5da58aa03d77be949b7":0
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 7587d6c..34ebdcc 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -247,6 +247,54 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_USE_PSA_CRYPTO */
+void pk_can_do_ext( int opaque_key, int key_type, int key_usage, int key_alg,
+                    int key_alg2, int parameter, int alg_check, int usage_check,
+                    int result )
+{
+    mbedtls_pk_context pk;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    mbedtls_pk_init( &pk );
+
+    if( opaque_key == 1 )
+    {
+        psa_set_key_usage_flags( &attributes, key_usage );
+        psa_set_key_algorithm( &attributes, key_alg );
+        if( key_alg2 != 0 )
+            psa_set_key_enrollment_algorithm( &attributes, key_alg2 );
+        psa_set_key_type( &attributes, key_type );
+        psa_set_key_bits( &attributes, parameter );
+
+        PSA_ASSERT( psa_generate_key( &attributes, &key ) );
+
+        if( mbedtls_svc_key_id_is_null( key ) )
+            goto exit;
+
+        TEST_EQUAL( mbedtls_pk_setup_opaque( &pk, key ), 0 );
+
+        TEST_EQUAL( mbedtls_pk_get_type( &pk ), MBEDTLS_PK_OPAQUE );
+    }
+    else
+    {
+        TEST_EQUAL( mbedtls_pk_setup( &pk,
+                            mbedtls_pk_info_from_type( key_type ) ), 0 );
+        TEST_EQUAL( pk_genkey( &pk, parameter ), 0 );
+        TEST_EQUAL( mbedtls_pk_get_type( &pk ), key_type );
+    }
+
+    TEST_EQUAL( mbedtls_pk_can_do_ext( &pk, alg_check, usage_check ), result );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    PSA_ASSERT( psa_destroy_key( key ) );
+    mbedtls_pk_free( &pk );
+    USE_PSA_DONE( );
+}
+/* END_CASE */
 
 /* BEGIN_CASE */
 void valid_parameters( )