Merge pull request #986 from Mbed-TLS/merge-back-3.3.0-3

Merge back 3.3.0 3
diff --git a/.uncrustify.cfg b/.uncrustify.cfg
new file mode 100644
index 0000000..ac9173e
--- /dev/null
+++ b/.uncrustify.cfg
@@ -0,0 +1,254 @@
+# Configuration options for Uncrustify specifying the Mbed TLS code style.
+#
+# Note: The code style represented by this file has not yet been introduced
+# to Mbed TLS.
+#
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# Line length options
+
+# Wrap lines at 100 characters
+code_width = 100
+
+# Allow splitting long for statements between the condition statements
+ls_for_split_full = true
+
+# Allow splitting function calls between arguments
+ls_func_split_full = true
+
+input_tab_size = 4
+
+# Spaces-only indentation
+indent_with_tabs = 0
+
+indent_columns = 4
+
+# Indent 'case' 1 level from 'switch'
+indent_switch_case = indent_columns
+
+# Line-up strings broken by '\'
+indent_align_string = true
+
+# Braces on the same line (Egyptian-style braces)
+nl_enum_brace = remove
+nl_union_brace = remove
+nl_struct_brace = remove
+nl_do_brace = remove
+nl_if_brace = remove
+nl_for_brace = remove
+nl_else_brace = remove
+nl_while_brace = remove
+nl_switch_brace = remove
+
+# Braces on same line as keywords that follow them - 'else' and the 'while' in 'do {} while ()';
+nl_brace_else = remove
+nl_brace_while = remove
+# Space before else on the same line
+sp_brace_else = add
+# If else is on the same line as '{', force exactly 1 space between them
+sp_else_brace = force
+
+# Functions are the exception and have braces on the next line
+nl_fcall_brace = add
+nl_fdef_brace = add
+
+# Force exactly one space between ')' and '{' in statements
+sp_sparen_brace = force
+
+# At least 1 space around assignment
+sp_assign = add
+
+# Remove spaces around the preprocessor '##' token-concatenate
+sp_pp_concat = ignore
+
+# At least 1 space around '||' and '&&'
+sp_bool = add
+
+# But no space after the '!' operator
+sp_not = remove
+
+# No space after the bitwise-not '~' operator
+sp_inv = remove
+
+# No space after the addressof '&' operator
+sp_addr = remove
+
+# No space around the member '.' and '->' operators
+sp_member = remove
+
+# No space after the dereference '*' operator
+sp_deref = remove
+
+# No space after a unary negation '-'
+sp_sign = remove
+
+# No space between the '++'/'--' operator and its operand
+sp_incdec = remove
+
+# At least 1 space around comparison operators
+sp_compare = add
+
+# Remove spaces inside all kinds of parentheses:
+
+# Remove spaces inside parentheses
+sp_inside_paren = remove
+
+# No spaces inside statement parentheses
+sp_inside_sparen = remove
+
+# No spaces inside cast parentheses '( char )x' -> '(char)x'
+sp_inside_paren_cast = remove
+
+# No spaces inside function parentheses
+sp_inside_fparen = remove
+# (The case where the function has no parameters/arguments)
+sp_inside_fparens = remove
+
+# No spaces inside the first parentheses in a function type
+sp_inside_tparen = remove
+
+# (Uncrustify >= 0.74.0) No spaces inside parens in for statements
+sp_inside_for = remove
+
+# Remove spaces between nested parentheses '( (' -> '(('
+sp_paren_paren = remove
+# (Uncrustify >= 0.74.0)
+sp_sparen_paren = remove
+
+# Remove spaces between ')' and adjacent '('
+sp_cparen_oparen = remove
+
+# (Uncrustify >= 0.73.0) space between 'do' and '{'
+sp_do_brace_open = force
+
+# (Uncrustify >= 0.73.0) space between '}' and 'while'
+sp_brace_close_while = force
+
+# At least 1 space before a '*' pointer star
+sp_before_ptr_star = add
+
+# Remove spaces between pointer stars
+sp_between_ptr_star = remove
+
+# No space after a pointer star
+sp_after_ptr_star = remove
+
+# But allow a space in the case of e.g. char * const x;
+sp_after_ptr_star_qualifier = ignore
+
+# Remove space after star in a function return type
+sp_after_ptr_star_func = remove
+
+# At least 1 space after a type in variable definition etc
+sp_after_type = add
+
+# Force exactly 1 space between a statement keyword (e.g. 'if') and an opening parenthesis
+sp_before_sparen = force
+
+# Remove a space before a ';'
+sp_before_semi = remove
+# (Uncrustify >= 0.73.0) Remove space before a semi in a non-empty for
+sp_before_semi_for = remove
+# (Uncrustify >= 0.73.0) Remove space in empty first statement of a for
+sp_before_semi_for_empty = remove
+# (Uncrustify >= 0.74.0) Remove space in empty middle statement of a for
+sp_between_semi_for_empty = remove
+
+# Add a space after a ';' (unless a comment follows)
+sp_after_semi = add
+# (Uncrustify >= 0.73.0) Add a space after a semi in non-empty for statements
+sp_after_semi_for = add
+# (Uncrustify >= 0.73.0) No space after final semi in empty for statements
+sp_after_semi_for_empty = remove
+
+# Remove spaces on the inside of square brackets '[]'
+sp_inside_square = remove
+
+# Must have at least 1 space after a comma
+sp_after_comma = add
+
+# Must not have a space before a comma
+sp_before_comma = remove
+
+# No space before the ':' in a case statement
+sp_before_case_colon = remove
+
+# No space after a cast - '(char) x' -> '(char)x'
+sp_after_cast = remove
+
+# No space between 'sizeof' and '('
+sp_sizeof_paren = remove
+
+# At least 1 space inside '{ }'
+sp_inside_braces = add
+
+# At least 1 space inside '{ }' in an enum
+sp_inside_braces_enum = add
+
+# At least 1 space inside '{ }' in a struct
+sp_inside_braces_struct = add
+
+# At least 1 space between a function return type and the function name
+sp_type_func = add
+
+# No space between a function name and its arguments/parameters
+sp_func_proto_paren = remove
+sp_func_def_paren = remove
+sp_func_call_paren = remove
+
+# No space between '__attribute__' and '('
+sp_attribute_paren = remove
+
+# No space between 'defined' and '(' in preprocessor conditions
+sp_defined_paren = remove
+
+# At least 1 space between a macro's name and its definition
+sp_macro = add
+sp_macro_func = add
+
+# Force exactly 1 space between a '}' and the name of a typedef if on the same line
+sp_brace_typedef = force
+
+# At least 1 space before a '\' line continuation
+sp_before_nl_cont = add
+
+# At least 1 space around '?' and ':' in ternary statements
+sp_cond_colon = add
+sp_cond_question = add
+
+# Space between #else/#endif and comment afterwards
+sp_endif_cmt = add
+
+# Remove newlines at the start of a file
+nl_start_of_file = remove
+
+# At least 1 newline at the end of a file
+nl_end_of_file = add
+nl_end_of_file_min = 1
+
+# Add braces in single-line statements
+mod_full_brace_do = add
+mod_full_brace_for = add
+mod_full_brace_if = add
+mod_full_brace_while = add
+
+# Remove parentheses from return statements
+mod_paren_on_return = remove
+
+# Disable removal of leading spaces in a multi-line comment if the first and
+# last lines are the same length
+cmt_multi_check_last = false
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 337e4db..64c1058 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -355,7 +355,7 @@
     install(
         FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfig.cmake"
               "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfigVersion.cmake"
-        DESTINATION "cmake")
+        DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/MbedTLS")
 
     export(
         EXPORT MbedTLSTargets
@@ -365,7 +365,7 @@
     install(
         EXPORT MbedTLSTargets
         NAMESPACE MbedTLS::
-        DESTINATION "cmake"
+        DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/MbedTLS"
         FILE "MbedTLSTargets.cmake")
 
     if(CMAKE_VERSION VERSION_GREATER 3.15 OR CMAKE_VERSION VERSION_EQUAL 3.15)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d19fe57..fc79e49 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -32,13 +32,9 @@
 
 The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches, as described in [BRANCHES.md](BRANCHES.md).
 
-To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change. If there is an API change, the contribution, if accepted, will be merged only when there will be a major release.
+To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change. If there is an API change, the contribution, if accepted, will be merged only when there is a major release.
 
-Where changes to an existing interface are necessary, functions in the public interface which need to be changed, are marked as 'deprecated'. This is done with the preprocessor symbols `MBEDTLS_DEPRECATED_WARNING` and `MBEDTLS_DEPRECATED_REMOVED`. Then, a new function with a new name but similar if not identical behaviour to the original function containing the necessary changes should be created alongside the existing deprecated function.
-
-When a build is made with the deprecation preprocessor symbols defined, a compiler warning will be generated to warn a user that the function will be removed at some point in the future, notifying users that they should change from the older deprecated function to the newer function at their own convenience.
-
-Therefore, no changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. As described above, if a function needs to be changed, a new function needs to be created alongside it, with a new name, and whatever change is necessary, such as a new parameter or the addition of a return value.
+No changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. Where changes to an existing interface are necessary, functions in the public interface which need to be changed are marked as 'deprecated'. If there is a strong reason to replace an existing function with one that has a slightly different interface (different prototype, or different documented behavior), create a new function with a new name with the desired interface. Keep the old function, but mark it as deprecated.
 
 Periodically, the library will remove deprecated functions from the library which will be a breaking change in the API, but such changes will be made only in a planned, structured way that gives sufficient notice to users of the library.
 
diff --git a/ChangeLog b/ChangeLog
index 5de8641..1404d36 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -207,7 +207,7 @@
 = Mbed TLS 3.2.1 branch released 2022-07-12
 
 Bugfix
-   *  Re-add missing generated file library/ssl_debug_helpers_generated.c
+   *  Re-add missing generated file library/psa_crypto_driver_wrappers.c
 
 = Mbed TLS 3.2.0 branch released 2022-07-11
 
diff --git a/ChangeLog.d/alignment-perf.txt b/ChangeLog.d/alignment-perf.txt
new file mode 100644
index 0000000..7a8e6fb
--- /dev/null
+++ b/ChangeLog.d/alignment-perf.txt
@@ -0,0 +1,8 @@
+Features
+   * General performance improvements by accessing multiple bytes at a time.
+     Fixes #1666.
+   * Improvements to use of unaligned and byte-swapped memory, reducing code
+     size and improving performance (depending on compiler and target
+     architecture).
+Changes
+   * Mixed-endian systems are explicitly not supported any more.
diff --git a/ChangeLog.d/cmake-install.txt b/ChangeLog.d/cmake-install.txt
new file mode 100644
index 0000000..d8eb72e
--- /dev/null
+++ b/ChangeLog.d/cmake-install.txt
@@ -0,0 +1,3 @@
+Changes
+  * Install the .cmake files into CMAKE_INSTALL_LIBDIR/cmake/MbedTLS,
+    typically /usr/lib/cmake/MbedTLS.
diff --git a/README.md b/README.md
index 1a4edb0..8a23bd2 100644
--- a/README.md
+++ b/README.md
@@ -261,6 +261,7 @@
 - Signed integers must be represented using two's complement.
 - `int` and `size_t` must be at least 32 bits wide.
 - The types `uint8_t`, `uint16_t`, `uint32_t` and their signed equivalents must be available.
+- Mixed-endian platforms are not supported.
 
 PSA cryptography API
 --------------------
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 04e43e3..b791344 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -23,6 +23,7 @@
 #ifndef MBEDTLS_CHECK_CONFIG_H
 #define MBEDTLS_CHECK_CONFIG_H
 
+/* *INDENT-OFF* */
 /*
  * We assume CHAR_BIT is 8 in many places. In practice, this is true on our
  * target platforms, so not an issue, but let's just be extra sure.
@@ -329,7 +330,7 @@
 
 /* Use of EC J-PAKE in TLS requires SHA-256.
  * This will be taken from MD if it is present, or from PSA if MD is absent.
- * Note: ECJPAKE_C depends on MD_C || PSA_CRYPTO_C. */
+ * Note: MBEDTLS_ECJPAKE_C depends on MBEDTLS_MD_C || MBEDTLS_PSA_CRYPTO_C. */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) &&                    \
     !( defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C) ) &&          \
     !( !defined(MBEDTLS_MD_C) && defined(PSA_WANT_ALG_SHA_256) )
@@ -1099,4 +1100,5 @@
  */
 typedef int mbedtls_iso_c_forbids_empty_translation_units;
 
+/* *INDENT-ON* */
 #endif /* MBEDTLS_CHECK_CONFIG_H */
diff --git a/include/mbedtls/legacy_or_psa.h b/include/mbedtls/legacy_or_psa.h
index f872dda..35798a5 100644
--- a/include/mbedtls/legacy_or_psa.h
+++ b/include/mbedtls/legacy_or_psa.h
@@ -64,7 +64,7 @@
  * The naming scheme for these macros is:
  *      MBEDTLS_HAS_feature_VIA_legacy_OR_PSA(_condition)
  * where:
- * - feature is expressed the same way as in PSA_WANT macros, for example:
+ * - feature is expressed the same way as in PSA_WANT_xxx macros, for example:
  *   KEY_TYPE_AES, ALG_SHA_256, ECC_SECP_R1_256;
  * - legacy is either LOWLEVEL or the name of the layer: MD, CIPHER;
  * - condition is omitted if it's based on availability, else it's
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 3f48377..7751560 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -3899,6 +3899,23 @@
 int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
                                          const unsigned char *pw,
                                          size_t pw_len );
+
+/**
+ * \brief          Set the EC J-PAKE opaque password for current handshake.
+ *
+ * \note           The key must remain valid until the handshake is over.
+ *
+ * \note           The SSL context needs to be already set up. The right place
+ *                 to call this function is between \c mbedtls_ssl_setup() or
+ *                 \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake().
+ *
+ * \param ssl      SSL context
+ * \param pwd      EC J-PAKE opaque password
+ *
+ * \return         0 on success, or a negative error code.
+ */
+int mbedtls_ssl_set_hs_ecjpake_password_opaque( mbedtls_ssl_context *ssl,
+                                                mbedtls_svc_key_id_t pwd );
 #endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_ALPN)
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index c9c1ec0..cf8a7b2 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -1760,7 +1760,7 @@
 #define PSA_ALG_HKDF_BASE                       ((psa_algorithm_t)0x08000100)
 /** Macro to build an HKDF algorithm.
  *
- * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256.
+ * For example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)` is HKDF using HMAC-SHA-256.
  *
  * This key derivation algorithm uses the following inputs:
  * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step.
@@ -1805,7 +1805,7 @@
 #define PSA_ALG_HKDF_EXTRACT_BASE                       ((psa_algorithm_t)0x08000400)
 /** Macro to build an HKDF-Extract algorithm.
  *
- * For example, `PSA_ALG_HKDF_EXTRACT(PSA_ALG_SHA256)` is
+ * For example, `PSA_ALG_HKDF_EXTRACT(PSA_ALG_SHA_256)` is
  * HKDF-Extract using HMAC-SHA-256.
  *
  * This key derivation algorithm uses the following inputs:
@@ -1854,7 +1854,7 @@
 #define PSA_ALG_HKDF_EXPAND_BASE                       ((psa_algorithm_t)0x08000500)
 /** Macro to build an HKDF-Expand algorithm.
  *
- * For example, `PSA_ALG_HKDF_EXPAND(PSA_ALG_SHA256)` is
+ * For example, `PSA_ALG_HKDF_EXPAND(PSA_ALG_SHA_256)` is
  * HKDF-Expand using HMAC-SHA-256.
  *
  * This key derivation algorithm uses the following inputs:
@@ -1925,7 +1925,7 @@
  * concatenation of ServerHello.Random + ClientHello.Random,
  * and the label is "key expansion".
  *
- * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the
+ * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)` represents the
  * TLS 1.2 PRF using HMAC-SHA-256.
  *
  * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
@@ -1995,7 +1995,7 @@
  *   PSA_ALG_RSA_PKCS1V15_CRYPT, passed to the key derivation operation
  *   with `psa_key_derivation_input_bytes()`.
  *
- * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the
+ * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)` represents the
  * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256.
  *
  * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
@@ -2050,7 +2050,7 @@
  * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2).
  * This macro specifies the PBKDF2 algorithm constructed using a PRF based on
  * HMAC with the specified hash.
- * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA256)` specifies PBKDF2
+ * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)` specifies PBKDF2
  * using the PRF HMAC-SHA-256.
  *
  * This key derivation algorithm uses the following inputs, which must be
diff --git a/library/aes.c b/library/aes.c
index 319d9bb..56dc5cf 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -978,7 +978,6 @@
                     const unsigned char *input,
                     unsigned char *output )
 {
-    int i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[16];
 
@@ -1009,8 +1008,7 @@
             if( ret != 0 )
                 goto exit;
 
-            for( i = 0; i < 16; i++ )
-                output[i] = (unsigned char)( output[i] ^ iv[i] );
+            mbedtls_xor( output, output, iv, 16 );
 
             memcpy( iv, temp, 16 );
 
@@ -1023,8 +1021,7 @@
     {
         while( length > 0 )
         {
-            for( i = 0; i < 16; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+            mbedtls_xor( output, input, iv, 16 );
 
             ret = mbedtls_aes_crypt_ecb( ctx, mode, output, output );
             if( ret != 0 )
@@ -1106,8 +1103,6 @@
 
     while( blocks-- )
     {
-        size_t i;
-
         if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
         {
             /* We are on the last block in a decrypt operation that has
@@ -1119,15 +1114,13 @@
             mbedtls_gf128mul_x_ble( tweak, tweak );
         }
 
-        for( i = 0; i < 16; i++ )
-            tmp[i] = input[i] ^ tweak[i];
+        mbedtls_xor( tmp, input, tweak, 16 );
 
         ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
         if( ret != 0 )
             return( ret );
 
-        for( i = 0; i < 16; i++ )
-            output[i] = tmp[i] ^ tweak[i];
+        mbedtls_xor( output, tmp, tweak, 16 );
 
         /* Update the tweak for the next block. */
         mbedtls_gf128mul_x_ble( tweak, tweak );
@@ -1148,19 +1141,18 @@
         unsigned char *prev_output = output - 16;
 
         /* Copy ciphertext bytes from the previous block to our output for each
-         * byte of ciphertext we won't steal. At the same time, copy the
-         * remainder of the input for this final round (since the loop bounds
-         * are the same). */
+         * byte of ciphertext we won't steal. */
         for( i = 0; i < leftover; i++ )
         {
             output[i] = prev_output[i];
-            tmp[i] = input[i] ^ t[i];
         }
 
+        /* Copy the remainder of the input for this final round. */
+        mbedtls_xor( tmp, input, t, leftover );
+
         /* Copy ciphertext bytes from the previous block for input in this
          * round. */
-        for( ; i < 16; i++ )
-            tmp[i] = prev_output[i] ^ t[i];
+        mbedtls_xor( tmp + i, prev_output + i, t + i, 16 - i );
 
         ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
         if( ret != 0 )
@@ -1168,8 +1160,7 @@
 
         /* Write the result back to the previous block, overriding the previous
          * output we copied. */
-        for( i = 0; i < 16; i++ )
-            prev_output[i] = tmp[i] ^ t[i];
+        mbedtls_xor( prev_output, tmp, t, 16 );
     }
 
     return( 0 );
diff --git a/library/alignment.h b/library/alignment.h
new file mode 100644
index 0000000..3c5fa23
--- /dev/null
+++ b/library/alignment.h
@@ -0,0 +1,494 @@
+/**
+ * \file alignment.h
+ *
+ * \brief Utility code for dealing with unaligned memory accesses
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef MBEDTLS_LIBRARY_ALIGNMENT_H
+#define MBEDTLS_LIBRARY_ALIGNMENT_H
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "mbedtls/build_info.h"
+
+/**
+ * Read the unsigned 16 bits integer from the given address, which need not
+ * be aligned.
+ *
+ * \param   p pointer to 2 bytes of data
+ * \return  Data at the given address
+ */
+inline uint16_t mbedtls_get_unaligned_uint16( const void *p )
+{
+    uint16_t r;
+    memcpy( &r, p, sizeof( r ) );
+    return r;
+}
+
+/**
+ * Write the unsigned 16 bits integer to the given address, which need not
+ * be aligned.
+ *
+ * \param   p pointer to 2 bytes of data
+ * \param   x data to write
+ */
+inline void mbedtls_put_unaligned_uint16( void *p, uint16_t x )
+{
+    memcpy( p, &x, sizeof( x ) );
+}
+
+/**
+ * Read the unsigned 32 bits integer from the given address, which need not
+ * be aligned.
+ *
+ * \param   p pointer to 4 bytes of data
+ * \return  Data at the given address
+ */
+inline uint32_t mbedtls_get_unaligned_uint32( const void *p )
+{
+    uint32_t r;
+    memcpy( &r, p, sizeof( r ) );
+    return r;
+}
+
+/**
+ * Write the unsigned 32 bits integer to the given address, which need not
+ * be aligned.
+ *
+ * \param   p pointer to 4 bytes of data
+ * \param   x data to write
+ */
+inline void mbedtls_put_unaligned_uint32( void *p, uint32_t x )
+{
+    memcpy( p, &x, sizeof( x ) );
+}
+
+/**
+ * Read the unsigned 64 bits integer from the given address, which need not
+ * be aligned.
+ *
+ * \param   p pointer to 8 bytes of data
+ * \return  Data at the given address
+ */
+inline uint64_t mbedtls_get_unaligned_uint64( const void *p )
+{
+    uint64_t r;
+    memcpy( &r, p, sizeof( r ) );
+    return r;
+}
+
+/**
+ * Write the unsigned 64 bits integer to the given address, which need not
+ * be aligned.
+ *
+ * \param   p pointer to 8 bytes of data
+ * \param   x data to write
+ */
+inline void mbedtls_put_unaligned_uint64( void *p, uint64_t x )
+{
+    memcpy( p, &x, sizeof( x ) );
+}
+
+/** Byte Reading Macros
+ *
+ * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
+ * byte from x, where byte 0 is the least significant byte.
+ */
+#define MBEDTLS_BYTE_0( x ) ( (uint8_t) (   ( x )         & 0xff ) )
+#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8  ) & 0xff ) )
+#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) )
+#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) )
+#define MBEDTLS_BYTE_4( x ) ( (uint8_t) ( ( ( x ) >> 32 ) & 0xff ) )
+#define MBEDTLS_BYTE_5( x ) ( (uint8_t) ( ( ( x ) >> 40 ) & 0xff ) )
+#define MBEDTLS_BYTE_6( x ) ( (uint8_t) ( ( ( x ) >> 48 ) & 0xff ) )
+#define MBEDTLS_BYTE_7( x ) ( (uint8_t) ( ( ( x ) >> 56 ) & 0xff ) )
+
+/*
+ * Detect GCC built-in byteswap routines
+ */
+#if defined(__GNUC__) && defined(__GNUC_PREREQ)
+#if __GNUC_PREREQ(4,8)
+#define MBEDTLS_BSWAP16 __builtin_bswap16
+#endif /* __GNUC_PREREQ(4,8) */
+#if __GNUC_PREREQ(4,3)
+#define MBEDTLS_BSWAP32 __builtin_bswap32
+#define MBEDTLS_BSWAP64 __builtin_bswap64
+#endif /* __GNUC_PREREQ(4,3) */
+#endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */
+
+/*
+ * Detect Clang built-in byteswap routines
+ */
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_bswap16)
+#define MBEDTLS_BSWAP16 __builtin_bswap16
+#endif /* __has_builtin(__builtin_bswap16) */
+#if __has_builtin(__builtin_bswap32)
+#define MBEDTLS_BSWAP32 __builtin_bswap32
+#endif /* __has_builtin(__builtin_bswap32) */
+#if __has_builtin(__builtin_bswap64)
+#define MBEDTLS_BSWAP64 __builtin_bswap64
+#endif /* __has_builtin(__builtin_bswap64) */
+#endif /* defined(__clang__) && defined(__has_builtin) */
+
+/*
+ * Detect MSVC built-in byteswap routines
+ */
+#if defined(_MSC_VER)
+#define MBEDTLS_BSWAP16 _byteswap_ushort
+#define MBEDTLS_BSWAP32 _byteswap_ulong
+#define MBEDTLS_BSWAP64 _byteswap_uint64
+#endif /* defined(_MSC_VER) */
+
+/* Detect armcc built-in byteswap routine */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000)
+#define MBEDTLS_BSWAP32 __rev
+#endif
+
+/*
+ * Where compiler built-ins are not present, fall back to C code that the
+ * compiler may be able to detect and transform into the relevant bswap or
+ * similar instruction.
+ */
+#if !defined(MBEDTLS_BSWAP16)
+static inline uint16_t mbedtls_bswap16( uint16_t x ) {
+    return
+         ( x & 0x00ff ) << 8 |
+         ( x & 0xff00 ) >> 8;
+}
+#define MBEDTLS_BSWAP16 mbedtls_bswap16
+#endif /* !defined(MBEDTLS_BSWAP16) */
+
+#if !defined(MBEDTLS_BSWAP32)
+static inline uint32_t mbedtls_bswap32( uint32_t x ) {
+    return
+         ( x & 0x000000ff ) << 24 |
+         ( x & 0x0000ff00 ) <<  8 |
+         ( x & 0x00ff0000 ) >>  8 |
+         ( x & 0xff000000 ) >> 24;
+}
+#define MBEDTLS_BSWAP32 mbedtls_bswap32
+#endif /* !defined(MBEDTLS_BSWAP32) */
+
+#if !defined(MBEDTLS_BSWAP64)
+static inline uint64_t mbedtls_bswap64( uint64_t x ) {
+    return
+         ( x & 0x00000000000000ff ) << 56 |
+         ( x & 0x000000000000ff00 ) << 40 |
+         ( x & 0x0000000000ff0000 ) << 24 |
+         ( x & 0x00000000ff000000 ) <<  8 |
+         ( x & 0x000000ff00000000 ) >>  8 |
+         ( x & 0x0000ff0000000000 ) >> 24 |
+         ( x & 0x00ff000000000000 ) >> 40 |
+         ( x & 0xff00000000000000 ) >> 56;
+}
+#define MBEDTLS_BSWAP64 mbedtls_bswap64
+#endif /* !defined(MBEDTLS_BSWAP64) */
+
+#if !defined(__BYTE_ORDER__)
+static const uint16_t mbedtls_byte_order_detector = { 0x100 };
+#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)
+#else
+#define MBEDTLS_IS_BIG_ENDIAN ((__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__))
+#endif /* !defined(__BYTE_ORDER__) */
+
+/**
+ * Get the unsigned 32 bits integer corresponding to four bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the four bytes from.
+ * \param   offset  Offset from \p data of the first and most significant
+ *                  byte of the four bytes to build the 32 bits unsigned
+ *                  integer from.
+ */
+#define MBEDTLS_GET_UINT32_BE( data, offset )                              \
+    ( ( MBEDTLS_IS_BIG_ENDIAN )                                            \
+        ? mbedtls_get_unaligned_uint32((data) + (offset))                  \
+        : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
+    )
+
+/**
+ * Put in memory a 32 bits unsigned integer in big-endian order.
+ *
+ * \param   n       32 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 32
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the most significant
+ *                  byte of the 32 bits unsigned integer \p n.
+ */
+#define MBEDTLS_PUT_UINT32_BE( n, data, offset )                             \
+{                                                                            \
+    if ( MBEDTLS_IS_BIG_ENDIAN )                                             \
+    {                                                                        \
+        mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t)(n));      \
+    }                                                                        \
+    else                                                                     \
+    {                                                                        \
+        mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t)(n))); \
+    }                                                                        \
+}
+
+/**
+ * Get the unsigned 32 bits integer corresponding to four bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the four bytes from.
+ * \param   offset  Offset from \p data of the first and least significant
+ *                  byte of the four bytes to build the 32 bits unsigned
+ *                  integer from.
+ */
+#define MBEDTLS_GET_UINT32_LE( data, offset )                              \
+    ( ( MBEDTLS_IS_BIG_ENDIAN )                                            \
+        ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
+        : mbedtls_get_unaligned_uint32((data) + (offset))                  \
+    )
+
+
+/**
+ * Put in memory a 32 bits unsigned integer in little-endian order.
+ *
+ * \param   n       32 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 32
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the least significant
+ *                  byte of the 32 bits unsigned integer \p n.
+ */
+#define MBEDTLS_PUT_UINT32_LE( n, data, offset )                             \
+{                                                                            \
+    if ( MBEDTLS_IS_BIG_ENDIAN )                                             \
+    {                                                                        \
+        mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t)(n))); \
+    }                                                                        \
+    else                                                                     \
+    {                                                                        \
+        mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t)(n)));      \
+    }                                                                        \
+}
+
+/**
+ * Get the unsigned 16 bits integer corresponding to two bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the two bytes from.
+ * \param   offset  Offset from \p data of the first and least significant
+ *                  byte of the two bytes to build the 16 bits unsigned
+ *                  integer from.
+ */
+#define MBEDTLS_GET_UINT16_LE( data, offset )                              \
+    ( ( MBEDTLS_IS_BIG_ENDIAN )                                            \
+        ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
+        : mbedtls_get_unaligned_uint16((data) + (offset))                  \
+    )
+
+/**
+ * Put in memory a 16 bits unsigned integer in little-endian order.
+ *
+ * \param   n       16 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 16
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the least significant
+ *                  byte of the 16 bits unsigned integer \p n.
+ */
+#define MBEDTLS_PUT_UINT16_LE( n, data, offset )                             \
+{                                                                            \
+    if ( MBEDTLS_IS_BIG_ENDIAN )                                             \
+    {                                                                        \
+        mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t)(n))); \
+    }                                                                        \
+    else                                                                     \
+    {                                                                        \
+        mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t)(n));      \
+    }                                                                        \
+}
+
+/**
+ * Get the unsigned 16 bits integer corresponding to two bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the two bytes from.
+ * \param   offset  Offset from \p data of the first and most significant
+ *                  byte of the two bytes to build the 16 bits unsigned
+ *                  integer from.
+ */
+#define MBEDTLS_GET_UINT16_BE( data, offset )                              \
+    ( ( MBEDTLS_IS_BIG_ENDIAN )                                            \
+        ? mbedtls_get_unaligned_uint16((data) + (offset))                  \
+        : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
+    )
+
+/**
+ * Put in memory a 16 bits unsigned integer in big-endian order.
+ *
+ * \param   n       16 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 16
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the most significant
+ *                  byte of the 16 bits unsigned integer \p n.
+ */
+#define MBEDTLS_PUT_UINT16_BE( n, data, offset )                             \
+{                                                                            \
+    if ( MBEDTLS_IS_BIG_ENDIAN )                                             \
+    {                                                                        \
+        mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t)(n));      \
+    }                                                                        \
+    else                                                                     \
+    {                                                                        \
+        mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t)(n))); \
+    }                                                                        \
+}
+
+/**
+ * Get the unsigned 24 bits integer corresponding to three bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the three bytes from.
+ * \param   offset  Offset from \p data of the first and most significant
+ *                  byte of the three bytes to build the 24 bits unsigned
+ *                  integer from.
+ */
+#define MBEDTLS_GET_UINT24_BE( data , offset )                  \
+    (                                                           \
+          ( (uint32_t) ( data )[( offset )    ] << 16 )         \
+        | ( (uint32_t) ( data )[( offset ) + 1] << 8  )         \
+        | ( (uint32_t) ( data )[( offset ) + 2]       )         \
+    )
+
+/**
+ * Put in memory a 24 bits unsigned integer in big-endian order.
+ *
+ * \param   n       24 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 24
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the most significant
+ *                  byte of the 24 bits unsigned integer \p n.
+ */
+#define MBEDTLS_PUT_UINT24_BE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_2( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_0( n );             \
+}
+
+/**
+ * Get the unsigned 24 bits integer corresponding to three bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the three bytes from.
+ * \param   offset  Offset from \p data of the first and least significant
+ *                  byte of the three bytes to build the 24 bits unsigned
+ *                  integer from.
+ */
+#define MBEDTLS_GET_UINT24_LE( data, offset )                   \
+    (                                                           \
+          ( (uint32_t) ( data )[( offset )    ]       )         \
+        | ( (uint32_t) ( data )[( offset ) + 1] <<  8 )         \
+        | ( (uint32_t) ( data )[( offset ) + 2] << 16 )         \
+    )
+
+/**
+ * Put in memory a 24 bits unsigned integer in little-endian order.
+ *
+ * \param   n       24 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 24
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the least significant
+ *                  byte of the 24 bits unsigned integer \p n.
+ */
+#define MBEDTLS_PUT_UINT24_LE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n );             \
+}
+
+/**
+ * Get the unsigned 64 bits integer corresponding to eight bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the eight bytes from.
+ * \param   offset  Offset from \p data of the first and most significant
+ *                  byte of the eight bytes to build the 64 bits unsigned
+ *                  integer from.
+ */
+#define MBEDTLS_GET_UINT64_BE( data, offset )                              \
+    ( ( MBEDTLS_IS_BIG_ENDIAN )                                            \
+        ? mbedtls_get_unaligned_uint64((data) + (offset))                  \
+        : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
+    )
+
+/**
+ * Put in memory a 64 bits unsigned integer in big-endian order.
+ *
+ * \param   n       64 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 64
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the most significant
+ *                  byte of the 64 bits unsigned integer \p n.
+ */
+#define MBEDTLS_PUT_UINT64_BE( n, data, offset )                             \
+{                                                                            \
+    if ( MBEDTLS_IS_BIG_ENDIAN )                                             \
+    {                                                                        \
+        mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t)(n));      \
+    }                                                                        \
+    else                                                                     \
+    {                                                                        \
+        mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t)(n))); \
+    }                                                                        \
+}
+
+/**
+ * Get the unsigned 64 bits integer corresponding to eight bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the eight bytes from.
+ * \param   offset  Offset from \p data of the first and least significant
+ *                  byte of the eight bytes to build the 64 bits unsigned
+ *                  integer from.
+ */
+#define MBEDTLS_GET_UINT64_LE( data, offset )                              \
+    ( ( MBEDTLS_IS_BIG_ENDIAN )                                            \
+        ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
+        : mbedtls_get_unaligned_uint64((data) + (offset))                  \
+    )
+
+/**
+ * Put in memory a 64 bits unsigned integer in little-endian order.
+ *
+ * \param   n       64 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 64
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the least significant
+ *                  byte of the 64 bits unsigned integer \p n.
+ */
+#define MBEDTLS_PUT_UINT64_LE( n, data, offset )                             \
+{                                                                            \
+    if ( MBEDTLS_IS_BIG_ENDIAN )                                             \
+    {                                                                        \
+        mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t)(n))); \
+    }                                                                        \
+    else                                                                     \
+    {                                                                        \
+        mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t)(n));      \
+    }                                                                        \
+}
+
+#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */
diff --git a/library/aria.c b/library/aria.c
index 5e52eea..517e10a 100644
--- a/library/aria.c
+++ b/library/aria.c
@@ -98,47 +98,8 @@
  * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness
  *
  * This is submatrix P3 in [1] Appendix B.1
- *
- * Some compilers fail to translate this to a single instruction,
- * so let's provide asm versions for common platforms with C fallback.
  */
-#if defined(MBEDTLS_HAVE_ASM)
-#if defined(__arm__) /* rev available from v6 up */
-/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
-#if defined(__GNUC__) && \
-    ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \
-    __ARM_ARCH >= 6
-static inline uint32_t aria_p3( uint32_t x )
-{
-    uint32_t r;
-    __asm( "rev %0, %1" : "=l" (r) : "l" (x) );
-    return( r );
-}
-#define ARIA_P3 aria_p3
-#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \
-    ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 )
-static inline uint32_t aria_p3( uint32_t x )
-{
-    uint32_t r;
-    __asm( "rev r, x" );
-    return( r );
-}
-#define ARIA_P3 aria_p3
-#endif
-#endif /* arm */
-#if defined(__GNUC__) && \
-    defined(__i386__) || defined(__amd64__) || defined( __x86_64__)
-static inline uint32_t aria_p3( uint32_t x )
-{
-    __asm( "bswap %0" : "=r" (x) : "0" (x) );
-    return( x );
-}
-#define ARIA_P3 aria_p3
-#endif /* x86 gnuc */
-#endif /* MBEDTLS_HAVE_ASM && GNUC */
-#if !defined(ARIA_P3)
-#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) )
-#endif
+#define ARIA_P3(x) MBEDTLS_BSWAP32(x)
 
 /*
  * ARIA Affine Transform
@@ -583,7 +544,6 @@
                             const unsigned char *input,
                             unsigned char *output )
 {
-    int i;
     unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE];
 
     ARIA_VALIDATE_RET( ctx != NULL );
@@ -603,8 +563,7 @@
             memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE );
             mbedtls_aria_crypt_ecb( ctx, input, output );
 
-            for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ )
-                output[i] = (unsigned char)( output[i] ^ iv[i] );
+            mbedtls_xor( output, output, iv, MBEDTLS_ARIA_BLOCKSIZE );
 
             memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE );
 
@@ -617,8 +576,7 @@
     {
         while( length > 0 )
         {
-            for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+            mbedtls_xor( output, input, iv, MBEDTLS_ARIA_BLOCKSIZE );
 
             mbedtls_aria_crypt_ecb( ctx, output, output );
             memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE );
diff --git a/library/bignum_core.c b/library/bignum_core.c
index 30fc661..1ce8457 100644
--- a/library/bignum_core.c
+++ b/library/bignum_core.c
@@ -83,45 +83,25 @@
 
 static mbedtls_mpi_uint mpi_bigendian_to_host( mbedtls_mpi_uint a )
 {
-#if defined(__BYTE_ORDER__)
-
-/* Nothing to do on bigendian systems. */
-#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
-    return( a );
-#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
-
-#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
-
-/* For GCC and Clang, have builtins for byte swapping. */
-#if defined(__GNUC__) && defined(__GNUC_PREREQ)
-#if __GNUC_PREREQ(4,3)
-#define have_bswap
-#endif
-#endif
-
-#if defined(__clang__) && defined(__has_builtin)
-#if __has_builtin(__builtin_bswap32)  &&                 \
-    __has_builtin(__builtin_bswap64)
-#define have_bswap
-#endif
-#endif
-
-#if defined(have_bswap)
-    /* The compiler is hopefully able to statically evaluate this! */
-    switch( sizeof(mbedtls_mpi_uint) )
+    if ( MBEDTLS_IS_BIG_ENDIAN )
     {
-        case 4:
-            return( __builtin_bswap32(a) );
-        case 8:
-            return( __builtin_bswap64(a) );
+        /* Nothing to do on bigendian systems. */
+        return( a );
     }
-#endif
-#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
-#endif /* __BYTE_ORDER__ */
+    else
+    {
+        switch( sizeof(mbedtls_mpi_uint) )
+        {
+            case 4:
+                return (mbedtls_mpi_uint) MBEDTLS_BSWAP32( (uint32_t)a );
+            case 8:
+                return (mbedtls_mpi_uint) MBEDTLS_BSWAP64( (uint64_t)a );
+        }
 
-    /* Fall back to C-based reordering if we don't know the byte order
-     * or we couldn't use a compiler-specific builtin. */
-    return( mpi_bigendian_to_host_c( a ) );
+        /* Fall back to C-based reordering if we don't know the byte order
+        * or we couldn't use a compiler-specific builtin. */
+        return( mpi_bigendian_to_host_c( a ) );
+    }
 }
 
 void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
diff --git a/library/bignum_core.h b/library/bignum_core.h
index add7fee..b7af4d0 100644
--- a/library/bignum_core.h
+++ b/library/bignum_core.h
@@ -517,6 +517,9 @@
  * \brief            Perform a modular exponentiation with secret exponent:
  *                   X = A^E mod N, where \p A is already in Montgomery form.
  *
+ * \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs ==
+ * \p AN_limbs.
+ *
  * \param[out] X     The destination MPI, as a little endian array of length
  *                   \p AN_limbs.
  * \param[in] A      The base MPI, as a little endian array of length \p AN_limbs.
diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c
index 22e56b7..c98a1c1 100644
--- a/library/bignum_mod_raw.c
+++ b/library/bignum_mod_raw.c
@@ -124,6 +124,37 @@
 
 /* BEGIN MERGE SLOT 3 */
 
+size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs( size_t AN_limbs )
+{
+    /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent,
+     * which will be the same size as the modulus and input (AN_limbs),
+     * and additional space to pass to mbedtls_mpi_core_exp_mod(). */
+    return( AN_limbs +
+            mbedtls_mpi_core_exp_mod_working_limbs( AN_limbs, AN_limbs ) );
+}
+
+void mbedtls_mpi_mod_raw_inv_prime( mbedtls_mpi_uint *X,
+                                    const mbedtls_mpi_uint *A,
+                                    const mbedtls_mpi_uint *N,
+                                    size_t AN_limbs,
+                                    const mbedtls_mpi_uint *RR,
+                                    mbedtls_mpi_uint *T )
+{
+    /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and
+     *                       |G| = N - 1, so we want
+     *                 g^(|G|-1) = g^(N - 2)
+     */
+
+    /* Use the first AN_limbs of T to hold N - 2 */
+    mbedtls_mpi_uint *Nminus2 = T;
+    (void) mbedtls_mpi_core_sub_int( Nminus2, N, 2, AN_limbs );
+
+    /* Rest of T is given to exp_mod for its working space */
+    mbedtls_mpi_core_exp_mod( X,
+                              A, N, AN_limbs, Nminus2, AN_limbs,
+                              RR, T + AN_limbs );
+}
+
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
@@ -182,6 +213,18 @@
     mbedtls_free( T );
     return( 0 );
 }
+
+void mbedtls_mpi_mod_raw_neg( mbedtls_mpi_uint *X,
+                              const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_mod_modulus *m )
+{
+    mbedtls_mpi_core_sub( X, m->p, A, m->limbs );
+
+    /* If A=0 initially, then X=N now. Detect this by
+     * subtracting N and catching the carry. */
+    mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub( X, X, m->p, m->limbs );
+    (void) mbedtls_mpi_core_add_if( X, m->p, m->limbs, (unsigned) borrow  );
+}
 /* END MERGE SLOT 7 */
 
 /* BEGIN MERGE SLOT 8 */
diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h
index d7b6dd1..f9968ba 100644
--- a/library/bignum_mod_raw.h
+++ b/library/bignum_mod_raw.h
@@ -174,6 +174,51 @@
 
 /* BEGIN MERGE SLOT 3 */
 
+/**
+ * \brief          Returns the number of limbs of working memory required for
+ *                 a call to `mbedtls_mpi_mod_raw_inv_prime()`.
+ *
+ * \param AN_limbs The number of limbs in the input `A` and the modulus `N`
+ *                 (they must be the same size) that will be given to
+ *                 `mbedtls_mpi_mod_raw_inv_prime()`.
+ *
+ * \return         The number of limbs of working memory required by
+ *                 `mbedtls_mpi_mod_raw_inv_prime()`.
+ */
+size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs( size_t AN_limbs );
+
+/**
+ * \brief Perform fixed-width modular inversion of a Montgomery-form MPI with
+ *        respect to a modulus \p N that must be prime.
+ *
+ * \p X may be aliased to \p A, but not to \p N or \p RR.
+ *
+ * \param[out] X     The modular inverse of \p A with respect to \p N.
+ *                   Will be in Montgomery form.
+ * \param[in] A      The number to calculate the modular inverse of.
+ *                   Must be in Montgomery form. Must not be 0.
+ * \param[in] N      The modulus, as a little-endian array of length \p AN_limbs.
+ *                   Must be prime.
+ * \param AN_limbs   The number of limbs in \p A, \p N and \p RR.
+ * \param[in] RR     The precomputed residue of 2^{2*biL} modulo N, as a little-
+ *                   endian array of length \p AN_limbs.
+ * \param[in,out] T  Temporary storage of at least the number of limbs returned
+ *                   by `mbedtls_mpi_mod_raw_inv_prime_working_limbs()`.
+ *                   Its initial content is unused and its final content is
+ *                   indeterminate.
+ *                   It must not alias or otherwise overlap any of the other
+ *                   parameters.
+ *                   It is up to the caller to zeroize \p T when it is no
+ *                   longer needed, and before freeing it if it was dynamically
+ *                   allocated.
+ */
+void mbedtls_mpi_mod_raw_inv_prime( mbedtls_mpi_uint *X,
+                                    const mbedtls_mpi_uint *A,
+                                    const mbedtls_mpi_uint *N,
+                                    size_t AN_limbs,
+                                    const mbedtls_mpi_uint *RR,
+                                    mbedtls_mpi_uint *T );
+
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
@@ -233,6 +278,23 @@
  */
 int mbedtls_mpi_mod_raw_from_mont_rep( mbedtls_mpi_uint *X,
                                        const mbedtls_mpi_mod_modulus *m );
+
+/** \brief  Perform fixed width modular negation.
+ *
+ * The size of the operation is determined by \p m. \p A must have
+ * the same number of limbs as \p m.
+ *
+ * \p X may be aliased to \p A.
+ *
+ * \param[out] X        The result of the modular negation.
+ *                      This must be initialized.
+ * \param[in] A         Little-endian presentation of the input operand. This
+ *                      must be less than or equal to \p m.
+ * \param[in] m         The modulus to use.
+ */
+void mbedtls_mpi_mod_raw_neg( mbedtls_mpi_uint *X,
+                              const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_mod_modulus *m);
 /* END MERGE SLOT 7 */
 
 /* BEGIN MERGE SLOT 8 */
diff --git a/library/camellia.c b/library/camellia.c
index 5dd6c56..6e781c7 100644
--- a/library/camellia.c
+++ b/library/camellia.c
@@ -526,7 +526,6 @@
                                 const unsigned char *input,
                                 unsigned char *output )
 {
-    int i;
     unsigned char temp[16];
     if( mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT )
         return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
@@ -541,8 +540,7 @@
             memcpy( temp, input, 16 );
             mbedtls_camellia_crypt_ecb( ctx, mode, input, output );
 
-            for( i = 0; i < 16; i++ )
-                output[i] = (unsigned char)( output[i] ^ iv[i] );
+            mbedtls_xor( output, output, iv, 16 );
 
             memcpy( iv, temp, 16 );
 
@@ -555,8 +553,7 @@
     {
         while( length > 0 )
         {
-            for( i = 0; i < 16; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+            mbedtls_xor( output, input, iv, 16 );
 
             mbedtls_camellia_crypt_ecb( ctx, mode, output, output );
             memcpy( iv, output, 16 );
diff --git a/library/ccm.c b/library/ccm.c
index 675783e..065eb60 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -112,7 +112,6 @@
                               const unsigned char *input,
                               unsigned char *output )
 {
-    size_t i;
     size_t olen = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char tmp_buf[16] = {0};
@@ -125,8 +124,7 @@
         return ret;
     }
 
-    for( i = 0; i < use_len; i++ )
-        output[i] = input[i] ^ tmp_buf[offset + i];
+    mbedtls_xor( output, input, tmp_buf + offset, use_len );
 
     mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
     return ret;
@@ -269,7 +267,6 @@
                            size_t add_len )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char i;
     size_t olen, use_len, offset;
 
     if( ctx->state & CCM_STATE__ERROR )
@@ -310,8 +307,7 @@
             if( use_len > add_len )
                 use_len = add_len;
 
-            for( i = 0; i < use_len; i++ )
-                ctx->y[i + offset] ^= add[i];
+            mbedtls_xor( ctx->y + offset, ctx->y + offset, add, use_len );
 
             ctx->processed += use_len;
             add_len -= use_len;
@@ -381,8 +377,7 @@
         if( ctx->mode == MBEDTLS_CCM_ENCRYPT || \
             ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT )
         {
-            for( i = 0; i < use_len; i++ )
-                ctx->y[i + offset] ^= input[i];
+            mbedtls_xor( ctx->y + offset, ctx->y + offset, input, use_len );
 
             if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len )
             {
@@ -411,8 +406,7 @@
             if( ret != 0 )
                 goto exit;
 
-            for( i = 0; i < use_len; i++ )
-                ctx->y[i + offset] ^= local_output[i];
+            mbedtls_xor( ctx->y + offset, ctx->y + offset, local_output, use_len );
 
             memcpy( output, local_output, use_len );
             mbedtls_platform_zeroize( local_output, 16 );
diff --git a/library/chacha20.c b/library/chacha20.c
index 85d7461..d17c58c 100644
--- a/library/chacha20.c
+++ b/library/chacha20.c
@@ -217,7 +217,6 @@
                               unsigned char *output )
 {
     size_t offset = 0U;
-    size_t i;
 
     /* Use leftover keystream bytes, if available */
     while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
@@ -237,17 +236,7 @@
         chacha20_block( ctx->state, ctx->keystream8 );
         ctx->state[CHACHA20_CTR_INDEX]++;
 
-        for( i = 0U; i < 64U; i += 8U )
-        {
-            output[offset + i  ] = input[offset + i  ] ^ ctx->keystream8[i  ];
-            output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
-            output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
-            output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
-            output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
-            output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
-            output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
-            output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
-        }
+        mbedtls_xor( output + offset, input + offset, ctx->keystream8, 64U );
 
         offset += CHACHA20_BLOCK_SIZE_BYTES;
         size   -= CHACHA20_BLOCK_SIZE_BYTES;
@@ -260,10 +249,7 @@
         chacha20_block( ctx->state, ctx->keystream8 );
         ctx->state[CHACHA20_CTR_INDEX]++;
 
-        for( i = 0U; i < size; i++)
-        {
-            output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
-        }
+        mbedtls_xor( output + offset, input + offset, ctx->keystream8, size );
 
         ctx->keystream_bytes_used = size;
 
diff --git a/library/cmac.c b/library/cmac.c
index 3cc49d1..9870856 100644
--- a/library/cmac.c
+++ b/library/cmac.c
@@ -148,15 +148,6 @@
 #endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */
 
 #if !defined(MBEDTLS_CMAC_ALT)
-static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
-                            const unsigned char *input2,
-                            const size_t block_size )
-{
-    size_t idx;
-
-    for( idx = 0; idx < block_size; idx++ )
-        output[ idx ] = input1[ idx ] ^ input2[ idx ];
-}
 
 /*
  * Create padded last block from (partial) last block.
@@ -247,7 +238,7 @@
                 input,
                 block_size - cmac_ctx->unprocessed_len );
 
-        cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
+        mbedtls_xor( state, cmac_ctx->unprocessed_block, state, block_size );
 
         if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
                                            &olen ) ) != 0 )
@@ -267,7 +258,7 @@
      * final partial or complete block */
     for( j = 1; j < n; j++ )
     {
-        cmac_xor_block( state, input, state, block_size );
+        mbedtls_xor( state, input, state, block_size );
 
         if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
                                            &olen ) ) != 0 )
@@ -319,16 +310,16 @@
     if( cmac_ctx->unprocessed_len < block_size )
     {
         cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
-        cmac_xor_block( M_last, M_last, K2, block_size );
+        mbedtls_xor( M_last, M_last, K2, block_size );
     }
     else
     {
         /* Last block is complete block */
-        cmac_xor_block( M_last, last_block, K1, block_size );
+        mbedtls_xor( M_last, last_block, K1, block_size );
     }
 
 
-    cmac_xor_block( state, M_last, state, block_size );
+    mbedtls_xor( state, M_last, state, block_size );
     if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
                                        &olen ) ) != 0 )
     {
diff --git a/library/common.h b/library/common.h
index 25d5294..9d3b8fe 100644
--- a/library/common.h
+++ b/library/common.h
@@ -24,9 +24,11 @@
 #define MBEDTLS_LIBRARY_COMMON_H
 
 #include "mbedtls/build_info.h"
+#include "alignment.h"
 
 #include <stddef.h>
 #include <stdint.h>
+#include <stddef.h>
 
 /** Helper to define a function as static except when building invasive tests.
  *
@@ -107,327 +109,30 @@
     return( p == NULL ? NULL : p + n );
 }
 
-/** Byte Reading Macros
- *
- * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
- * byte from x, where byte 0 is the least significant byte.
- */
-#define MBEDTLS_BYTE_0( x ) ( (uint8_t) (   ( x )         & 0xff ) )
-#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8  ) & 0xff ) )
-#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) )
-#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) )
-#define MBEDTLS_BYTE_4( x ) ( (uint8_t) ( ( ( x ) >> 32 ) & 0xff ) )
-#define MBEDTLS_BYTE_5( x ) ( (uint8_t) ( ( ( x ) >> 40 ) & 0xff ) )
-#define MBEDTLS_BYTE_6( x ) ( (uint8_t) ( ( ( x ) >> 48 ) & 0xff ) )
-#define MBEDTLS_BYTE_7( x ) ( (uint8_t) ( ( ( x ) >> 56 ) & 0xff ) )
-
 /**
- * Get the unsigned 32 bits integer corresponding to four bytes in
- * big-endian order (MSB first).
+ * Perform a fast block XOR operation, such that
+ * r[i] = a[i] ^ b[i] where 0 <= i < n
  *
- * \param   data    Base address of the memory to get the four bytes from.
- * \param   offset  Offset from \p data of the first and most significant
- *                  byte of the four bytes to build the 32 bits unsigned
- *                  integer from.
+ * \param   r Pointer to result (buffer of at least \p n bytes). \p r
+ *            may be equal to either \p a or \p b, but behaviour when
+ *            it overlaps in other ways is undefined.
+ * \param   a Pointer to input (buffer of at least \p n bytes)
+ * \param   b Pointer to input (buffer of at least \p n bytes)
+ * \param   n Number of bytes to process.
  */
-#ifndef MBEDTLS_GET_UINT32_BE
-#define MBEDTLS_GET_UINT32_BE( data , offset )                  \
-    (                                                           \
-          ( (uint32_t) ( data )[( offset )    ] << 24 )         \
-        | ( (uint32_t) ( data )[( offset ) + 1] << 16 )         \
-        | ( (uint32_t) ( data )[( offset ) + 2] <<  8 )         \
-        | ( (uint32_t) ( data )[( offset ) + 3]       )         \
-    )
-#endif
-
-/**
- * Put in memory a 32 bits unsigned integer in big-endian order.
- *
- * \param   n       32 bits unsigned integer to put in memory.
- * \param   data    Base address of the memory where to put the 32
- *                  bits unsigned integer in.
- * \param   offset  Offset from \p data where to put the most significant
- *                  byte of the 32 bits unsigned integer \p n.
- */
-#ifndef MBEDTLS_PUT_UINT32_BE
-#define MBEDTLS_PUT_UINT32_BE( n, data, offset )                \
-{                                                               \
-    ( data )[( offset )    ] = MBEDTLS_BYTE_3( n );             \
-    ( data )[( offset ) + 1] = MBEDTLS_BYTE_2( n );             \
-    ( data )[( offset ) + 2] = MBEDTLS_BYTE_1( n );             \
-    ( data )[( offset ) + 3] = MBEDTLS_BYTE_0( n );             \
+inline void mbedtls_xor( unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n )
+{
+    size_t i;
+    for ( i = 0; ( i + 4 ) <= n; i += 4 )
+    {
+        uint32_t x = mbedtls_get_unaligned_uint32( a + i ) ^ mbedtls_get_unaligned_uint32( b + i );
+        mbedtls_put_unaligned_uint32( r + i, x );
+    }
+    for ( ; i < n; i++ )
+    {
+        r[i] = a[i] ^ b[i];
+    }
 }
-#endif
-
-/**
- * Get the unsigned 32 bits integer corresponding to four bytes in
- * little-endian order (LSB first).
- *
- * \param   data    Base address of the memory to get the four bytes from.
- * \param   offset  Offset from \p data of the first and least significant
- *                  byte of the four bytes to build the 32 bits unsigned
- *                  integer from.
- */
-#ifndef MBEDTLS_GET_UINT32_LE
-#define MBEDTLS_GET_UINT32_LE( data, offset )                   \
-    (                                                           \
-          ( (uint32_t) ( data )[( offset )    ]       )         \
-        | ( (uint32_t) ( data )[( offset ) + 1] <<  8 )         \
-        | ( (uint32_t) ( data )[( offset ) + 2] << 16 )         \
-        | ( (uint32_t) ( data )[( offset ) + 3] << 24 )         \
-    )
-#endif
-
-/**
- * Put in memory a 32 bits unsigned integer in little-endian order.
- *
- * \param   n       32 bits unsigned integer to put in memory.
- * \param   data    Base address of the memory where to put the 32
- *                  bits unsigned integer in.
- * \param   offset  Offset from \p data where to put the least significant
- *                  byte of the 32 bits unsigned integer \p n.
- */
-#ifndef MBEDTLS_PUT_UINT32_LE
-#define MBEDTLS_PUT_UINT32_LE( n, data, offset )                \
-{                                                               \
-    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
-    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
-    ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n );             \
-    ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n );             \
-}
-#endif
-
-/**
- * Get the unsigned 16 bits integer corresponding to two bytes in
- * little-endian order (LSB first).
- *
- * \param   data    Base address of the memory to get the two bytes from.
- * \param   offset  Offset from \p data of the first and least significant
- *                  byte of the two bytes to build the 16 bits unsigned
- *                  integer from.
- */
-#ifndef MBEDTLS_GET_UINT16_LE
-#define MBEDTLS_GET_UINT16_LE( data, offset )                   \
-    (                                                           \
-          ( (uint16_t) ( data )[( offset )    ]       )         \
-        | ( (uint16_t) ( data )[( offset ) + 1] <<  8 )         \
-    )
-#endif
-
-/**
- * Put in memory a 16 bits unsigned integer in little-endian order.
- *
- * \param   n       16 bits unsigned integer to put in memory.
- * \param   data    Base address of the memory where to put the 16
- *                  bits unsigned integer in.
- * \param   offset  Offset from \p data where to put the least significant
- *                  byte of the 16 bits unsigned integer \p n.
- */
-#ifndef MBEDTLS_PUT_UINT16_LE
-#define MBEDTLS_PUT_UINT16_LE( n, data, offset )                \
-{                                                               \
-    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
-    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
-}
-#endif
-
-/**
- * Get the unsigned 16 bits integer corresponding to two bytes in
- * big-endian order (MSB first).
- *
- * \param   data    Base address of the memory to get the two bytes from.
- * \param   offset  Offset from \p data of the first and most significant
- *                  byte of the two bytes to build the 16 bits unsigned
- *                  integer from.
- */
-#ifndef MBEDTLS_GET_UINT16_BE
-#define MBEDTLS_GET_UINT16_BE( data, offset )                   \
-    (                                                           \
-          ( (uint16_t) ( data )[( offset )    ] << 8 )          \
-        | ( (uint16_t) ( data )[( offset ) + 1]      )          \
-    )
-#endif
-
-/**
- * Put in memory a 16 bits unsigned integer in big-endian order.
- *
- * \param   n       16 bits unsigned integer to put in memory.
- * \param   data    Base address of the memory where to put the 16
- *                  bits unsigned integer in.
- * \param   offset  Offset from \p data where to put the most significant
- *                  byte of the 16 bits unsigned integer \p n.
- */
-#ifndef MBEDTLS_PUT_UINT16_BE
-#define MBEDTLS_PUT_UINT16_BE( n, data, offset )                \
-{                                                               \
-    ( data )[( offset )    ] = MBEDTLS_BYTE_1( n );             \
-    ( data )[( offset ) + 1] = MBEDTLS_BYTE_0( n );             \
-}
-#endif
-
-/**
- * Get the unsigned 24 bits integer corresponding to three bytes in
- * big-endian order (MSB first).
- *
- * \param   data    Base address of the memory to get the three bytes from.
- * \param   offset  Offset from \p data of the first and most significant
- *                  byte of the three bytes to build the 24 bits unsigned
- *                  integer from.
- */
-#ifndef MBEDTLS_GET_UINT24_BE
-#define MBEDTLS_GET_UINT24_BE( data , offset )                  \
-    (                                                           \
-          ( (uint32_t) ( data )[( offset )    ] << 16 )         \
-        | ( (uint32_t) ( data )[( offset ) + 1] << 8  )         \
-        | ( (uint32_t) ( data )[( offset ) + 2]       )         \
-    )
-#endif
-
-/**
- * Put in memory a 24 bits unsigned integer in big-endian order.
- *
- * \param   n       24 bits unsigned integer to put in memory.
- * \param   data    Base address of the memory where to put the 24
- *                  bits unsigned integer in.
- * \param   offset  Offset from \p data where to put the most significant
- *                  byte of the 24 bits unsigned integer \p n.
- */
-#ifndef MBEDTLS_PUT_UINT24_BE
-#define MBEDTLS_PUT_UINT24_BE( n, data, offset )                \
-{                                                               \
-    ( data )[( offset )    ] = MBEDTLS_BYTE_2( n );             \
-    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
-    ( data )[( offset ) + 2] = MBEDTLS_BYTE_0( n );             \
-}
-#endif
-
-/**
- * Get the unsigned 24 bits integer corresponding to three bytes in
- * little-endian order (LSB first).
- *
- * \param   data    Base address of the memory to get the three bytes from.
- * \param   offset  Offset from \p data of the first and least significant
- *                  byte of the three bytes to build the 24 bits unsigned
- *                  integer from.
- */
-#ifndef MBEDTLS_GET_UINT24_LE
-#define MBEDTLS_GET_UINT24_LE( data, offset )                   \
-    (                                                           \
-          ( (uint32_t) ( data )[( offset )    ]       )         \
-        | ( (uint32_t) ( data )[( offset ) + 1] <<  8 )         \
-        | ( (uint32_t) ( data )[( offset ) + 2] << 16 )         \
-    )
-#endif
-
-/**
- * Put in memory a 24 bits unsigned integer in little-endian order.
- *
- * \param   n       24 bits unsigned integer to put in memory.
- * \param   data    Base address of the memory where to put the 24
- *                  bits unsigned integer in.
- * \param   offset  Offset from \p data where to put the least significant
- *                  byte of the 24 bits unsigned integer \p n.
- */
-#ifndef MBEDTLS_PUT_UINT24_LE
-#define MBEDTLS_PUT_UINT24_LE( n, data, offset )                \
-{                                                               \
-    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
-    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
-    ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n );             \
-}
-#endif
-
-/**
- * Get the unsigned 64 bits integer corresponding to eight bytes in
- * big-endian order (MSB first).
- *
- * \param   data    Base address of the memory to get the eight bytes from.
- * \param   offset  Offset from \p data of the first and most significant
- *                  byte of the eight bytes to build the 64 bits unsigned
- *                  integer from.
- */
-#ifndef MBEDTLS_GET_UINT64_BE
-#define MBEDTLS_GET_UINT64_BE( data, offset )                   \
-    (                                                           \
-          ( (uint64_t) ( data )[( offset )    ] << 56 )         \
-        | ( (uint64_t) ( data )[( offset ) + 1] << 48 )         \
-        | ( (uint64_t) ( data )[( offset ) + 2] << 40 )         \
-        | ( (uint64_t) ( data )[( offset ) + 3] << 32 )         \
-        | ( (uint64_t) ( data )[( offset ) + 4] << 24 )         \
-        | ( (uint64_t) ( data )[( offset ) + 5] << 16 )         \
-        | ( (uint64_t) ( data )[( offset ) + 6] <<  8 )         \
-        | ( (uint64_t) ( data )[( offset ) + 7]       )         \
-    )
-#endif
-
-/**
- * Put in memory a 64 bits unsigned integer in big-endian order.
- *
- * \param   n       64 bits unsigned integer to put in memory.
- * \param   data    Base address of the memory where to put the 64
- *                  bits unsigned integer in.
- * \param   offset  Offset from \p data where to put the most significant
- *                  byte of the 64 bits unsigned integer \p n.
- */
-#ifndef MBEDTLS_PUT_UINT64_BE
-#define MBEDTLS_PUT_UINT64_BE( n, data, offset )                \
-{                                                               \
-    ( data )[( offset )    ] = MBEDTLS_BYTE_7( n );             \
-    ( data )[( offset ) + 1] = MBEDTLS_BYTE_6( n );             \
-    ( data )[( offset ) + 2] = MBEDTLS_BYTE_5( n );             \
-    ( data )[( offset ) + 3] = MBEDTLS_BYTE_4( n );             \
-    ( data )[( offset ) + 4] = MBEDTLS_BYTE_3( n );             \
-    ( data )[( offset ) + 5] = MBEDTLS_BYTE_2( n );             \
-    ( data )[( offset ) + 6] = MBEDTLS_BYTE_1( n );             \
-    ( data )[( offset ) + 7] = MBEDTLS_BYTE_0( n );             \
-}
-#endif
-
-/**
- * Get the unsigned 64 bits integer corresponding to eight bytes in
- * little-endian order (LSB first).
- *
- * \param   data    Base address of the memory to get the eight bytes from.
- * \param   offset  Offset from \p data of the first and least significant
- *                  byte of the eight bytes to build the 64 bits unsigned
- *                  integer from.
- */
-#ifndef MBEDTLS_GET_UINT64_LE
-#define MBEDTLS_GET_UINT64_LE( data, offset )                   \
-    (                                                           \
-          ( (uint64_t) ( data )[( offset ) + 7] << 56 )         \
-        | ( (uint64_t) ( data )[( offset ) + 6] << 48 )         \
-        | ( (uint64_t) ( data )[( offset ) + 5] << 40 )         \
-        | ( (uint64_t) ( data )[( offset ) + 4] << 32 )         \
-        | ( (uint64_t) ( data )[( offset ) + 3] << 24 )         \
-        | ( (uint64_t) ( data )[( offset ) + 2] << 16 )         \
-        | ( (uint64_t) ( data )[( offset ) + 1] <<  8 )         \
-        | ( (uint64_t) ( data )[( offset )    ]       )         \
-    )
-#endif
-
-/**
- * Put in memory a 64 bits unsigned integer in little-endian order.
- *
- * \param   n       64 bits unsigned integer to put in memory.
- * \param   data    Base address of the memory where to put the 64
- *                  bits unsigned integer in.
- * \param   offset  Offset from \p data where to put the least significant
- *                  byte of the 64 bits unsigned integer \p n.
- */
-#ifndef MBEDTLS_PUT_UINT64_LE
-#define MBEDTLS_PUT_UINT64_LE( n, data, offset )                \
-{                                                               \
-    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
-    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
-    ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n );             \
-    ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n );             \
-    ( data )[( offset ) + 4] = MBEDTLS_BYTE_4( n );             \
-    ( data )[( offset ) + 5] = MBEDTLS_BYTE_5( n );             \
-    ( data )[( offset ) + 6] = MBEDTLS_BYTE_6( n );             \
-    ( data )[( offset ) + 7] = MBEDTLS_BYTE_7( n );             \
-}
-#endif
 
 /* Fix MSVC C99 compatible issue
  *      MSVC support __func__ from visual studio 2015( 1900 )
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 71c48af..f5c5e7b 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -174,8 +174,7 @@
 
         while( use_len > 0 )
         {
-            for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
-                chain[i] ^= p[i];
+            mbedtls_xor( chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE );
             p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
             use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
                        MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
diff --git a/library/des.c b/library/des.c
index 65f5681..c56d4d4 100644
--- a/library/des.c
+++ b/library/des.c
@@ -635,7 +635,6 @@
                     const unsigned char *input,
                     unsigned char *output )
 {
-    int i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
@@ -646,8 +645,7 @@
     {
         while( length > 0 )
         {
-            for( i = 0; i < 8; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+            mbedtls_xor( output, input, iv, 8 );
 
             ret = mbedtls_des_crypt_ecb( ctx, output, output );
             if( ret != 0 )
@@ -668,8 +666,7 @@
             if( ret != 0 )
                 goto exit;
 
-            for( i = 0; i < 8; i++ )
-                output[i] = (unsigned char)( output[i] ^ iv[i] );
+            mbedtls_xor( output, output, iv, 8 );
 
             memcpy( iv, temp, 8 );
 
@@ -741,7 +738,6 @@
                      const unsigned char *input,
                      unsigned char *output )
 {
-    int i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
@@ -752,8 +748,7 @@
     {
         while( length > 0 )
         {
-            for( i = 0; i < 8; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+            mbedtls_xor( output, input, iv, 8 );
 
             ret = mbedtls_des3_crypt_ecb( ctx, output, output );
             if( ret != 0 )
@@ -774,8 +769,7 @@
             if( ret != 0 )
                 goto exit;
 
-            for( i = 0; i < 8; i++ )
-                output[i] = (unsigned char)( output[i] ^ iv[i] );
+            mbedtls_xor( output, output, iv, 8 );
 
             memcpy( iv, temp, 8 );
 
diff --git a/library/entropy.c b/library/entropy.c
index 1e0d9d3..545fd9d 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -564,7 +564,7 @@
 }
 
 /*
- * A test to ensure hat the entropy sources are functioning correctly
+ * A test to ensure that the entropy sources are functioning correctly
  * and there is no obvious failure. The test performs the following checks:
  *  - The entropy source is not providing only 0s (all bits unset) or 1s (all
  *    bits set).
diff --git a/library/gcm.c b/library/gcm.c
index f004a73c..0178b5b 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -235,7 +235,6 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char work_buf[16];
-    size_t i;
     const unsigned char *p;
     size_t use_len, olen = 0;
     uint64_t iv_bits;
@@ -268,8 +267,7 @@
         {
             use_len = ( iv_len < 16 ) ? iv_len : 16;
 
-            for( i = 0; i < use_len; i++ )
-                ctx->y[i] ^= p[i];
+            mbedtls_xor( ctx->y, ctx->y, p, use_len );
 
             gcm_mult( ctx, ctx->y, ctx->y );
 
@@ -277,8 +275,7 @@
             p += use_len;
         }
 
-        for( i = 0; i < 16; i++ )
-            ctx->y[i] ^= work_buf[i];
+        mbedtls_xor( ctx->y, ctx->y, work_buf, 16);
 
         gcm_mult( ctx, ctx->y, ctx->y );
     }
@@ -313,7 +310,7 @@
                            const unsigned char *add, size_t add_len )
 {
     const unsigned char *p;
-    size_t use_len, i, offset;
+    size_t use_len, offset;
 
     /* IV is limited to 2^64 bits, so 2^61 bytes */
     if( (uint64_t) add_len >> 61 != 0 )
@@ -328,8 +325,7 @@
         if( use_len > add_len )
             use_len = add_len;
 
-        for( i = 0; i < use_len; i++ )
-            ctx->buf[i+offset] ^= p[i];
+        mbedtls_xor( ctx->buf + offset, ctx->buf + offset, p, use_len );
 
         if( offset + use_len == 16 )
             gcm_mult( ctx, ctx->buf, ctx->buf );
@@ -343,8 +339,7 @@
 
     while( add_len >= 16 )
     {
-        for( i = 0; i < 16; i++ )
-            ctx->buf[i] ^= p[i];
+        mbedtls_xor( ctx->buf, ctx->buf, p, 16 );
 
         gcm_mult( ctx, ctx->buf, ctx->buf );
 
@@ -354,8 +349,7 @@
 
     if( add_len > 0 )
     {
-        for( i = 0; i < add_len; i++ )
-            ctx->buf[i] ^= p[i];
+        mbedtls_xor( ctx->buf, ctx->buf, p, add_len );
     }
 
     return( 0 );
@@ -378,7 +372,6 @@
                      const unsigned char *input,
                      unsigned char *output )
 {
-    size_t i;
     size_t olen = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
@@ -389,14 +382,12 @@
         return( ret );
     }
 
-    for( i = 0; i < use_len; i++ )
-    {
-        if( ctx->mode == MBEDTLS_GCM_DECRYPT )
-            ctx->buf[offset + i] ^= input[i];
-        output[i] = ectr[offset + i] ^ input[i];
-        if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
-            ctx->buf[offset + i] ^= output[i];
-    }
+    if( ctx->mode == MBEDTLS_GCM_DECRYPT )
+        mbedtls_xor( ctx->buf + offset, ctx->buf + offset, input, use_len );
+    mbedtls_xor( output, ectr + offset, input, use_len );
+    if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
+        mbedtls_xor( ctx->buf + offset, ctx->buf + offset, output, use_len );
+
     return( 0 );
 }
 
@@ -489,7 +480,6 @@
                         unsigned char *tag, size_t tag_len )
 {
     unsigned char work_buf[16];
-    size_t i;
     uint64_t orig_len;
     uint64_t orig_add_len;
 
@@ -524,13 +514,11 @@
         MBEDTLS_PUT_UINT32_BE( ( orig_len     >> 32 ), work_buf, 8  );
         MBEDTLS_PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
 
-        for( i = 0; i < 16; i++ )
-            ctx->buf[i] ^= work_buf[i];
+        mbedtls_xor( ctx->buf, ctx->buf, work_buf, 16 );
 
         gcm_mult( ctx, ctx->buf, ctx->buf );
 
-        for( i = 0; i < tag_len; i++ )
-            tag[i] ^= ctx->buf[i];
+        mbedtls_xor( tag, tag, ctx->buf, tag_len );
     }
 
     return( 0 );
diff --git a/library/md.c b/library/md.c
index 8efcf10..9c161a5 100644
--- a/library/md.c
+++ b/library/md.c
@@ -633,7 +633,6 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char sum[MBEDTLS_MD_MAX_SIZE];
     unsigned char *ipad, *opad;
-    size_t i;
 
     if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
@@ -657,11 +656,8 @@
     memset( ipad, 0x36, ctx->md_info->block_size );
     memset( opad, 0x5C, ctx->md_info->block_size );
 
-    for( i = 0; i < keylen; i++ )
-    {
-        ipad[i] = (unsigned char)( ipad[i] ^ key[i] );
-        opad[i] = (unsigned char)( opad[i] ^ key[i] );
-    }
+    mbedtls_xor( ipad, ipad, key, keylen );
+    mbedtls_xor( opad, opad, key, keylen );
 
     if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
         goto cleanup;
diff --git a/library/pkcs5.c b/library/pkcs5.c
index ac5945a..1e3b17e 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -211,7 +211,6 @@
                               uint32_t key_length, unsigned char *output )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    int j;
     unsigned int i;
     unsigned char md1[MBEDTLS_MD_MAX_SIZE];
     unsigned char work[MBEDTLS_MD_MAX_SIZE];
@@ -263,8 +262,7 @@
 
             // U1 xor U2
             //
-            for( j = 0; j < md_size; j++ )
-                work[j] ^= md1[j];
+            mbedtls_xor( work, work, md1, md_size );
         }
 
         use_len = ( key_length < md_size ) ? key_length : md_size;
@@ -324,7 +322,6 @@
     mbedtls_md_free( &md_ctx );
     return( ret );
 #else
-    int j;
     unsigned int i;
     unsigned char md1[PSA_HASH_MAX_SIZE];
     unsigned char work[PSA_HASH_MAX_SIZE];
@@ -396,8 +393,7 @@
 
             // U1 xor U2
             //
-            for( j = 0; j < md_size; j++ )
-                work[j] ^= md1[j];
+            mbedtls_xor( work, work, md1, md_size );
         }
 
         use_len = ( key_length < md_size ) ? key_length : md_size;
diff --git a/library/platform_util.c b/library/platform_util.c
index 916a7f4..2b674f6 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -143,3 +143,20 @@
 void (*mbedtls_test_hook_test_fail)( const char *, int, const char *);
 #endif /* MBEDTLS_TEST_HOOKS */
 
+/*
+ * Provide external definitions of some inline functions so that the compiler
+ * has the option to not inline them
+ */
+extern inline void mbedtls_xor( unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n );
+
+extern inline uint16_t mbedtls_get_unaligned_uint16( const void *p );
+
+extern inline void mbedtls_put_unaligned_uint16( void *p, uint16_t x );
+
+extern inline uint32_t mbedtls_get_unaligned_uint32( const void *p );
+
+extern inline void mbedtls_put_unaligned_uint32( void *p, uint32_t x );
+
+extern inline uint64_t mbedtls_get_unaligned_uint64( const void *p );
+
+extern inline void mbedtls_put_unaligned_uint64( void *p, uint64_t x );
diff --git a/library/psa_crypto_aead.h b/library/psa_crypto_aead.h
index 17b3953..70f714a 100644
--- a/library/psa_crypto_aead.h
+++ b/library/psa_crypto_aead.h
@@ -508,4 +508,4 @@
 psa_status_t mbedtls_psa_aead_abort(
     mbedtls_psa_aead_operation_t *operation );
 
-#endif /* PSA_CRYPTO_AEAD */
+#endif /* PSA_CRYPTO_AEAD_H */
diff --git a/library/psa_crypto_its.h b/library/psa_crypto_its.h
index 3a3f49a..1b8dc20 100644
--- a/library/psa_crypto_its.h
+++ b/library/psa_crypto_its.h
@@ -73,7 +73,7 @@
  * \return      A status indicating the success/failure of the operation
  *
  * \retval      #PSA_SUCCESS                     The operation completed successfully
- * \retval      #PSA_ERROR_NOT_PERMITTED         The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG
+ * \retval      #PSA_ERROR_NOT_PERMITTED         The operation failed because the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE
  * \retval      #PSA_ERROR_NOT_SUPPORTED         The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid
  * \retval      #PSA_ERROR_INSUFFICIENT_STORAGE  The operation failed because there was insufficient space on the storage medium
  * \retval      #PSA_ERROR_STORAGE_FAILURE       The operation failed because the physical storage has failed (Fatal error)
@@ -137,7 +137,7 @@
  *
  * \retval      #PSA_SUCCESS                  The operation completed successfully
  * \retval      #PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided key value was not found in the storage
- * \retval      #PSA_ERROR_NOT_PERMITTED      The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG
+ * \retval      #PSA_ERROR_NOT_PERMITTED      The operation failed because the provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE
  * \retval      #PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
  */
 psa_status_t psa_its_remove(psa_storage_uid_t uid);
diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h
index 197caa8..5835c6f 100644
--- a/library/psa_crypto_rsa.h
+++ b/library/psa_crypto_rsa.h
@@ -249,7 +249,7 @@
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
@@ -306,7 +306,7 @@
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
  * \retval #PSA_ERROR_INVALID_PADDING
  * \retval #PSA_ERROR_BAD_STATE
diff --git a/library/ssl_client.c b/library/ssl_client.c
index 2c4ce43..e838845 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -518,18 +518,22 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS)
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
     {
-        unsigned char cookie_len = 0;
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        uint8_t cookie_len = 0;
+#else
+        uint16_t cookie_len = 0;
+#endif /* !MBEDTLS_SSL_PROTO_TLS1_3 */
 
         if( handshake->cookie != NULL )
         {
             MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
                                    handshake->cookie,
-                                   handshake->verify_cookie_len );
-            cookie_len = handshake->verify_cookie_len;
+                                   handshake->cookie_len );
+            cookie_len = handshake->cookie_len;
         }
 
         MBEDTLS_SSL_CHK_BUF_PTR( p, end, cookie_len + 1 );
-        *p++ = cookie_len;
+        *p++ = ( unsigned char )cookie_len;
         if( cookie_len > 0 )
         {
             memcpy( p, handshake->cookie, cookie_len );
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 0e0479a..8254964 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -846,19 +846,33 @@
     } buffering;
 
 #if defined(MBEDTLS_SSL_CLI_C) && \
-    ( defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3) )
-    unsigned char *cookie;              /*!<  HelloVerifyRequest cookie for DTLS
-                                         *    HelloRetryRequest cookie for TLS 1.3 */
+    ( defined(MBEDTLS_SSL_PROTO_DTLS) || \
+      defined(MBEDTLS_SSL_PROTO_TLS1_3) )
+    unsigned char *cookie;              /*!< HelloVerifyRequest cookie for DTLS
+                                         *   HelloRetryRequest cookie for TLS 1.3 */
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    /* RFC 6347 page 15
+       ...
+       opaque cookie<0..2^8-1>;
+       ...
+     */
+    uint8_t cookie_len;
+#else
+    /* RFC 8446 page 39
+       ...
+       opaque cookie<0..2^16-1>;
+       ...
+       If TLS1_3 is enabled, the max length is 2^16 - 1
+     */
+    uint16_t cookie_len;                /*!< DTLS: HelloVerifyRequest cookie length
+                                         *   TLS1_3: HelloRetryRequest cookie length */
+#endif
 #endif /* MBEDTLS_SSL_CLI_C &&
-          ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    unsigned char verify_cookie_len;    /*!<  Cli: HelloVerifyRequest cookie
-                                         *    length
-                                         *    Srv: flag for sending a cookie */
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    uint16_t hrr_cookie_len;            /*!<  HelloRetryRequest cookie length */
-#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_3 */
+          ( MBEDTLS_SSL_PROTO_DTLS ||
+            MBEDTLS_SSL_PROTO_TLS1_3 ) */
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_DTLS)
+    unsigned char cookie_verify_result; /*!< Srv: flag for sending a cookie */
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     unsigned int out_msg_seq;           /*!<  Outgoing handshake sequence number */
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index e4d50db..753998e 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -669,15 +669,12 @@
                                     unsigned char const *dynamic_iv,
                                     size_t dynamic_iv_len )
 {
-    size_t i;
-
     /* Start with Fixed IV || 0 */
     memset( dst_iv, 0, dst_iv_len );
     memcpy( dst_iv, fixed_iv, fixed_iv_len );
 
     dst_iv += dst_iv_len - dynamic_iv_len;
-    for( i = 0; i < dynamic_iv_len; i++ )
-        dst_iv[i] ^= dynamic_iv[i];
+    mbedtls_xor( dst_iv, dst_iv, dynamic_iv, dynamic_iv_len );
 }
 #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
 
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 9bb9dc2..b757613 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1863,27 +1863,55 @@
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-/*
- * Set EC J-PAKE password for current handshake
- */
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
-                                         const unsigned char *pw,
-                                         size_t pw_len )
-{
-    psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_pake_role_t psa_role;
-    psa_status_t status;
 
-    if( ssl->handshake == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static psa_status_t mbedtls_ssl_set_hs_ecjpake_password_common(
+                                                mbedtls_ssl_context *ssl,
+                                                mbedtls_svc_key_id_t pwd )
+{
+    psa_status_t status;
+    psa_pake_role_t psa_role;
+    psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
+
+    psa_pake_cs_set_algorithm( &cipher_suite, PSA_ALG_JPAKE );
+    psa_pake_cs_set_primitive( &cipher_suite,
+                               PSA_PAKE_PRIMITIVE( PSA_PAKE_PRIMITIVE_TYPE_ECC,
+                                                   PSA_ECC_FAMILY_SECP_R1,
+                                                   256) );
+    psa_pake_cs_set_hash( &cipher_suite, PSA_ALG_SHA_256 );
+
+    status = psa_pake_setup( &ssl->handshake->psa_pake_ctx, &cipher_suite );
+    if( status != PSA_SUCCESS )
+        return status;
 
     if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
         psa_role = PSA_PAKE_ROLE_SERVER;
     else
         psa_role = PSA_PAKE_ROLE_CLIENT;
 
+    status = psa_pake_set_role( &ssl->handshake->psa_pake_ctx, psa_role );
+    if( status != PSA_SUCCESS )
+        return status;
+
+    status = psa_pake_set_password_key( &ssl->handshake->psa_pake_ctx, pwd );
+    if( status != PSA_SUCCESS )
+        return status;
+
+    ssl->handshake->psa_pake_ctx_is_ok = 1;
+
+    return ( PSA_SUCCESS );
+}
+
+int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
+                                         const unsigned char *pw,
+                                         size_t pw_len )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status;
+
+    if( ssl->handshake == NULL || ssl->conf == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
     /* Empty password is not valid  */
     if( ( pw == NULL) || ( pw_len == 0 ) )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -1897,21 +1925,8 @@
     if( status != PSA_SUCCESS )
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
 
-    psa_pake_cs_set_algorithm( &cipher_suite, PSA_ALG_JPAKE );
-    psa_pake_cs_set_primitive( &cipher_suite,
-                               PSA_PAKE_PRIMITIVE( PSA_PAKE_PRIMITIVE_TYPE_ECC,
-                                                   PSA_ECC_FAMILY_SECP_R1,
-                                                   256) );
-    psa_pake_cs_set_hash( &cipher_suite, PSA_ALG_SHA_256 );
-
-    status = psa_pake_setup( &ssl->handshake->psa_pake_ctx, &cipher_suite );
-    if( status != PSA_SUCCESS )
-    {
-        psa_destroy_key( ssl->handshake->psa_pake_password );
-        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-    }
-
-    status = psa_pake_set_role( &ssl->handshake->psa_pake_ctx, psa_role );
+    status = mbedtls_ssl_set_hs_ecjpake_password_common( ssl,
+                                        ssl->handshake->psa_pake_password );
     if( status != PSA_SUCCESS )
     {
         psa_destroy_key( ssl->handshake->psa_pake_password );
@@ -1919,17 +1934,27 @@
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
     }
 
-    psa_pake_set_password_key( &ssl->handshake->psa_pake_ctx,
-                                ssl->handshake->psa_pake_password );
+    return( 0 );
+}
+
+int mbedtls_ssl_set_hs_ecjpake_password_opaque( mbedtls_ssl_context *ssl,
+                                                mbedtls_svc_key_id_t pwd )
+{
+    psa_status_t status;
+
+    if( ssl->handshake == NULL || ssl->conf == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+    if( mbedtls_svc_key_id_is_null( pwd ) )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+    status = mbedtls_ssl_set_hs_ecjpake_password_common( ssl, pwd );
     if( status != PSA_SUCCESS )
     {
-        psa_destroy_key( ssl->handshake->psa_pake_password );
         psa_pake_abort( &ssl->handshake->psa_pake_ctx );
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
     }
 
-    ssl->handshake->psa_pake_ctx_is_ok = 1;
-
     return( 0 );
 }
 #else /* MBEDTLS_USE_PSA_CRYPTO */
@@ -1942,6 +1967,10 @@
     if( ssl->handshake == NULL || ssl->conf == NULL )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
+    /* Empty password is not valid  */
+    if( ( pw == NULL) || ( pw_len == 0 ) )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
     if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
         role = MBEDTLS_ECJPAKE_SERVER;
     else
@@ -3996,7 +4025,15 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_pake_abort( &handshake->psa_pake_ctx );
-    psa_destroy_key( handshake->psa_pake_password );
+    /*
+     * Opaque keys are not stored in the handshake's data and it's the user
+     * responsibility to destroy them. Clear ones, instead, are created by
+     * the TLS library and should be destroyed at the same level
+     */
+    if( ! mbedtls_svc_key_id_is_null( handshake->psa_pake_password ) )
+    {
+        psa_destroy_key( handshake->psa_pake_password );
+    }
     handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT;
 #else
     mbedtls_ecjpake_free( &handshake->ecjpake_ctx );
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index 7a17452..76588d3 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -1137,7 +1137,12 @@
 {
     const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
     uint16_t dtls_legacy_version;
-    unsigned char cookie_len;
+
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    uint8_t cookie_len;
+#else
+    uint16_t cookie_len;
+#endif
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) );
 
@@ -1200,7 +1205,7 @@
     }
 
     memcpy( ssl->handshake->cookie, p, cookie_len );
-    ssl->handshake->verify_cookie_len = cookie_len;
+    ssl->handshake->cookie_len = cookie_len;
 
     /* Start over at ClientHello */
     ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
@@ -1284,7 +1289,7 @@
             /* We made it through the verification process */
             mbedtls_free( ssl->handshake->cookie );
             ssl->handshake->cookie = NULL;
-            ssl->handshake->verify_cookie_len = 0;
+            ssl->handshake->cookie_len = 0;
         }
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index eeb579a..5cdbcc0 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -1274,12 +1274,12 @@
                                      ssl->cli_id, ssl->cli_id_len ) != 0 )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) );
-                ssl->handshake->verify_cookie_len = 1;
+                ssl->handshake->cookie_verify_result = 1;
             }
             else
             {
                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) );
-                ssl->handshake->verify_cookie_len = 0;
+                ssl->handshake->cookie_verify_result = 0;
             }
         }
         else
@@ -2244,7 +2244,7 @@
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake->verify_cookie_len != 0 )
+        ssl->handshake->cookie_verify_result != 0 )
     {
         MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) );
         MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 0109f77..839b954 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -553,7 +553,7 @@
     MBEDTLS_SSL_DEBUG_BUF( 3, "cookie extension", p, cookie_len );
 
     mbedtls_free( handshake->cookie );
-    handshake->hrr_cookie_len = 0;
+    handshake->cookie_len = 0;
     handshake->cookie = mbedtls_calloc( 1, cookie_len );
     if( handshake->cookie == NULL )
     {
@@ -564,7 +564,7 @@
     }
 
     memcpy( handshake->cookie, p, cookie_len );
-    handshake->hrr_cookie_len = cookie_len;
+    handshake->cookie_len = cookie_len;
 
     return( 0 );
 }
@@ -587,21 +587,21 @@
 
     MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
                            handshake->cookie,
-                           handshake->hrr_cookie_len );
+                           handshake->cookie_len );
 
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, handshake->hrr_cookie_len + 6 );
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, handshake->cookie_len + 6 );
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding cookie extension" ) );
 
     MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_COOKIE, p, 0 );
-    MBEDTLS_PUT_UINT16_BE( handshake->hrr_cookie_len + 2, p, 2 );
-    MBEDTLS_PUT_UINT16_BE( handshake->hrr_cookie_len, p, 4 );
+    MBEDTLS_PUT_UINT16_BE( handshake->cookie_len + 2, p, 2 );
+    MBEDTLS_PUT_UINT16_BE( handshake->cookie_len, p, 4 );
     p += 6;
 
     /* Cookie */
-    memcpy( p, handshake->cookie, handshake->hrr_cookie_len );
+    memcpy( p, handshake->cookie, handshake->cookie_len );
 
-    *out_len = handshake->hrr_cookie_len + 6;
+    *out_len = handshake->cookie_len + 6;
 
     mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_COOKIE );
 
diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c
index 1303719..f40874e 100644
--- a/programs/psa/key_ladder_demo.c
+++ b/programs/psa/key_ladder_demo.c
@@ -713,4 +713,6 @@
     usage( );
     return( EXIT_FAILURE );
 }
-#endif /* MBEDTLS_SHA256_C && MBEDTLS_MD_C && MBEDTLS_AES_C && MBEDTLS_CCM_C && MBEDTLS_PSA_CRYPTO_C && MBEDTLS_FS_IO */
+#endif /* MBEDTLS_SHA256_C && MBEDTLS_MD_C &&
+          MBEDTLS_AES_C && MBEDTLS_CCM_C &&
+          MBEDTLS_PSA_CRYPTO_C && MBEDTLS_FS_IO */
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 6aa295d..02ee7cf 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -68,6 +68,7 @@
 #define DFL_PSK_OPAQUE          0
 #define DFL_PSK_IDENTITY        "Client_identity"
 #define DFL_ECJPAKE_PW          NULL
+#define DFL_ECJPAKE_PW_OPAQUE   0
 #define DFL_EC_MAX_OPS          -1
 #define DFL_FORCE_CIPHER        0
 #define DFL_TLS1_3_KEX_MODES    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL
@@ -318,11 +319,17 @@
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
 #define USAGE_ECJPAKE \
-    "    ecjpake_pw=%%s       default: none (disabled)\n"
-#else
+    "    ecjpake_pw=%%s           default: none (disabled)\n"   \
+    "    ecjpake_pw_opaque=%%d    default: 0 (disabled)\n"
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+#define USAGE_ECJPAKE \
+    "    ecjpake_pw=%%s           default: none (disabled)\n"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#else /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 #define USAGE_ECJPAKE ""
-#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
 #define USAGE_ECRESTART \
@@ -492,6 +499,9 @@
     const char *psk;            /* the pre-shared key                       */
     const char *psk_identity;   /* the pre-shared key identity              */
     const char *ecjpake_pw;     /* the EC J-PAKE password                   */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    int ecjpake_pw_opaque;      /* set to 1 to use the opaque method for setting the password */
+#endif
     int ec_max_ops;             /* EC consecutive operations limit          */
     int force_ciphersuite[2];   /* protocol/ciphersuite to use, or all      */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
@@ -824,6 +834,10 @@
         MBEDTLS_TLS_SRTP_UNSET
     };
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_svc_key_id_t ecjpake_pw_slot = MBEDTLS_SVC_KEY_ID_INIT; /* ecjpake password key slot */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -919,6 +933,9 @@
 #endif
     opt.psk_identity        = DFL_PSK_IDENTITY;
     opt.ecjpake_pw          = DFL_ECJPAKE_PW;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    opt.ecjpake_pw_opaque   = DFL_ECJPAKE_PW_OPAQUE;
+#endif
     opt.ec_max_ops          = DFL_EC_MAX_OPS;
     opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
@@ -1094,6 +1111,10 @@
             opt.psk_identity = q;
         else if( strcmp( p, "ecjpake_pw" ) == 0 )
             opt.ecjpake_pw = q;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        else if( strcmp( p, "ecjpake_pw_opaque" ) == 0 )
+            opt.ecjpake_pw_opaque = atoi( q );
+#endif
         else if( strcmp( p, "ec_max_ops" ) == 0 )
             opt.ec_max_ops = atoi( q );
         else if( strcmp( p, "force_ciphersuite" ) == 0 )
@@ -2166,16 +2187,46 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     if( opt.ecjpake_pw != DFL_ECJPAKE_PW )
     {
-        if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,
-                        (const unsigned char *) opt.ecjpake_pw,
-                                        strlen( opt.ecjpake_pw ) ) ) != 0 )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        if ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE )
         {
-            mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n",
-                            ret );
-            goto exit;
+            psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+            psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+            psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE );
+            psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD );
+
+            status = psa_import_key( &attributes,
+                                (const unsigned char *) opt.ecjpake_pw,
+                                strlen( opt.ecjpake_pw ),
+                                &ecjpake_pw_slot );
+            if( status != PSA_SUCCESS )
+            {
+                mbedtls_printf( " failed\n  ! psa_import_key returned %d\n\n",
+                            status );
+                goto exit;
+            }
+            if( ( ret = mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl,
+                                        ecjpake_pw_slot ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hs_ecjpake_password_opaque returned %d\n\n", ret );
+                goto exit;
+            }
+            mbedtls_printf( "using opaque password\n");
+        }
+        else
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
+        {
+            if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,
+                                        (const unsigned char *) opt.ecjpake_pw,
+                                        strlen( opt.ecjpake_pw ) ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret );
+                goto exit;
+            }
         }
     }
-#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
     if( opt.context_crt_cb == 1 )
@@ -3276,6 +3327,31 @@
 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED &&
           MBEDTLS_USE_PSA_CRYPTO */
 
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+    /*
+     * In case opaque keys it's the user responsibility to keep the key valid
+     * for the duration of the handshake and destroy it at the end
+     */
+    if( ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE ) )
+    {
+        psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+        /* Verify that the key is still valid before destroying it */
+        if( psa_get_key_attributes( ecjpake_pw_slot, &check_attributes ) !=
+                PSA_SUCCESS )
+        {
+            if( ret == 0 )
+                ret = 1;
+            mbedtls_printf( "The EC J-PAKE password key has unexpectedly been already destroyed\n" );
+        }
+        else
+        {
+            psa_destroy_key( ecjpake_pw_slot );
+        }
+    }
+#endif  /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO */
+
 #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
     const char* message = mbedtls_test_helper_is_psa_leaking();
     if( message )
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 00624b5..802beb2 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -98,6 +98,7 @@
 #define DFL_PSK_LIST_OPAQUE     0
 #define DFL_PSK_IDENTITY        "Client_identity"
 #define DFL_ECJPAKE_PW          NULL
+#define DFL_ECJPAKE_PW_OPAQUE   0
 #define DFL_PSK_LIST            NULL
 #define DFL_FORCE_CIPHER        0
 #define DFL_TLS1_3_KEX_MODES    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL
@@ -419,11 +420,17 @@
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
 #define USAGE_ECJPAKE \
-    "    ecjpake_pw=%%s       default: none (disabled)\n"
-#else
+    "    ecjpake_pw=%%s           default: none (disabled)\n"   \
+    "    ecjpake_pw_opaque=%%d    default: 0 (disabled)\n"
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+#define USAGE_ECJPAKE \
+    "    ecjpake_pw=%%s           default: none (disabled)\n"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#else /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 #define USAGE_ECJPAKE ""
-#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
 #define USAGE_EARLY_DATA \
@@ -631,6 +638,9 @@
     const char *psk_identity;   /* the pre-shared key identity              */
     char *psk_list;             /* list of PSK id/key pairs for callback    */
     const char *ecjpake_pw;     /* the EC J-PAKE password                   */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    int ecjpake_pw_opaque;      /* set to 1 to use the opaque method for setting the password */
+#endif
     int force_ciphersuite[2];   /* protocol/ciphersuite to use, or all      */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     int tls13_kex_modes;        /* supported TLS 1.3 key exchange modes     */
@@ -1517,6 +1527,10 @@
     unsigned char *context_buf = NULL;
     size_t context_buf_len = 0;
 #endif
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_svc_key_id_t ecjpake_pw_slot = MBEDTLS_SVC_KEY_ID_INIT; /* ecjpake password key slot */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
     uint16_t sig_alg_list[SIG_ALG_LIST_SIZE];
@@ -1675,6 +1689,9 @@
     opt.psk_identity        = DFL_PSK_IDENTITY;
     opt.psk_list            = DFL_PSK_LIST;
     opt.ecjpake_pw          = DFL_ECJPAKE_PW;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    opt.ecjpake_pw_opaque   = DFL_ECJPAKE_PW_OPAQUE;
+#endif
     opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     opt.tls13_kex_modes     = DFL_TLS1_3_KEX_MODES;
@@ -1879,6 +1896,10 @@
             opt.psk_list = q;
         else if( strcmp( p, "ecjpake_pw" ) == 0 )
             opt.ecjpake_pw = q;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        else if( strcmp( p, "ecjpake_pw_opaque" ) == 0 )
+            opt.ecjpake_pw_opaque = atoi( q );
+#endif
         else if( strcmp( p, "force_ciphersuite" ) == 0 )
         {
             opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q );
@@ -3528,15 +3549,46 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     if( opt.ecjpake_pw != DFL_ECJPAKE_PW )
     {
-        if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,
-                        (const unsigned char *) opt.ecjpake_pw,
-                                        strlen( opt.ecjpake_pw ) ) ) != 0 )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        if ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE )
         {
-            mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret );
-            goto exit;
+            psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+            psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+            psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE );
+            psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD );
+
+            status = psa_import_key( &attributes,
+                                (const unsigned char *) opt.ecjpake_pw,
+                                strlen( opt.ecjpake_pw ),
+                                &ecjpake_pw_slot );
+            if( status != PSA_SUCCESS )
+            {
+                mbedtls_printf( " failed\n  ! psa_import_key returned %d\n\n",
+                            status );
+                goto exit;
+            }
+            if( ( ret = mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl,
+                                        ecjpake_pw_slot ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hs_ecjpake_password_opaque returned %d\n\n", ret );
+                goto exit;
+            }
+            mbedtls_printf( "using opaque password\n");
+        }
+        else
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
+        {
+            if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,
+                                        (const unsigned char *) opt.ecjpake_pw,
+                                        strlen( opt.ecjpake_pw ) ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret );
+                goto exit;
+            }
         }
     }
-#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
 #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
@@ -4422,6 +4474,31 @@
 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED &&
           MBEDTLS_USE_PSA_CRYPTO */
 
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+    /*
+     * In case opaque keys it's the user responsibility to keep the key valid
+     * for the duration of the handshake and destroy it at the end
+     */
+    if( ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE ) )
+    {
+        psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+        /* Verify that the key is still valid before destroying it */
+        if( psa_get_key_attributes( ecjpake_pw_slot, &check_attributes ) !=
+                PSA_SUCCESS )
+        {
+            if( ret == 0 )
+                ret = 1;
+            mbedtls_printf( "The EC J-PAKE password key has unexpectedly been already destroyed\n" );
+        }
+        else
+        {
+            psa_destroy_key( ecjpake_pw_slot );
+        }
+    }
+#endif  /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO */
+
 #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
     const char* message = mbedtls_test_helper_is_psa_leaking();
     if( message )
diff --git a/programs/test/cmake_package_install/CMakeLists.txt b/programs/test/cmake_package_install/CMakeLists.txt
index 711a1e5..fb5ad51 100644
--- a/programs/test/cmake_package_install/CMakeLists.txt
+++ b/programs/test/cmake_package_install/CMakeLists.txt
@@ -26,7 +26,7 @@
 # Locate the package.
 #
 
-set(MbedTLS_DIR "${MbedTLS_INSTALL_DIR}/cmake")
+list(INSERT CMAKE_PREFIX_PATH 0 "${MbedTLS_INSTALL_DIR}")
 find_package(MbedTLS REQUIRED)
 
 #
diff --git a/scripts/code_style.py b/scripts/code_style.py
new file mode 100755
index 0000000..68cd556
--- /dev/null
+++ b/scripts/code_style.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+"""Check or fix the code style by running Uncrustify.
+
+Note: The code style enforced by this script is not yet introduced to
+Mbed TLS. At present this script will only be used to prepare for a future
+change of code style.
+"""
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import argparse
+import io
+import os
+import subprocess
+import sys
+from typing import List
+
+UNCRUSTIFY_SUPPORTED_VERSION = "0.75.1"
+CONFIG_FILE = ".uncrustify.cfg"
+UNCRUSTIFY_EXE = "uncrustify"
+UNCRUSTIFY_ARGS = ["-c", CONFIG_FILE]
+STDOUT_UTF8 = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
+STDERR_UTF8 = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
+
+def print_err(*args):
+    print("Error: ", *args, file=STDERR_UTF8)
+
+def get_src_files() -> List[str]:
+    """
+    Use git ls-files to get a list of the source files
+    """
+    git_ls_files_cmd = ["git", "ls-files",
+                        "*.[hc]",
+                        "tests/suites/*.function",
+                        "scripts/data_files/*.fmt"]
+
+    result = subprocess.run(git_ls_files_cmd, stdout=subprocess.PIPE, \
+            stderr=STDERR_UTF8, check=False)
+
+    if result.returncode != 0:
+        print_err("git ls-files returned: " + str(result.returncode))
+        return []
+    else:
+        src_files = str(result.stdout, "utf-8").split()
+        # Don't correct style for files in 3rdparty/
+        src_files = list(filter( \
+                lambda filename: not filename.startswith("3rdparty/"), \
+                src_files))
+        return src_files
+
+def get_uncrustify_version() -> str:
+    """
+    Get the version string from Uncrustify
+    """
+    result = subprocess.run([UNCRUSTIFY_EXE, "--version"], \
+            stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
+    if result.returncode != 0:
+        print_err("Could not get Uncrustify version:", str(result.stderr, "utf-8"))
+        return ""
+    else:
+        return str(result.stdout, "utf-8")
+
+def check_style_is_correct(src_file_list: List[str]) -> bool:
+    """
+    Check the code style and output a diff for each file whose style is
+    incorrect.
+    """
+    style_correct = True
+    for src_file in src_file_list:
+        uncrustify_cmd = [UNCRUSTIFY_EXE] + UNCRUSTIFY_ARGS + [src_file]
+        subprocess.run(uncrustify_cmd, stdout=subprocess.PIPE, \
+                stderr=subprocess.PIPE, check=False)
+
+        # Uncrustify makes changes to the code and places the result in a new
+        # file with the extension ".uncrustify". To get the changes (if any)
+        # simply diff the 2 files.
+        diff_cmd = ["diff", "-u", src_file, src_file + ".uncrustify"]
+        result = subprocess.run(diff_cmd, stdout=subprocess.PIPE, \
+                stderr=STDERR_UTF8, check=False)
+        if len(result.stdout) > 0:
+            print(src_file + " - Incorrect code style.", file=STDOUT_UTF8)
+            print("File changed - diff:", file=STDOUT_UTF8)
+            print(str(result.stdout, "utf-8"), file=STDOUT_UTF8)
+            style_correct = False
+        else:
+            print(src_file + " - OK.", file=STDOUT_UTF8)
+
+        # Tidy up artifact
+        os.remove(src_file + ".uncrustify")
+
+    return style_correct
+
+def fix_style_single_pass(src_file_list: List[str]) -> None:
+    """
+    Run Uncrustify once over the source files.
+    """
+    code_change_args = UNCRUSTIFY_ARGS + ["--no-backup"]
+    for src_file in src_file_list:
+        uncrustify_cmd = [UNCRUSTIFY_EXE] + code_change_args + [src_file]
+        subprocess.run(uncrustify_cmd, check=False, stdout=STDOUT_UTF8, \
+                stderr=STDERR_UTF8)
+
+def fix_style(src_file_list: List[str]) -> int:
+    """
+    Fix the code style. This takes 2 passes of Uncrustify.
+    """
+    fix_style_single_pass(src_file_list)
+    fix_style_single_pass(src_file_list)
+
+    # Guard against future changes that cause the codebase to require
+    # more passes.
+    if not check_style_is_correct(src_file_list):
+        print("Code style still incorrect after second run of Uncrustify.")
+        return 1
+    else:
+        return 0
+
+def main() -> int:
+    """
+    Main with command line arguments.
+    """
+    uncrustify_version = get_uncrustify_version().strip()
+    if UNCRUSTIFY_SUPPORTED_VERSION not in uncrustify_version:
+        print("Warning: Using unsupported Uncrustify version '" \
+                + uncrustify_version + "' (Note: The only supported version" \
+                "is " + UNCRUSTIFY_SUPPORTED_VERSION + ")", file=STDOUT_UTF8)
+
+    src_files = get_src_files()
+
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-f', '--fix', action='store_true', \
+            help='modify source files to fix the code style')
+
+    args = parser.parse_args()
+
+    if args.fix:
+        # Fix mode
+        return fix_style(src_files)
+    else:
+        # Check mode
+        if check_style_is_correct(src_files):
+            return 0
+        else:
+            return 1
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
index 3ad92aa..e716e40 100644
--- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
+++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
@@ -291,7 +291,7 @@
                     alg, hash, hash_length,
                     signature, signature_size, signature_length ) );
     }
-#endif /* PSA_CRYPTO_SE_C */
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_location_t location =
@@ -375,7 +375,7 @@
                     alg, hash, hash_length,
                     signature, signature_length ) );
     }
-#endif /* PSA_CRYPTO_SE_C */
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_location_t location =
@@ -647,7 +647,7 @@
 
         return( PSA_SUCCESS );
     }
-#endif /* PSA_CRYPTO_SE_C */
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     switch( location )
     {
@@ -715,7 +715,7 @@
                      *( (psa_key_slot_number_t *)key_buffer ),
                      data, data_size, data_length ) );
     }
-#endif /* PSA_CRYPTO_SE_C */
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     switch( location )
     {
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
index 3ff8b2f..0339b1a 100644
--- a/scripts/mbedtls_dev/bignum_common.py
+++ b/scripts/mbedtls_dev/bignum_common.py
@@ -99,6 +99,7 @@
     limb_sizes = [32, 64] # type: List[int]
     arities = [1, 2]
     arity = 2
+    suffix = False   # for arity = 1, symbol can be prefix (default) or suffix
 
     def __init__(self, val_a: str, val_b: str = "0", bits_in_limb: int = 32) -> None:
         self.val_a = val_a
@@ -170,7 +171,8 @@
         """
         if not self.case_description:
             if self.arity == 1:
-                self.case_description = "{} {:x}".format(
+                format_string = "{1:x} {0}" if self.suffix else "{0} {1:x}"
+                self.case_description = format_string.format(
                     self.symbol, self.int_a
                 )
             elif self.arity == 2:
diff --git a/scripts/mbedtls_dev/bignum_data.py b/scripts/mbedtls_dev/bignum_data.py
index e6ed300..9658933 100644
--- a/scripts/mbedtls_dev/bignum_data.py
+++ b/scripts/mbedtls_dev/bignum_data.py
@@ -90,8 +90,8 @@
                               "4708d9893a973000b54a23020fc5b043d6e4a51519d9c9cc"
                               "52d32377e78131c1")
 
-# Adding 192 bit and 1024 bit numbers because these are the shortest required
-# for ECC and RSA respectively.
+# Adding 192 bit and 1024 bit numbers because these are the shortest required
+# for ECC and RSA respectively.
 INPUTS_DEFAULT = [
         "0", "1", # corner cases
         "2", "3", # small primes
@@ -110,13 +110,21 @@
 # supported for now.
 MODULI_DEFAULT = [
         "53", # safe prime
-        "45", # non-prime
+        "45", # non-prime
         SAFE_PRIME_192_BIT_SEED_1,  # safe prime
         RANDOM_192_BIT_SEED_2_NO4,  # not a prime
         SAFE_PRIME_1024_BIT_SEED_3, # safe prime
         RANDOM_1024_BIT_SEED_4_NO5, # not a prime
         ]
 
+# Some functions, e.g. mbedtls_mpi_mod_raw_inv_prime(), only support prime moduli.
+ONLY_PRIME_MODULI = [
+        "53", # safe prime
+        "8ac72304057392b5",     # 9999999997777777333 (longer, not safe, prime)
+        SAFE_PRIME_192_BIT_SEED_1,  # safe prime
+        SAFE_PRIME_1024_BIT_SEED_3, # safe prime
+        ]
+
 def __gen_safe_prime(bits, seed):
     '''
     Generate a safe prime.
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
index d05479a..6fc4c91 100644
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ b/scripts/mbedtls_dev/bignum_mod_raw.py
@@ -18,6 +18,7 @@
 
 from . import test_data_generation
 from . import bignum_common
+from .bignum_data import ONLY_PRIME_MODULI
 
 class BignumModRawTarget(test_data_generation.BaseTarget):
     #pylint: disable=abstract-method, too-few-public-methods
@@ -53,6 +54,34 @@
 
 # BEGIN MERGE SLOT 3
 
+class BignumModRawInvPrime(bignum_common.ModOperationCommon,
+                           BignumModRawTarget):
+    """Test cases for bignum mpi_mod_raw_inv_prime()."""
+    moduli = ONLY_PRIME_MODULI
+    symbol = "^ -1"
+    test_function = "mpi_mod_raw_inv_prime"
+    test_name = "mbedtls_mpi_mod_raw_inv_prime (Montgomery form only)"
+    input_style = "fixed"
+    arity = 1
+    suffix = True
+
+    @property
+    def is_valid(self) -> bool:
+        return self.int_a > 0 and self.int_a < self.int_n
+
+    @property
+    def arg_a(self) -> str:
+        # Input has to be given in Montgomery form
+        mont_a = self.to_montgomery(self.int_a)
+        return self.format_arg('{:x}'.format(mont_a))
+
+    def result(self) -> List[str]:
+        result = bignum_common.invmod(self.int_a, self.int_n)
+        if result < 0:
+            result += self.int_n
+        mont_result = self.to_montgomery(result)
+        return [self.format_result(mont_result)]
+
 # END MERGE SLOT 3
 
 # BEGIN MERGE SLOT 4
@@ -108,7 +137,18 @@
         result = self.from_montgomery(self.int_a)
         return [self.format_result(result)]
 
+class BignumModRawModNegate(bignum_common.ModOperationCommon,
+                            BignumModRawTarget):
+    """ Test cases for mpi_mod_raw_neg(). """
+    test_function = "mpi_mod_raw_neg"
+    test_name = "Modular negation: "
+    symbol = "-"
+    input_style = "arch_split"
+    arity = 1
 
+    def result(self) -> List[str]:
+        result = (self.int_n - self.int_a) % self.int_n
+        return [self.format_result(result)]
 # END MERGE SLOT 7
 
 # BEGIN MERGE SLOT 8
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index cadedb1..cc630ce 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -185,7 +185,8 @@
     export CTEST_OUTPUT_ON_FAILURE=1
 
     # CFLAGS and LDFLAGS for Asan builds that don't use CMake
-    ASAN_CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all'
+    # default to -O2, use -Ox _after_ this if you want another level
+    ASAN_CFLAGS='-O2 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all'
 
     # Gather the list of available components. These are the functions
     # defined in this script whose name starts with "component_".
@@ -1456,10 +1457,14 @@
     make -C programs ssl/ssl_server2 ssl/ssl_client2
     make -C programs test/udp_proxy test/query_compile_time_config
 
-    msg "test: server w/o USE_PSA - client w/ USE_PSA"
-    P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f ECJPAKE
-    msg "test: client w/o USE_PSA - server w/ USE_PSA"
-    P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f ECJPAKE
+    msg "test: server w/o USE_PSA - client w/ USE_PSA, text password"
+    P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: working, TLS"
+    msg "test: server w/o USE_PSA - client w/ USE_PSA, opaque password"
+    P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: opaque password client only, working, TLS"
+    msg "test: client w/o USE_PSA - server w/ USE_PSA, text password"
+    P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: working, TLS"
+    msg "test: client w/o USE_PSA - server w/ USE_PSA, opaque password"
+    P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: opaque password server only, working, TLS"
 
     rm s2_no_use_psa c2_no_use_psa
 }
@@ -2208,11 +2213,16 @@
     msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
     make test
 
+    # This is mostly useful so that we can later compare outcome files with
+    # the reference config in analyze_outcomes.py, to check that the
+    # dependency declarations in ssl-opt.sh and in TLS code are correct.
     msg "test: ssl-opt.sh, MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
     tests/ssl-opt.sh
 
-    msg "test: compat.sh, MBEDTLS_PSA_CRYPTO_CONFIG without accelerated hash and USE_PSA"
-    tests/compat.sh
+    # This is to make sure all ciphersuites are exercised, but we don't need
+    # interop testing (besides, we already got some from ssl-opt.sh).
+    msg "test: compat.sh, MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
+    tests/compat.sh -p mbedTLS -V YES
 }
 
 # This component provides reference configuration for test_psa_crypto_config_accel_hash_use_psa
@@ -3662,6 +3672,26 @@
     [ "$ver_major" -eq 3 ] && [ "$ver_minor" -ge 10 ]
 }
 
+component_test_corrected_code_style () {
+    ./scripts/code_style.py --fix
+
+    msg "build: make, default config (out-of-box), corrected code style"
+    make
+
+    msg "test: main suites make, default config (out-of-box), corrected code style"
+    make test
+
+    # Clean up code-style corrections
+    git checkout -- .
+}
+
+support_test_corrected_code_style() {
+    case $(uncrustify --version) in
+        *0.75.1*) true;;
+        *) false;;
+    esac
+}
+
 component_check_python_files () {
     msg "Lint: Python scripts"
     tests/scripts/check-python-files.sh
diff --git a/tests/scripts/check_names.py b/tests/scripts/check_names.py
index 920537e..13b6c2d 100755
--- a/tests/scripts/check_names.py
+++ b/tests/scripts/check_names.py
@@ -36,7 +36,7 @@
   declared in the header files. This uses the nm command.
 - All macros, constants, and identifiers (function names, struct names, etc)
   follow the required regex pattern.
-- Typo checking: All words that begin with MBED exist as macros or constants.
+- Typo checking: All words that begin with MBED|PSA exist as macros or constants.
 
 The script returns 0 on success, 1 on test failure, and 2 if there is a script
 error. It must be run from Mbed TLS root.
@@ -191,11 +191,12 @@
 
 class Typo(Problem): # pylint: disable=too-few-public-methods
     """
-    A problem that occurs when a word using MBED doesn't appear to be defined as
-    constants nor enum values. Created with NameCheck.check_for_typos()
+    A problem that occurs when a word using MBED or PSA doesn't
+    appear to be defined as constants nor enum values. Created with
+    NameCheck.check_for_typos()
 
     Fields:
-    * match: the Match object of the MBED name in question.
+    * match: the Match object of the MBED|PSA name in question.
     """
     def __init__(self, match):
         self.match = match
@@ -245,7 +246,7 @@
             .format(str(self.excluded_files))
         )
 
-        all_macros = {"public": [], "internal": []}
+        all_macros = {"public": [], "internal": [], "private":[]}
         all_macros["public"] = self.parse_macros([
             "include/mbedtls/*.h",
             "include/psa/*.h",
@@ -256,9 +257,14 @@
             "library/*.h",
             "tests/include/test/drivers/*.h",
         ])
+        all_macros["private"] = self.parse_macros([
+            "library/*.c",
+        ])
         enum_consts = self.parse_enum_consts([
             "include/mbedtls/*.h",
+            "include/psa/*.h",
             "library/*.h",
+            "library/*.c",
             "3rdparty/everest/include/everest/everest.h",
             "3rdparty/everest/include/everest/x25519.h"
         ])
@@ -269,7 +275,7 @@
             "3rdparty/everest/include/everest/everest.h",
             "3rdparty/everest/include/everest/x25519.h"
         ])
-        mbed_words = self.parse_mbed_words([
+        mbed_psa_words = self.parse_mbed_psa_words([
             "include/mbedtls/*.h",
             "include/psa/*.h",
             "library/*.h",
@@ -302,10 +308,11 @@
         return {
             "public_macros": actual_macros["public"],
             "internal_macros": actual_macros["internal"],
+            "private_macros": all_macros["private"],
             "enum_consts": enum_consts,
             "identifiers": identifiers,
             "symbols": symbols,
-            "mbed_words": mbed_words
+            "mbed_psa_words": mbed_psa_words
         }
 
     def is_file_excluded(self, path, exclude_wildcards):
@@ -373,25 +380,28 @@
 
         return macros
 
-    def parse_mbed_words(self, include, exclude=None):
+    def parse_mbed_psa_words(self, include, exclude=None):
         """
-        Parse all words in the file that begin with MBED, in and out of macros,
-        comments, anything.
+        Parse all words in the file that begin with MBED|PSA, in and out of
+        macros, comments, anything.
 
         Args:
         * include: A List of glob expressions to look for files through.
         * exclude: A List of glob expressions for excluding files.
 
-        Returns a List of Match objects for words beginning with MBED.
+        Returns a List of Match objects for words beginning with MBED|PSA.
         """
         # Typos of TLS are common, hence the broader check below than MBEDTLS.
-        mbed_regex = re.compile(r"\bMBED.+?_[A-Z0-9_]*")
+        mbed_regex = re.compile(r"\b(MBED.+?|PSA)_[A-Z0-9_]*")
         exclusions = re.compile(r"// *no-check-names|#error")
 
         files = self.get_files(include, exclude)
-        self.log.debug("Looking for MBED words in {} files".format(len(files)))
+        self.log.debug(
+            "Looking for MBED|PSA words in {} files"
+            .format(len(files))
+        )
 
-        mbed_words = []
+        mbed_psa_words = []
         for filename in files:
             with open(filename, "r", encoding="utf-8") as fp:
                 for line_no, line in enumerate(fp):
@@ -399,14 +409,14 @@
                         continue
 
                     for name in mbed_regex.finditer(line):
-                        mbed_words.append(Match(
+                        mbed_psa_words.append(Match(
                             filename,
                             line,
                             line_no,
                             name.span(0),
                             name.group(0)))
 
-        return mbed_words
+        return mbed_psa_words
 
     def parse_enum_consts(self, include, exclude=None):
         """
@@ -832,12 +842,14 @@
             for match
             in self.parse_result["public_macros"] +
             self.parse_result["internal_macros"] +
+            self.parse_result["private_macros"] +
             self.parse_result["enum_consts"]
             }
         typo_exclusion = re.compile(r"XXX|__|_$|^MBEDTLS_.*CONFIG_FILE$|"
-                                    r"MBEDTLS_TEST_LIBTESTDRIVER*")
+                                    r"MBEDTLS_TEST_LIBTESTDRIVER*|"
+                                    r"PSA_CRYPTO_DRIVER_TEST")
 
-        for name_match in self.parse_result["mbed_words"]:
+        for name_match in self.parse_result["mbed_psa_words"]:
             found = name_match.name in all_caps_names
 
             # Since MBEDTLS_PSA_ACCEL_XXX defines are defined by the
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 1fe8bae..ea57b25 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -7986,6 +7986,8 @@
             -C "found ecjpake_kkpp extension" \
             -s "SSL - The handshake negotiation failed"
 
+# Note: if the name of this test is changed, then please adjust the corresponding
+#       filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh")
 requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ECJPAKE: working, TLS" \
@@ -8004,6 +8006,73 @@
             -S "SSL - The handshake negotiation failed" \
             -S "SSL - Verification of the message MAC failed"
 
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "ECJPAKE: opaque password client+server, working, TLS" \
+            "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \
+            "$P_CLI debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1\
+             force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \
+            0 \
+            -c "add ciphersuite: c0ff" \
+            -c "adding ecjpake_kkpp extension" \
+            -c "using opaque password" \
+            -s "using opaque password" \
+            -C "re-using cached ecjpake parameters" \
+            -s "found ecjpake kkpp extension" \
+            -S "skip ecjpake kkpp extension" \
+            -S "ciphersuite mismatch: ecjpake not configured" \
+            -s "server hello, ecjpake kkpp extension" \
+            -c "found ecjpake_kkpp extension" \
+            -S "SSL - The handshake negotiation failed" \
+            -S "SSL - Verification of the message MAC failed"
+
+# Note: if the name of this test is changed, then please adjust the corresponding
+#       filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh")
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "ECJPAKE: opaque password client only, working, TLS" \
+            "$P_SRV debug_level=3 ecjpake_pw=bla" \
+            "$P_CLI debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1\
+             force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \
+            0 \
+            -c "add ciphersuite: c0ff" \
+            -c "adding ecjpake_kkpp extension" \
+            -c "using opaque password" \
+            -S "using opaque password" \
+            -C "re-using cached ecjpake parameters" \
+            -s "found ecjpake kkpp extension" \
+            -S "skip ecjpake kkpp extension" \
+            -S "ciphersuite mismatch: ecjpake not configured" \
+            -s "server hello, ecjpake kkpp extension" \
+            -c "found ecjpake_kkpp extension" \
+            -S "SSL - The handshake negotiation failed" \
+            -S "SSL - Verification of the message MAC failed"
+
+# Note: if the name of this test is changed, then please adjust the corresponding
+#       filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh")
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "ECJPAKE: opaque password server only, working, TLS" \
+            "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \
+            "$P_CLI debug_level=3 ecjpake_pw=bla\
+             force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \
+            0 \
+            -c "add ciphersuite: c0ff" \
+            -c "adding ecjpake_kkpp extension" \
+            -C "using opaque password" \
+            -s "using opaque password" \
+            -C "re-using cached ecjpake parameters" \
+            -s "found ecjpake kkpp extension" \
+            -S "skip ecjpake kkpp extension" \
+            -S "ciphersuite mismatch: ecjpake not configured" \
+            -s "server hello, ecjpake kkpp extension" \
+            -c "found ecjpake_kkpp extension" \
+            -S "SSL - The handshake negotiation failed" \
+            -S "SSL - Verification of the message MAC failed"
+
 server_needs_more_time 1
 requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
@@ -8015,6 +8084,20 @@
             -C "re-using cached ecjpake parameters" \
             -s "SSL - Verification of the message MAC failed"
 
+server_needs_more_time 1
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "ECJPAKE_OPAQUE_PW: opaque password mismatch, TLS" \
+            "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \
+            "$P_CLI debug_level=3 ecjpake_pw=bad ecjpake_pw_opaque=1 \
+             force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \
+            1 \
+            -c "using opaque password" \
+            -s "using opaque password" \
+            -C "re-using cached ecjpake parameters" \
+            -s "SSL - Verification of the message MAC failed"
+
 requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ECJPAKE: working, DTLS" \
diff --git a/tests/suites/test_suite_alignment.data b/tests/suites/test_suite_alignment.data
new file mode 100644
index 0000000..8c0c21d
--- /dev/null
+++ b/tests/suites/test_suite_alignment.data
@@ -0,0 +1,119 @@
+Aligned 16-bit access
+mbedtls_unaligned_access:16:0
+
+Aligned 32-bit access
+mbedtls_unaligned_access:32:0
+
+Aligned 64-bit access
+mbedtls_unaligned_access:64:0
+
+Unaligned 16-bit access offset=1
+mbedtls_unaligned_access:16:1
+
+Unaligned 32-bit access offset=1
+mbedtls_unaligned_access:32:1
+
+Unaligned 64-bit access offset=1
+mbedtls_unaligned_access:64:1
+
+Unaligned 16-bit access offset=4
+mbedtls_unaligned_access:16:4
+
+Unaligned 32-bit access offset=4
+mbedtls_unaligned_access:32:4
+
+Unaligned 64-bit access offset=4
+mbedtls_unaligned_access:64:4
+
+Unaligned 16-bit access offset=7
+mbedtls_unaligned_access:16:7
+
+Unaligned 32-bit access offset=7
+mbedtls_unaligned_access:32:7
+
+Unaligned 64-bit access offset=7
+mbedtls_unaligned_access:64:7
+
+Unaligned 16-bit access offset=8
+mbedtls_unaligned_access:16:8
+
+Unaligned 32-bit access offset=8
+mbedtls_unaligned_access:32:8
+
+Unaligned 64-bit access offset=8
+mbedtls_unaligned_access:64:8
+
+Byteswap 16
+mbedtls_byteswap:"0100":16:"0001"
+
+Byteswap 16 with truncation
+mbedtls_byteswap:"0706050403020100":16:"0001"
+
+Byteswap 16 all-zero
+mbedtls_byteswap:"0000":16:"0000"
+
+Byteswap 16 all-ones
+mbedtls_byteswap:"ffffffffffffffff":16:"ffff"
+
+Byteswap 32
+mbedtls_byteswap:"03020100":32:"00010203"
+
+Byteswap 32 with truncation
+mbedtls_byteswap:"0706050403020100":32:"00010203"
+
+Byteswap 32 all-zero
+mbedtls_byteswap:"00000000":32:"00000000"
+
+Byteswap 32 all-ones
+mbedtls_byteswap:"ffffffffffffffff":32:"ffffffff"
+
+Byteswap 64
+mbedtls_byteswap:"0706050403020100":64:"01020304050607"
+
+Byteswap 64 all-zero
+mbedtls_byteswap:"0000000000000000":64:"0000000000000000"
+
+Byteswap 64 all-ones
+mbedtls_byteswap:"ffffffffffffffff":64:"ffffffffffffffff"
+
+Get individual bytes
+get_byte
+
+Endian-aware unaligned 16-bit BE offset=0
+unaligned_access_endian_aware:16:0:1
+
+Endian-aware unaligned 16-bit BE offset=3
+unaligned_access_endian_aware:16:3:1
+
+Endian-aware unaligned 16-bit LE offset=0
+unaligned_access_endian_aware:16:0:0
+
+Endian-aware unaligned 16-bit LE offset=3
+unaligned_access_endian_aware:16:3:0
+
+Endian-aware unaligned 32-bit BE offset=0
+unaligned_access_endian_aware:32:0:1
+
+Endian-aware unaligned 32-bit BE offset=3
+unaligned_access_endian_aware:32:3:1
+
+Endian-aware unaligned 32-bit LE offset=0
+unaligned_access_endian_aware:32:0:0
+
+Endian-aware unaligned 32-bit LE offset=3
+unaligned_access_endian_aware:32:3:0
+
+Endian-aware unaligned 64-bit BE offset=0
+unaligned_access_endian_aware:64:0:1
+
+Endian-aware unaligned 64-bit BE offset=3
+unaligned_access_endian_aware:64:3:1
+
+Endian-aware unaligned 64-bit LE offset=0
+unaligned_access_endian_aware:64:0:0
+
+Endian-aware unaligned 64-bit LE offset=3
+unaligned_access_endian_aware:64:3:0
+
+Big-endian check
+mbedtls_is_big_endian
diff --git a/tests/suites/test_suite_alignment.function b/tests/suites/test_suite_alignment.function
new file mode 100644
index 0000000..06c5668
--- /dev/null
+++ b/tests/suites/test_suite_alignment.function
@@ -0,0 +1,407 @@
+/* BEGIN_HEADER */
+#include "../library/alignment.h"
+
+#include <stdint.h>
+
+#if defined(__clang__)
+#pragma clang diagnostic ignored "-Wunreachable-code"
+#endif
+#include <stdio.h>
+
+/*
+ * Convert a string of the form "abcd" (case-insensitive) to a uint64_t.
+ */
+int parse_hex_string( char* hex_string, uint64_t *result )
+{
+    uint8_t raw[8];
+    size_t olen;
+    if ( mbedtls_test_unhexify(raw, sizeof(raw), hex_string, &olen) != 0 ) return 0;
+    *result = 0;
+    for ( size_t i = 0; i < olen; i++ )
+    {
+        if ( MBEDTLS_IS_BIG_ENDIAN ) {
+            *result |= ((uint64_t)raw[i]) << ( i * 8 );
+        }
+        else
+        {
+            *result |= ((uint64_t)raw[i]) << ( (olen - i - 1) * 8 );
+        }
+    }
+    return 1;
+}
+
+/* END_HEADER */
+
+/* BEGIN_CASE */
+void mbedtls_unaligned_access( int size, int offset )
+{
+    /* Define 64-bit aligned raw byte array */
+    uint64_t raw[2];
+
+    /* Populate with known data */
+    uint8_t *x = (uint8_t *) raw;
+    for ( size_t i = 0; i < sizeof(raw); i++ )
+        x[i] = (uint8_t)i;
+
+    TEST_ASSERT( size == 16 || size == 32 || size == 64 );
+
+    uint64_t r = 0;
+    switch ( size )
+    {
+        case 16:
+            r = mbedtls_get_unaligned_uint16( x + offset );
+            break;
+        case 32:
+            r = mbedtls_get_unaligned_uint32( x + offset );
+            break;
+        case 64:
+            r = mbedtls_get_unaligned_uint64( x + offset );
+            break;
+    }
+
+    /* Generate expected result */
+    uint64_t expected = 0;
+    for ( uint8_t i = 0; i < 8; i++ )
+    {
+        uint8_t shift;
+        if ( MBEDTLS_IS_BIG_ENDIAN )
+        {
+            /*
+            * Similar to little-endian case described below, but the shift needs
+            * to be inverted
+            */
+            shift = 7 - ( i * 8 );
+        } else {
+            /* example for offset == 1:
+            * expected = (( 1 + 0 ) << (0 * 8)) | (( 1 + 1 ) << (1 * 8)) | (( 1 + 2 ) << (2 * 8)))
+            *          = (1 << 0) | (2 << 8) | (3 << 16) ...
+            *          = 0x0807060504030201
+            * x = { 0, 1, 2, 3, ... }
+            * ie expected is the value that would be read from x on a LE system, when
+            * byte swapping is not performed
+            */
+            shift = i * 8;
+        }
+        uint64_t b = offset + i;
+        expected |= b << shift;
+    }
+
+    /* Mask out excess bits from expected result */
+    switch ( size )
+    {
+        case 16:
+            expected &= 0xffff;
+            break;
+        case 32:
+            expected &= 0xffffffff;
+            break;
+    }
+
+    TEST_EQUAL( r, expected );
+
+    /* Write sentinel to the part of the array we will testing writing to */
+    for ( size_t i = 0; i < (size_t) ( size / 8 ); i++ )
+    {
+        x[i + offset] = 0xff;
+    }
+    /*
+        * Write back to the array with mbedtls_put_unaligned_uint16 and validate
+        * that the array is unchanged as a result.
+        */
+    switch ( size )
+    {
+        case 16:
+            mbedtls_put_unaligned_uint16( x + offset, r );
+            break;
+        case 32:
+            mbedtls_put_unaligned_uint32( x + offset, r );
+            break;
+        case 64:
+            mbedtls_put_unaligned_uint64( x + offset, r );
+            break;
+    }
+    for ( size_t i = 0; i < sizeof(x); i++ )
+    {
+        TEST_EQUAL( x[i], (uint8_t)i );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_byteswap( char* input_str, int size, char *expected_str )
+{
+    uint64_t input, expected;
+    TEST_ASSERT( parse_hex_string( input_str, &input ) );
+    TEST_ASSERT( parse_hex_string( expected_str, &expected ) );
+
+    /* Check against expected result */
+    uint64_t r = 0;
+    switch ( size )
+    {
+        case 16:
+            r = MBEDTLS_BSWAP16( input );
+            break;
+        case 32:
+            r = MBEDTLS_BSWAP32( input );
+            break;
+        case 64:
+            r = MBEDTLS_BSWAP64( input );
+            break;
+        default:
+            TEST_ASSERT( ! "size must be 16, 32 or 64" );
+    }
+    TEST_EQUAL( r, expected );
+
+    /*
+     * Check byte by byte by extracting bytes from opposite ends of
+     * input and r.
+     */
+    for ( size_t i = 0; i < (size_t)( size / 8 ); i++ )
+    {
+        size_t s1 = i * 8;
+        size_t s2 = ( ( size / 8 - 1 ) - i ) * 8;
+        uint64_t a = ( input & ( (uint64_t)0xff << s1 ) ) >> s1;
+        uint64_t b = ( r & ( (uint64_t)0xff << s2 ) ) >> s2;
+        TEST_EQUAL( a, b );
+    }
+
+    /* Check BSWAP(BSWAP(x)) == x */
+    switch ( size )
+    {
+        case 16:
+            r = MBEDTLS_BSWAP16( r );
+            TEST_EQUAL( r, input & 0xffff );
+            break;
+        case 32:
+            r = MBEDTLS_BSWAP32( r );
+            TEST_EQUAL( r, input & 0xffffffff );
+            break;
+        case 64:
+            r = MBEDTLS_BSWAP64( r );
+            TEST_EQUAL( r, input );
+            break;
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_byte()
+{
+    uint8_t data[16];
+
+    for ( size_t i = 0; i < sizeof(data); i++ )
+        data[i] = (uint8_t) i;
+
+    uint64_t u64 = 0x0706050403020100;
+    for ( size_t b = 0; b < 8 ; b++ )
+    {
+        uint8_t expected = b;
+        uint8_t actual = b + 1;
+        switch ( b )
+        {
+            case 0:
+                actual = MBEDTLS_BYTE_0( u64 );
+                break;
+            case 1:
+                actual = MBEDTLS_BYTE_1( u64 );
+                break;
+            case 2:
+                actual = MBEDTLS_BYTE_2( u64 );
+                break;
+            case 3:
+                actual = MBEDTLS_BYTE_3( u64 );
+                break;
+            case 4:
+                actual = MBEDTLS_BYTE_4( u64 );
+                break;
+            case 5:
+                actual = MBEDTLS_BYTE_5( u64 );
+                break;
+            case 6:
+                actual = MBEDTLS_BYTE_6( u64 );
+                break;
+            case 7:
+                actual = MBEDTLS_BYTE_7( u64 );
+                break;
+        }
+        TEST_EQUAL( actual, expected );
+    }
+
+    uint32_t u32 = 0x03020100;
+    for ( size_t b = 0; b < 4 ; b++ )
+    {
+        uint8_t expected = b;
+        uint8_t actual = b + 1;
+        switch ( b )
+        {
+            case 0:
+                actual = MBEDTLS_BYTE_0( u32 );
+                break;
+            case 1:
+                actual = MBEDTLS_BYTE_1( u32 );
+                break;
+            case 2:
+                actual = MBEDTLS_BYTE_2( u32 );
+                break;
+            case 3:
+                actual = MBEDTLS_BYTE_3( u32 );
+                break;
+        }
+        TEST_EQUAL( actual, expected );
+    }
+
+    uint16_t u16 = 0x0100;
+    for ( size_t b = 0; b < 2 ; b++ )
+    {
+        uint8_t expected = b;
+        uint8_t actual = b + 1;
+        switch ( b )
+        {
+            case 0:
+                actual = MBEDTLS_BYTE_0( u16 );
+                break;
+            case 1:
+                actual = MBEDTLS_BYTE_1( u16 );
+                break;
+        }
+        TEST_EQUAL( actual, expected );
+    }
+
+    uint8_t u8 = 0x01;
+    uint8_t actual = MBEDTLS_BYTE_0( u8 );
+    TEST_EQUAL( actual, u8 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void unaligned_access_endian_aware(int size, int offset, int big_endian )
+{
+    TEST_ASSERT( size == 16 || size == 24 || size == 32 || size == 64 );
+    TEST_ASSERT( offset >= 0 && offset < 8 );
+
+    /* Define 64-bit aligned raw byte array */
+    uint64_t raw[2];
+    /* Populate with known data: x == { 0, 1, 2, ... } */
+    uint8_t *x = (uint8_t *) raw;
+    for ( size_t i = 0; i < sizeof(raw); i++ )
+        x[i] = (uint8_t) i;
+
+    uint64_t read = 0;
+    if ( big_endian )
+    {
+        switch ( size )
+        {
+            case 16:
+                read = MBEDTLS_GET_UINT16_BE( x, offset );
+                break;
+            case 24:
+                read = MBEDTLS_GET_UINT24_BE( x, offset );
+                break;
+            case 32:
+                read = MBEDTLS_GET_UINT32_BE( x, offset );
+                break;
+            case 64:
+                read = MBEDTLS_GET_UINT64_BE( x, offset );
+                break;
+        }
+    }
+    else
+    {
+        switch ( size )
+        {
+            case 16:
+                read = MBEDTLS_GET_UINT16_LE( x, offset );
+                break;
+            case 24:
+                read = MBEDTLS_GET_UINT24_LE( x, offset );
+                break;
+            case 32:
+                read = MBEDTLS_GET_UINT32_LE( x, offset );
+                break;
+            case 64:
+                read = MBEDTLS_GET_UINT64_LE( x, offset );
+                break;
+        }
+    }
+
+    /* Build up expected value byte by byte, in either big or little endian format */
+    uint64_t expected = 0;
+    for ( size_t i = 0; i < (size_t)(size / 8); i++ )
+    {
+        uint64_t b = x[i + offset];
+        uint8_t shift = (big_endian) ? (8 * ((size / 8 - 1) - i)) : (8 * i);
+        expected |= b << shift;
+    }
+
+    /* Verify read */
+    TEST_EQUAL( read, expected );
+
+    /* Test writing back to memory. First write sentiel */
+    for ( size_t i = 0; i < (size_t)(size / 8); i++ )
+    {
+        x[i + offset] = 0xff;
+    }
+    /* Overwrite sentinel with endian-aware write macro */
+    if ( big_endian )
+    {
+        switch ( size )
+        {
+            case 16:
+                MBEDTLS_PUT_UINT16_BE( read, x, offset );
+                break;
+            case 24:
+                MBEDTLS_PUT_UINT24_BE( read, x, offset );
+                break;
+            case 32:
+                MBEDTLS_PUT_UINT32_BE( read, x, offset );
+                break;
+            case 64:
+                MBEDTLS_PUT_UINT64_BE( read, x, offset );
+                break;
+        }
+    }
+    else
+    {
+        switch ( size )
+        {
+            case 16:
+                MBEDTLS_PUT_UINT16_LE( read, x, offset );
+                break;
+                case 24:
+                MBEDTLS_PUT_UINT24_LE( read, x, offset );
+                break;
+            case 32:
+                MBEDTLS_PUT_UINT32_LE( read, x, offset );
+                break;
+            case 64:
+                MBEDTLS_PUT_UINT64_LE( read, x, offset );
+                break;
+        }
+    }
+
+    /* Verify write - check memory is correct */
+    for ( size_t i = 0; i < sizeof(raw); i++ )
+        TEST_EQUAL( x[i], (uint8_t) i );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_is_big_endian()
+{
+    uint16_t check = 0x1234;
+    uint8_t* p = (uint8_t*) &check;
+
+    if ( MBEDTLS_IS_BIG_ENDIAN )
+    {
+        /* Big-endian: data stored MSB first, i.e. p == { 0x12, 0x34 } */
+        TEST_EQUAL( p[0], 0x12 );
+        TEST_EQUAL( p[1], 0x34 );
+    }
+    else
+    {
+        /* Little-endian: data stored LSB first, i.e. p == { 0x34, 0x12 } */
+        TEST_EQUAL( p[0], 0x34 );
+        TEST_EQUAL( p[1], 0x12 );
+    }
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function
index b64127a..7bf03fb 100644
--- a/tests/suites/test_suite_bignum_core.function
+++ b/tests/suites/test_suite_bignum_core.function
@@ -1097,6 +1097,12 @@
 
     TEST_EQUAL( 0, memcmp( X, Y, N_limbs * sizeof( mbedtls_mpi_uint ) ) );
 
+    /* Check when output aliased to input */
+
+    mbedtls_mpi_core_exp_mod( A, A, N, N_limbs, E, E_limbs, R2, T );
+
+    TEST_EQUAL( 0, memcmp( X, A, N_limbs * sizeof( mbedtls_mpi_uint ) ) );
+
 exit:
     mbedtls_free( T );
     mbedtls_free( A );
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index c7decf0..83e1f54 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -349,6 +349,75 @@
 
 /* BEGIN MERGE SLOT 3 */
 
+/* BEGIN_CASE */
+void mpi_mod_raw_inv_prime( char * input_N, char * input_A, char * input_X )
+{
+    mbedtls_mpi_uint *A = NULL;
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *X = NULL;
+    size_t A_limbs, N_limbs, X_limbs;
+    mbedtls_mpi_uint *Y = NULL;
+    mbedtls_mpi_uint *T = NULL;
+    const mbedtls_mpi_uint *R2 = NULL;
+
+    /* Legacy MPIs for computing R2 */
+    mbedtls_mpi N_mpi;  /* gets set up manually, aliasing N, so no need to free */
+    mbedtls_mpi R2_mpi;
+    mbedtls_mpi_init( &R2_mpi );
+
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &N_limbs, input_N ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+    ASSERT_ALLOC( Y, N_limbs );
+
+    TEST_EQUAL( A_limbs, N_limbs );
+    TEST_EQUAL( X_limbs, N_limbs );
+
+    N_mpi.s = 1;
+    N_mpi.p = N;
+    N_mpi.n = N_limbs;
+    TEST_EQUAL( 0, mbedtls_mpi_core_get_mont_r2_unsafe( &R2_mpi, &N_mpi ) );
+    TEST_EQUAL( 0, mbedtls_mpi_grow( &R2_mpi, N_limbs ) );
+    R2 = R2_mpi.p;
+
+    size_t working_limbs = mbedtls_mpi_mod_raw_inv_prime_working_limbs( N_limbs );
+
+    /* No point exactly duplicating the code in mbedtls_mpi_mod_raw_inv_prime_working_limbs()
+     * to see if the output is correct, but we can check that it's in a
+     * reasonable range.  The current calculation works out as
+     * `1 + N_limbs * (welem + 4)`, where welem is the number of elements in
+     * the window (1 << 1 up to 1 << 6).
+     */
+    size_t min_expected_working_limbs = 1 + N_limbs * 5;
+    size_t max_expected_working_limbs = 1 + N_limbs * 68;
+
+    TEST_LE_U( min_expected_working_limbs, working_limbs );
+    TEST_LE_U( working_limbs, max_expected_working_limbs );
+
+    ASSERT_ALLOC( T, working_limbs );
+
+    mbedtls_mpi_mod_raw_inv_prime( Y, A, N, N_limbs, R2, T );
+
+    TEST_EQUAL( 0, memcmp( X, Y, N_limbs * sizeof( mbedtls_mpi_uint ) ) );
+
+    /* Check when output aliased to input */
+
+    mbedtls_mpi_mod_raw_inv_prime( A, A, N, N_limbs, R2, T );
+
+    TEST_EQUAL( 0, memcmp( X, A, N_limbs * sizeof( mbedtls_mpi_uint ) ) );
+
+exit:
+    mbedtls_free( T );
+    mbedtls_free( A );
+    mbedtls_free( N );
+    mbedtls_free( X );
+    mbedtls_free( Y );
+    mbedtls_mpi_free( &R2_mpi );
+    // R2 doesn't need to be freed as it is only aliasing R2_mpi
+    // N_mpi doesn't need to be freed as it is only aliasing N
+}
+/* END_CASE */
+
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
@@ -526,6 +595,60 @@
     mbedtls_free( X );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_raw_neg( char * input_N, char * input_A, char * input_X )
+{
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *A = NULL;
+    mbedtls_mpi_uint *X = NULL;
+    mbedtls_mpi_uint *R = NULL;
+    mbedtls_mpi_uint *Z = NULL;
+    size_t n_limbs, a_limbs, x_limbs, bytes;
+
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_modulus_init( &m );
+
+    /* Read inputs */
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &a_limbs, input_A ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &x_limbs, input_X ) );
+
+    TEST_EQUAL( a_limbs, n_limbs );
+    TEST_EQUAL( x_limbs, n_limbs );
+    bytes = n_limbs * sizeof( mbedtls_mpi_uint );
+
+    ASSERT_ALLOC( R, n_limbs );
+    ASSERT_ALLOC( Z, n_limbs );
+
+    TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
+            MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+    /* Neg( A == 0 ) => Zero result */
+    mbedtls_mpi_mod_raw_neg( R, Z, &m );
+    ASSERT_COMPARE( R, bytes, Z, bytes );
+
+    /* Neg( A == N ) => Zero result */
+    mbedtls_mpi_mod_raw_neg( R, N, &m );
+    ASSERT_COMPARE( R, bytes, Z, bytes );
+
+    /* Neg( A ) => Correct result */
+    mbedtls_mpi_mod_raw_neg( R, A, &m );
+    ASSERT_COMPARE( R, bytes, X, bytes );
+
+    /* Neg( A ): alias A to R => Correct result */
+    mbedtls_mpi_mod_raw_neg( A, A, &m );
+    ASSERT_COMPARE( A, bytes, X, bytes );
+exit:
+    mbedtls_mpi_mod_modulus_free( &m );
+    mbedtls_free( N );
+    mbedtls_free( A );
+    mbedtls_free( X );
+    mbedtls_free( R );
+    mbedtls_free( Z );
+}
+/* END_CASE */
+
 /* END MERGE SLOT 7 */
 
 /* BEGIN MERGE SLOT 8 */
diff --git a/tests/suites/test_suite_common.data b/tests/suites/test_suite_common.data
new file mode 100644
index 0000000..500852d
--- /dev/null
+++ b/tests/suites/test_suite_common.data
@@ -0,0 +1,20 @@
+Block xor, length 0
+mbedtls_xor:0
+
+Block xor, length 1
+mbedtls_xor:1
+
+Block xor, length 3
+mbedtls_xor:3
+
+Block xor, length 4
+mbedtls_xor:4
+
+Block xor, length 7
+mbedtls_xor:7
+
+Block xor, length 8
+mbedtls_xor:8
+
+Block xor, length 16
+mbedtls_xor:16
diff --git a/tests/suites/test_suite_common.function b/tests/suites/test_suite_common.function
new file mode 100644
index 0000000..4444a52
--- /dev/null
+++ b/tests/suites/test_suite_common.function
@@ -0,0 +1,90 @@
+/* BEGIN_HEADER */
+#include "../library/common.h"
+
+void fill_arrays( unsigned char *a, unsigned char *b, unsigned char *r1, unsigned char *r2, size_t n )
+{
+    for ( size_t i = 0; i < n; i++ )
+    {
+        a[i]  = (unsigned char) i * 3;
+        b[i]  = (unsigned char) i * 3 + 1;
+        r1[i] = (unsigned char) i * 3 + 2;
+        r2[i] = r1[i];
+    }
+}
+/* END_HEADER */
+
+/* BEGIN_CASE */
+void mbedtls_xor( int len )
+{
+    size_t n = (size_t) len;
+    unsigned char *a = NULL, *b = NULL, *r1 = NULL, *r2 = NULL;
+    ASSERT_ALLOC( a, n + 1 );
+    ASSERT_ALLOC( b, n + 1 );
+    ASSERT_ALLOC( r1, n + 1 );
+    ASSERT_ALLOC( r2, n + 1 );
+
+    /* Test non-overlapping */
+    fill_arrays( a, b, r1, r2, n );
+    for ( size_t i = 0; i < n; i++ )
+    {
+        r1[i] = a[i] ^ b[i];
+    }
+    mbedtls_xor( r2, a, b, n );
+    ASSERT_COMPARE( r1, n, r2, n );
+
+    /* Test r == a */
+    fill_arrays( a, b, r1, r2, n );
+    for ( size_t i = 0; i < n; i++ )
+    {
+        r1[i] = r1[i] ^ b[i];
+    }
+    mbedtls_xor( r2, r2, b, n );
+    ASSERT_COMPARE( r1, n, r2, n );
+
+    /* Test r == b */
+    fill_arrays( a, b, r1, r2, n );
+    for ( size_t i = 0; i < n; i++ )
+    {
+        r1[i] = a[i] ^ r1[i];
+    }
+    mbedtls_xor( r2, a, r2, n );
+    ASSERT_COMPARE( r1, n, r2, n );
+
+    /* Test a == b */
+    fill_arrays( a, b, r1, r2, n );
+    for ( size_t i = 0; i < n; i++ )
+    {
+        r1[i] = a[i] ^ a[i];
+    }
+    mbedtls_xor( r2, a, a, n );
+    ASSERT_COMPARE( r1, n, r2, n );
+
+    /* Test a == b == r */
+    fill_arrays( a, b, r1, r2, n );
+    for ( size_t i = 0; i < n; i++ )
+    {
+        r1[i] = r1[i] ^ r1[i];
+    }
+    mbedtls_xor( r2, r2, r2, n );
+    ASSERT_COMPARE( r1, n, r2, n );
+
+    /* Test non-word-aligned buffers, for all combinations of alignedness */
+    for ( int i = 0; i < 7; i++ )
+    {
+        int r_off = i & 1, a_off = (i & 2) >> 1, b_off = (i & 4) >> 2;
+        fill_arrays( a, b, r1, r2, n + 1 );
+
+        for ( size_t j = 0; j < n; j++ )
+        {
+            r1[j + r_off] = a[j + a_off] ^ b[j + b_off];
+        }
+        mbedtls_xor( r2 + r_off, a + a_off, b + b_off, n );
+        ASSERT_COMPARE( r1 + r_off, n, r2 + r_off, n );
+    }
+exit:
+    mbedtls_free( a );
+    mbedtls_free( b );
+    mbedtls_free( r1 );
+    mbedtls_free( r2 );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index a7f0501..1b5e44b 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -3539,3 +3539,11 @@
 
 TLS 1.3 srv Certificate msg - wrong vector lengths
 tls13_server_certificate_msg_invalid_vector_len
+
+EC-JPAKE set password
+depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+ssl_ecjpake_set_password:0
+
+EC-JPAKE set opaque password
+depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+ssl_ecjpake_set_password:1
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 674e649..95fa8ef 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -2582,6 +2582,21 @@
     return( 0 );
 }
 #endif /* MBEDTLS_TEST_HOOKS */
+
+#define ECJPAKE_TEST_PWD        "bla"
+
+#if defined( MBEDTLS_USE_PSA_CRYPTO )
+#define ECJPAKE_TEST_SET_PASSWORD( exp_ret_val )                          \
+    ret = ( use_opaque_arg ) ?                                            \
+        mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl, pwd_slot ) :    \
+        mbedtls_ssl_set_hs_ecjpake_password( &ssl, pwd_string, pwd_len ); \
+    TEST_EQUAL( ret, exp_ret_val )
+#else
+#define ECJPAKE_TEST_SET_PASSWORD( exp_ret_val )                \
+    ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl,            \
+                                        pwd_string, pwd_len );  \
+    TEST_EQUAL( ret, exp_ret_val )
+#endif
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -5997,3 +6012,85 @@
     USE_PSA_DONE( );
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+void ssl_ecjpake_set_password( int use_opaque_arg )
+{
+    mbedtls_ssl_context ssl;
+    mbedtls_ssl_config conf;
+#if defined( MBEDTLS_USE_PSA_CRYPTO )
+    mbedtls_svc_key_id_t pwd_slot = MBEDTLS_SVC_KEY_ID_INIT;
+#else   /* MBEDTLS_USE_PSA_CRYPTO */
+    (void) use_opaque_arg;
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
+    unsigned char pwd_string[ sizeof(ECJPAKE_TEST_PWD) ] = "";
+    size_t pwd_len = 0;
+    int ret;
+
+    USE_PSA_INIT( );
+
+    mbedtls_ssl_init( &ssl );
+
+    /* test with uninitalized SSL context */
+    ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+    mbedtls_ssl_config_init( &conf );
+
+    TEST_EQUAL( mbedtls_ssl_config_defaults( &conf,
+                                              MBEDTLS_SSL_IS_CLIENT,
+                                              MBEDTLS_SSL_TRANSPORT_STREAM,
+                                              MBEDTLS_SSL_PRESET_DEFAULT ), 0 );
+
+    TEST_EQUAL( mbedtls_ssl_setup( &ssl, &conf ), 0 );
+
+    /* test with empty password or unitialized password key (depending on use_opaque_arg) */
+    ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+    pwd_len = strlen( ECJPAKE_TEST_PWD );
+    memcpy( pwd_string, ECJPAKE_TEST_PWD, pwd_len );
+
+#if defined( MBEDTLS_USE_PSA_CRYPTO )
+    if( use_opaque_arg )
+    {
+        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+        psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+        /* First try with an invalid usage */
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
+        psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE );
+        psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD );
+
+        PSA_ASSERT( psa_import_key( &attributes, pwd_string,
+                    pwd_len, &pwd_slot ) );
+
+        ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+        /* check that the opaque key is still valid after failure */
+        TEST_EQUAL( psa_get_key_attributes( pwd_slot, &check_attributes ),
+                        PSA_SUCCESS );
+
+        psa_destroy_key( pwd_slot );
+
+        /* Then set the correct usage */
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+
+        PSA_ASSERT( psa_import_key( &attributes, pwd_string,
+                    pwd_len, &pwd_slot ) );
+    }
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
+
+    /* final check which should work without errors */
+    ECJPAKE_TEST_SET_PASSWORD( 0 );
+
+#if defined( MBEDTLS_USE_PSA_CRYPTO )
+    if( use_opaque_arg )
+    {
+        psa_destroy_key( pwd_slot );
+    }
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
+    mbedtls_ssl_free( &ssl );
+    mbedtls_ssl_config_free( &conf );
+
+    USE_PSA_DONE( );
+}
+/* END_CASE */